2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
5 Loader for shared libraries and devices.
8 #include <exec/execbase.h>
9 #include <exec/resident.h>
10 #include <exec/memory.h>
11 #include <exec/errors.h>
12 #include <exec/libraries.h>
13 #include <exec/devices.h>
14 #include <exec/ports.h>
15 #include <exec/lists.h>
16 #include <exec/alerts.h>
17 #include <exec/tasks.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <aros/asmcall.h>
23 #include <aros/debug.h>
25 #include <proto/exec.h>
26 #include <proto/dos.h>
27 #include "dos_intern.h"
28 #include LC_LIBDEFS_FILE
34 #define CHECK_DEPENDENCY 1
36 /* Please leave them here! They are needed on Linux-M68K */
37 AROS_LD2(struct Library
*, OpenLibrary
,
38 AROS_LDA(STRPTR
, libname
, A1
),
39 AROS_LDA(ULONG
, version
, D0
),
40 struct ExecBase
*, SysBase
, 0, Dos
);
41 AROS_LD4(BYTE
, OpenDevice
,
42 AROS_LDA(STRPTR
, devname
, A0
),
43 AROS_LDA(ULONG
, unitNumber
, D0
),
44 AROS_LDA(struct IORequest
*, iORequest
, A1
),
45 AROS_LDA(ULONG
, flags
, D1
),
46 struct ExecBase
*, SysBase
, 0, Dos
);
47 AROS_LD1(void, CloseLibrary
,
48 AROS_LDA(struct Library
*, library
, A1
),
49 struct ExecBase
*, SysBase
, 0, Dos
);
50 AROS_LD1(void, CloseDevice
,
51 AROS_LDA(struct IORequest
*, iORequest
, A1
),
52 struct ExecBase
*, SysBase
, 0, Dos
);
53 AROS_LD1(void, RemLibrary
,
54 AROS_LDA(struct Library
*, library
, A1
),
55 struct ExecBase
*, SysBase
, 0, Dos
);
59 struct Message ldd_Msg
; /* Message link */
60 struct MsgPort ldd_ReplyPort
; /* Callers ReplyPort */
62 STRPTR ldd_Name
; /* Name of thing to load */
63 ULONG ldd_Version
; /* Version of thing to load */
65 STRPTR ldd_BaseDir
; /* Base directory to load from */
66 struct Library
* ldd_Return
; /* The result */
72 #define LIBEND LDDemon_end
74 #include <libcore/compiler.h>
76 static const char name
[];
77 static const char version
[];
78 extern const int LIBEND TEXT_SECTION
;
79 static ULONG
AROS_SLIB_ENTRY(Init
, LDDemon
)();
81 const struct Resident LDDemon_resident
=
84 (struct Resident
*)&LDDemon_resident
,
92 AROS_SLIB_ENTRY(Init
,LDDemon
)
95 static const char name
[] = "LDDemon";
96 static const char version
[] = "$VER: LDDemon 41.3 (11.3.2007)\r\n";
97 static const char ldDemonName
[] = "Lib & Dev Loader Daemon";
100 BPTR LDLoad( caller, name, basedir, DOSBase )
101 Try and load a segment from disk for the object <name>, relative
102 to directory <basedir>. Will also try <caller>'s current and home
107 struct Process
*caller
,
110 struct DosLibrary
*DOSBase
113 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
114 struct Process
*me
= (struct Process
*)FindTask(NULL
);
121 If the caller was a process, we have more scope for loading
122 libraries. We can load them from the callers current directory,
123 or from the PROGDIR: assign. These could both be the same
127 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
128 caller
, caller
->pr_Task
.tc_Node
.ln_Name
, name
, basedir
131 if (strncmp(name
, "PROGDIR:", 8) == 0)
133 /* Special case for explicit PROGDIR-based path */
134 if (__is_process(caller
))
136 if (caller
->pr_HomeDir
!= NULL
)
138 BPTR oldHomeDir
= me
->pr_HomeDir
;
139 D(bug("[LDLoad] Trying homedir\n"));
140 /* Temporarily override pr_HomeDir to let GetDeviceProc handle
141 PROGDIR: case correctly while opening library file */
142 me
->pr_HomeDir
= caller
->pr_HomeDir
;
143 seglist
= LoadSeg(name
);
144 me
->pr_HomeDir
= oldHomeDir
;
148 else if (!strstr(name
, ":")) {
149 delimPos
= strlen(basedir
);
150 pathLen
= delimPos
+ strlen(name
) + 2;
151 path
= AllocMem(pathLen
, MEMF_ANY
);
153 strcpy(path
, basedir
);
154 path
[delimPos
] = '/';
155 strcpy(&path
[delimPos
+ 1], name
);
157 if (__is_process(caller
))
159 /* Try the current directory of the caller */
161 D(bug("[LDLoad] Process\n"));
162 me
->pr_CurrentDir
= caller
->pr_CurrentDir
;
163 D(bug("[LDLoad] Trying currentdir\n"));
164 seglist
= LoadSeg(name
);
165 if ((!seglist
) && path
)
166 seglist
= LoadSeg(path
);
168 /* The the program directory of the caller */
169 if((!seglist
) && (caller
->pr_HomeDir
!= NULL
))
171 D(bug("[LDLoad] Trying homedir\n"));
172 me
->pr_CurrentDir
= caller
->pr_HomeDir
;
173 seglist
= LoadSeg(name
);
174 if ((!seglist
) && path
)
175 seglist
= LoadSeg(path
);
181 /* Nup, lets try the default directory as supplied. */
182 D(bug("[LDLoad] Trying defaultir\n"));
183 path
[delimPos
] = ':';
184 seglist
= LoadSeg(path
);
186 FreeMem(path
, pathLen
);
189 seglist
=LoadSeg(name
);
195 Library *LDInit(seglist, DOSBase)
196 Initialise the library.
198 static struct Library
*
199 LDInit(BPTR seglist
, struct DosLibrary
*DOSBase
)
201 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
206 STRPTR addr
= (STRPTR
)((IPTR
)BADDR(seg
)-sizeof(ULONG
));
207 ULONG size
= *(ULONG
*)addr
;
210 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
211 size
-= sizeof(BPTR
) + sizeof(ULONG
);
212 size
>= sizeof(struct Resident
) ;
214 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
217 struct Resident
*res
= (struct Resident
*)addr
;
218 if( res
->rt_MatchWord
== RTC_MATCHWORD
219 && res
->rt_MatchTag
== res
)
223 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
225 lib
= InitResident(res
, seglist
);
227 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
233 seg
= *(BPTR
*)BADDR(seg
);
235 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist
));
240 struct Library
*(*__OpenLibrary
)();
241 BYTE (*__OpenDevice
)();
243 #define ExecOpenLibrary(libname, version) \
244 AROS_CALL2(struct Library *, __OpenLibrary, \
245 AROS_LCA(STRPTR, libname, A1), \
246 AROS_LCA(ULONG, version, D0), \
247 struct ExecBase *, SysBase)
249 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
250 AROS_CALL4(BYTE, __OpenDevice, \
251 AROS_LCA(STRPTR, devname, A0), \
252 AROS_LCA(ULONG, unitNumber, D0), \
253 AROS_LCA(struct IORequest *, iORequest, A1), \
254 AROS_LCA(ULONG, flags, D1), \
255 struct ExecBase *, SysBase)
258 struct Library *AROS_SLIB_ENTRY(OpenLibrary, Exec)();
259 BYTE AROS_SLIB_ENTRY(OpenDevice, Exec)();
261 #define ExecOpenLibrary(libname, version) \
262 AROS_CALL2(struct Library *, &AROS_SLIB_ENTRY(OpenLibrary, Exec), \
263 AROS_LCA(STRPTR, libname, A1), \
264 AROS_LCA(ULONG, version, D0), \
265 struct ExecBase *, SysBase)
267 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
268 AROS_CALL4(BYTE, &AROS_SLIB_ENTRY(OpenDevice, Exec), \
269 AROS_LCA(STRPTR, devname, A0), \
270 AROS_LCA(ULONG, unitNumber, D0), \
271 AROS_LCA(struct IORequest *, iORequest, A1), \
272 AROS_LCA(ULONG, flags, D1), \
273 struct ExecBase *, SysBase)
278 struct Node ldon_Node
;
279 struct SignalSemaphore ldon_SigSem
;
280 ULONG ldon_AccessCount
;
282 struct Task
*ldon_FirstLocker
;
286 struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct DosLibrary
*DOSBase
)
288 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
290 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
293 ULONG len
= strlen(name
);
294 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
297 CopyMem(name
, dupname
, len
);
299 ret
->ldon_Node
.ln_Name
= dupname
;
300 InitSemaphore(&ret
->ldon_SigSem
);
301 ret
->ldon_AccessCount
= 0;
304 ret
->ldon_FirstLocker
= FindTask(0);
315 VOID
LDDestroyObjectNode(struct LDObjectNode
*object
, struct DosLibrary
*DOSBase
)
317 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
319 FreeVec(object
->ldon_Node
.ln_Name
);
323 AROS_LH2(struct Library
*, OpenLibrary
,
324 AROS_LHA(STRPTR
, libname
, A1
),
325 AROS_LHA(ULONG
, version
, D0
),
326 struct ExecBase
*, SysBase
, 0, Dos
)
330 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
331 struct Library
*library
, *tmplib
;
332 STRPTR stripped_libname
;
333 struct LDObjectNode
*object
;
336 We get the DOS semaphore to prevent the following:
337 - task 1 tries to open foobar.library, needs to load it from disk...
338 - task 1 Permit()'s (since its not doing list things)
339 - task switch (whilst LDDemon MAY get process next it might not)
340 - task 2 tries to open foobar.library, needs to load it from disk...
341 - it also requests LDDemon to open foobar.library, so it is now
342 trying to open it twice
344 We block all OpenLibrary() callers from searching the list until
345 all the other OpenLibrary() callers have returned. That way,
346 task #2 won't ask for foobar.library until task #1 has got its
347 response back from the LDDemon process.
349 falemagn: I changed the implementation of all that.
350 There's a list of "LDObjectNodes", that contain the name
351 of the object being opened. Since the problem is that more
352 processes can attempt to open the same device/library Instead of
353 locking a global semaphore until the opening is done, we lock a
354 per-object semaphore, so that others libraries/devices can be opened
355 in the meantime. Before a deadlock could happen if there was a
358 Process A opens L --------> LDDemon loads L and locks sem S
364 L spawns a process B and ----------> The process opens
365 waits for it to respond a library but gets loked
366 to a message <----/---- because sem S is locked
373 Hopefully this won't happen anymore now.
377 /* We use FilePart() because the liblist is built from resident IDs,
378 and contain no path. Eg. The user can request gadgets/foo.gadget,
379 but the resident only contains foo.gadget
381 stripped_libname
= FilePart(libname
);
382 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
383 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_libname
);
386 object
= LDNewObjectNode(stripped_libname
, DOSBase
);
389 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
395 object
->ldon_AccessCount
+= 1;
400 struct Task
*curtask
= FindTask(0);
401 struct ETask
*et
= GetETask(curtask
);
403 D(bug("Checking for circular dependency\n"));
406 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
407 curtask
= et
->et_Parent
;
411 bug("Circular dependency found!\n");
417 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
423 ObtainSemaphore(&object
->ldon_SigSem
);
425 /* Call the EXEC's OpenLibrary function */
426 library
= ExecOpenLibrary(stripped_libname
, version
);
428 if( library
== NULL
)
430 /* Use stack for now, this could be a security hole */
433 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
434 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
435 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
436 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
437 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
439 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
441 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
442 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
444 ldd
.ldd_Name
= libname
;
445 ldd
.ldd_Version
= version
;
446 ldd
.ldd_BaseDir
= "libs";
448 SetSignal(0, SIGF_SINGLE
);
449 D(bug("[LDCaller] Sending request for %s v%ld\n", libname
, version
));
450 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
451 WaitPort(&ldd
.ldd_ReplyPort
);
452 D(bug("[LDCaller] Returned\n"));
454 library
= LDInit(ldd
.ldd_Return
, DOSBase
);
456 if( library
!= NULL
)
459 We have to Forbid() here because we need to look through the list
460 again, we also need to call the libOpen vector, which wants us
461 under a Forbidden state.
463 falemagn: well, it doesn't want us under a Forbidden state, it just
464 wants to be single threaded, and it is, in fact, so no
465 need for Forbid()/Permit() around open. I Hope... :)
469 tmplib
= (struct Library
*)FindName(&SysBase
->LibList
, stripped_libname
);
475 if(library
->lib_Version
>= version
)
477 D(bug("[LDCaller] Calling libOpen() of %s\n",
478 library
->lib_Node
.ln_Name
));
480 library
= AROS_LVO_CALL1(struct Library
*,
481 AROS_LCA(ULONG
, version
, D0
),
482 struct Library
*, library
, 1,
485 D(bug("[LDCaller] libOpen() returned\n"));
495 the library is not on disk so
499 struct Resident
*resident
;
501 resident
= FindResident(stripped_libname
);
504 if (resident
->rt_Version
>= version
)
506 if (InitResident(resident
, NULL
))
507 library
= ExecOpenLibrary(stripped_libname
, version
);
513 Release the semaphore here, after calling Open vector. This
514 means that library open is singlethreaded by the semaphore.
515 It also handles circular dependant libraries. (Won't deadlock),
516 and recursive OpenLibrary calls (Semaphores nest when obtained
517 several times in a row by the same task).
519 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
520 if (--(object
->ldon_AccessCount
) == 0)
522 Remove((struct Node
*)object
);
523 LDDestroyObjectNode(object
, DOSBase
);
526 ReleaseSemaphore(&object
->ldon_SigSem
);
527 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
534 AROS_LH4(BYTE
, OpenDevice
,
535 AROS_LHA(STRPTR
, devname
, A0
),
536 AROS_LHA(ULONG
, unitNumber
, D0
),
537 AROS_LHA(struct IORequest
*, iORequest
, A1
),
538 AROS_LHA(ULONG
, flags
, D1
),
539 struct ExecBase
*, SysBase
, 0, Dos
)
543 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
544 struct Device
*tmpdev
;
545 STRPTR stripped_devname
;
546 struct LDObjectNode
*object
;
548 iORequest
->io_Error
= IOERR_OPENFAIL
;
549 iORequest
->io_Device
= NULL
;
551 /* We use FilePart() because the liblist is built from resident IDs,
552 which contain no path. Eg. The user can request gadgets/foo.gadget,
553 but the resident only contains foo.gadget
556 stripped_devname
= FilePart(devname
);
558 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
559 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_devname
);
563 object
= LDNewObjectNode(stripped_devname
, DOSBase
);
566 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
572 object
->ldon_AccessCount
+= 1;
577 struct Task
*curtask
= FindTask(0);
578 struct ETask
*et
= GetETask(curtask
);
582 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
583 curtask
= et
->et_Parent
;
587 bug("[LDCaller] Circular dependency found!\n");
593 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
596 return IOERR_OPENFAIL
;
598 ObtainSemaphore(&object
->ldon_SigSem
);
600 ExecOpenDevice(stripped_devname
, unitNumber
, iORequest
, flags
);
602 if (iORequest
->io_Error
)
604 /* Use stack for now, this could be a security hole */
607 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
608 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
609 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
610 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
611 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
613 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
614 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
615 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
617 ldd
.ldd_Name
= devname
;
618 ldd
.ldd_BaseDir
= "devs";
620 SetSignal(0, SIGF_SINGLE
);
621 D(bug("[LDCaller] Sending request for %s\n", devname
));
622 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
623 WaitPort(&ldd
.ldd_ReplyPort
);
624 D(bug("[LDCaller] Returned\n"));
626 iORequest
->io_Device
= (struct Device
*)LDInit(ldd
.ldd_Return
, DOSBase
);
628 if(iORequest
->io_Device
)
631 tmpdev
= (struct Device
*)FindName(&SysBase
->DeviceList
, stripped_devname
);
635 iORequest
->io_Device
= tmpdev
;
637 iORequest
->io_Error
= 0;
638 iORequest
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
640 D(bug("[LDCaller] Calling devOpen() of %s unit %ld\n",
641 iORequest
->io_Device
->dd_Library
.lib_Node
.ln_Name
, unitNumber
));
643 AROS_LVO_CALL3NR(void,
644 AROS_LCA(struct IORequest
*, iORequest
, A1
),
645 AROS_LCA(ULONG
, unitNumber
, D0
),
646 AROS_LCA(ULONG
, flags
, D1
),
647 struct Device
*, iORequest
->io_Device
, 1,
650 D(bug("[LDCaller] devOpen() returned\n"));
652 if (iORequest
->io_Error
)
653 iORequest
->io_Device
= NULL
;
657 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
658 if (--(object
->ldon_AccessCount
) == 0)
660 Remove((struct Node
*)object
);
661 LDDestroyObjectNode(object
, DOSBase
);
664 ReleaseSemaphore(&object
->ldon_SigSem
);
665 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
667 D(bug("%s", iORequest
->io_Error
?"[LDCaller] Couldn't open the device\n":""));
669 return iORequest
->io_Error
;
674 AROS_LH1(void, CloseLibrary
,
675 AROS_LHA(struct Library
*, library
, A1
),
676 struct ExecBase
*, SysBase
, 0, Dos
)
680 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
683 if( library
!= NULL
)
686 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
689 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
691 /* Safe to call from a Task */
700 AROS_LH1(void, CloseDevice
,
701 AROS_LHA(struct IORequest
*, iORequest
, A1
),
702 struct ExecBase
*, SysBase
, 0, Dos
)
705 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
709 if( iORequest
->io_Device
!= NULL
)
711 seglist
= AROS_LVO_CALL1(BPTR
,
712 AROS_LCA(struct IORequest
*, iORequest
, A1
),
713 struct Device
, iORequest
->io_Device
, 2, );
714 iORequest
->io_Device
=(struct Device
*)-1;
717 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
725 AROS_LH1(void, RemLibrary
,
726 AROS_LHA(struct Library
*, library
, A1
),
727 struct ExecBase
*, SysBase
, 0, Dos
)
731 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
735 /* calling ExpungeLib: library ends up in D0 and A6 for compatibility */
736 seglist
= AROS_CALL1(BPTR
, __AROS_GETVECADDR(library
, 3),
737 AROS_LCA(struct Library
*, library
, D0
),
738 struct Library
*, library
742 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
750 AROS_UFH3(LONG
, LDFlush
,
751 AROS_UFHA(struct MemHandlerData
*, lmhd
, A0
),
752 AROS_UFHA(APTR
, data
, A1
),
753 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
758 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
759 struct Library
*library
;
761 D(bug("[LDDemon] Flush called\n"));
762 DOSBase
->dl_LDReturn
= MEM_DID_NOTHING
;
764 /* Forbid() is already done, but I don't want to rely on it. */
767 /* Follow the linked list of shared libraries. */
768 library
= (struct Library
*)SysBase
->LibList
.lh_Head
;
769 while(library
->lib_Node
.ln_Succ
!= NULL
)
771 /* Flush libraries with a 0 open count */
772 if( ! library
->lib_OpenCnt
)
774 /* the library list node will be wiped from memory */
775 struct Library
*nextLib
= (struct Library
*)library
->lib_Node
.ln_Succ
;
777 /* Did it really go away? */
778 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
780 /* Yes! Return it. */
782 return MEM_TRY_AGAIN
;
788 /* Go on to next library. */
789 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
793 /* Do the same with the device list. */
794 library
= (struct Library
*)SysBase
->DeviceList
.lh_Head
;
795 while(library
->lib_Node
.ln_Succ
!= NULL
)
797 /* Flush libraries with a 0 open count */
798 if( ! library
->lib_OpenCnt
)
800 struct Library
*nextDev
= (struct Library
*)library
->lib_Node
.ln_Succ
;
801 RemDevice((struct Device
*)library
);
802 /* Did it really go away? */
803 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
805 /* Yes! Return it. */
807 return MEM_TRY_AGAIN
;
813 /* Go on to next library. */
814 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
818 return MEM_DID_NOTHING
;
825 The LDDemon process entry. Sits around and does nothing until a
826 request for a library comes, when it will then find the library
827 and hopefully open it.
829 AROS_UFH3(void, LDDemon
,
830 AROS_UFHA(STRPTR
, argstr
, A0
),
831 AROS_UFHA(ULONG
, arglen
, D0
),
832 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
837 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
842 WaitPort(DOSBase
->dl_LDDemonPort
);
843 while( (ldd
= (struct LDDMsg
*)GetMsg(DOSBase
->dl_LDDemonPort
)) )
845 D(bug("[LDDemon] Got a request for %s in %s\n",
846 ldd
->ldd_Name
, ldd
->ldd_BaseDir
));
848 ldd
->ldd_Return
= LDLoad(
849 ldd
->ldd_ReplyPort
.mp_SigTask
,
854 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
855 ReplyMsg((struct Message
*)ldd
);
856 } /* messages available */
862 AROS_UFH3(ULONG
, AROS_SLIB_ENTRY(Init
, LDDemon
),
863 AROS_UFHA(ULONG
, dummy
, D0
),
864 AROS_UFHA(BPTR
, segList
, A0
),
865 AROS_UFHA(struct ExecBase
*, sysBase
, A6
)
870 struct DosLibrary
*DOSBase
;
871 struct TagItem tags
[] =
873 { NP_Entry
, (IPTR
)LDDemon
},
876 { NP_WindowPtr
, -1 },
877 { NP_Name
, (IPTR
)ldDemonName
},
878 { NP_StackSize
, AROS_STACKSIZE
},
882 /* We want version v41 of DOS, since it corresponds to AROS atm... */
883 if((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 41)) == NULL
)
885 Alert(AT_DeadEnd
| AN_RAMLib
| AG_OpenLib
| AO_DOSLib
);
888 SysBase
->ex_RamLibPrivate
= DOSBase
;
890 if( (DOSBase
->dl_LDDemonPort
= CreateMsgPort()) == NULL
)
892 Alert( AN_RAMLib
| AG_NoMemory
| AT_DeadEnd
);
895 FreeSignal(DOSBase
->dl_LDDemonPort
->mp_SigBit
);
896 DOSBase
->dl_LDDemonPort
->mp_SigBit
= SIGBREAKB_CTRL_F
;
898 DOSBase
->dl_LDHandler
.is_Node
.ln_Name
= (STRPTR
)ldDemonName
;
899 DOSBase
->dl_LDHandler
.is_Node
.ln_Pri
= 0;
900 DOSBase
->dl_LDHandler
.is_Code
= (void (*)())LDFlush
;
901 DOSBase
->dl_LDHandler
.is_Data
= NULL
;
903 NEWLIST(&DOSBase
->dl_LDObjectsList
);
904 InitSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
905 AddMemHandler(&DOSBase
->dl_LDHandler
);
908 * Grab the semaphore ourself. The reason for this is that it will
909 * cause all other tasks to wait until we have finished initialising
910 * before they try and open something.
912 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
914 #define SetFunc(offs,ptr) \
915 SetFunction(&SysBase->LibNode, (offs)*LIB_VECTSIZE, \
916 AROS_SLIB_ENTRY(ptr,Dos))
918 /* Do not set the vectors until you have initialised everything else. */
919 __OpenLibrary
= SetFunc(-92, OpenLibrary
);
920 __OpenDevice
= SetFunc(-74, OpenDevice
);
921 (void)SetFunc(-69, CloseLibrary
);
922 (void)SetFunc(-75, CloseDevice
);
923 (void)SetFunc(-67, RemLibrary
);
924 (void)SetFunc(-73, RemLibrary
);
926 if( !(DOSBase
->dl_LDDemonTask
= CreateNewProc((struct TagItem
*)tags
)) )
928 Alert( AT_DeadEnd
| AN_RAMLib
| AG_ProcCreate
);
931 /* Fix up the MsgPort */
933 DOSBase
->dl_LDDemonPort
->mp_SigTask
= DOSBase
->dl_LDDemonTask
;
935 /* Then unlock the semaphore to allow other processes to run. */
936 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
943 const int LIBEND TEXT_SECTION
= 1;