2 Copyright © 1995-2019, The AROS Development Team. All rights reserved.
5 Loader for shared libraries and devices.
8 #include <aros/config.h>
10 #include <aros/asmcall.h>
11 #include <aros/debug.h>
12 #include <aros/symbolsets.h>
13 #include <exec/execbase.h>
14 #include <exec/resident.h>
15 #include <exec/memory.h>
16 #include <exec/errors.h>
17 #include <exec/devices.h>
18 #include <exec/ports.h>
19 #include <exec/alerts.h>
20 #include <exec/tasks.h>
22 #include <dos/dosextens.h>
23 #include <dos/dostags.h>
24 #include <proto/exec.h>
25 #include <proto/execlock.h>
26 #include <proto/dos.h>
28 #include <proto/lddemon.h>
30 #include <resources/execlock.h>
31 #include <aros/types/spinlock_s.h>
39 #define INIT_IN_LDDEMON_CONTEXT 1
41 #define INIT_IN_LDDEMON_CONTEXT 0
44 #define CHECK_DEPENDENCY 1
46 /* Please leave them here! They are needed on Linux-M68K */
47 AROS_LD2(struct Library
*, OpenLibrary
,
48 AROS_LDA(STRPTR
, libname
, A1
),
49 AROS_LDA(ULONG
, version
, D0
),
50 struct ExecBase
*, SysBase
, 0, Lddemon
);
51 AROS_LD4(LONG
, OpenDevice
,
52 AROS_LDA(STRPTR
, devname
, A0
),
53 AROS_LDA(IPTR
, unitNumber
, D0
),
54 AROS_LDA(struct IORequest
*, iORequest
, A1
),
55 AROS_LDA(ULONG
, flags
, D1
),
56 struct ExecBase
*, SysBase
, 0, Lddemon
);
57 AROS_LD1(void, CloseLibrary
,
58 AROS_LDA(struct Library
*, library
, A1
),
59 struct ExecBase
*, SysBase
, 0, Lddemon
);
60 AROS_LD1(void, CloseDevice
,
61 AROS_LDA(struct IORequest
*, iORequest
, A1
),
62 struct ExecBase
*, SysBase
, 0, Lddemon
);
63 AROS_LD1(void, RemLibrary
,
64 AROS_LDA(struct Library
*, library
, A1
),
65 struct ExecBase
*, SysBase
, 0, Lddemon
);
69 struct Message ldd_Msg
; /* Message link */
70 struct MsgPort ldd_ReplyPort
; /* Callers ReplyPort */
72 STRPTR ldd_Name
; /* Name of thing to load */
74 STRPTR ldd_BaseDir
; /* Base directory to load from */
75 #if INIT_IN_LDDEMON_CONTEXT
76 struct Library
*ldd_Return
; /* Loaded and initialized Library */
77 struct List
*ldd_List
; /* List to add */
79 BPTR ldd_Return
; /* Loaded seglist */
83 static const char ldDemonName
[] = "Lib & Dev Loader Daemon";
88 AROS_LH1(BPTR
, LDLoadSeg
,
89 AROS_LHA(CONST_STRPTR
, name
, D1
),
90 struct IntLDDemonBase
*, ldBase
, 1, Lddemon
)
93 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
94 D(bug("[LDLoadSeg] name=%s\n", name
));
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
105 static BPTR
LDLoad(struct IntLDDemonBase
*ldBase
, struct Process
*caller
, STRPTR name
, STRPTR basedir
, struct ExecBase
*SysBase
)
107 struct Process
*me
= (struct Process
*)FindTask(NULL
);
108 BPTR seglist
= BNULL
;
114 If the caller was a process, we have more scope for loading
115 libraries. We can load them from the caller's current directory,
116 or from the PROGDIR: assign. These could both be the same
120 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
121 caller
, caller
->pr_Task
.tc_Node
.ln_Name
, name
, basedir
124 if (strncmp(name
, "PROGDIR:", 8) == 0)
126 /* Special case for explicit PROGDIR-based path */
127 if (caller
->pr_Task
.tc_Node
.ln_Type
== NT_PROCESS
)
129 if (caller
->pr_HomeDir
!= BNULL
)
131 BPTR oldHomeDir
= me
->pr_HomeDir
;
132 D(bug("[LDLoad] Trying homedir\n"));
133 /* Temporarily override pr_HomeDir to let GetDeviceProc handle
134 PROGDIR: case correctly while opening library file */
135 me
->pr_HomeDir
= caller
->pr_HomeDir
;
136 seglist
= LDLoadSeg(name
);
137 me
->pr_HomeDir
= oldHomeDir
;
141 else if (!strstr(name
, ":")) {
142 delimPos
= strlen(basedir
);
143 pathLen
= delimPos
+ strlen(name
) + 2;
144 path
= AllocMem(pathLen
, MEMF_ANY
);
146 strcpy(path
, basedir
);
147 path
[delimPos
] = '/';
148 strcpy(&path
[delimPos
+ 1], name
);
150 if (caller
->pr_Task
.tc_Node
.ln_Type
== NT_PROCESS
)
152 /* Try the current directory of the caller */
154 D(bug("[LDLoad] Process\n"));
155 me
->pr_CurrentDir
= caller
->pr_CurrentDir
;
156 D(bug("[LDLoad] Trying currentdir\n"));
157 seglist
= LDLoadSeg(name
);
158 if ((!seglist
) && path
)
159 seglist
= LDLoadSeg(path
);
161 /* The the program directory of the caller */
162 if((!seglist
) && (caller
->pr_HomeDir
!= BNULL
))
164 D(bug("[LDLoad] Trying homedir\n"));
165 me
->pr_CurrentDir
= caller
->pr_HomeDir
;
166 seglist
= LDLoadSeg(name
);
167 if ((!seglist
) && path
)
168 seglist
= LDLoadSeg(path
);
174 /* Nup, let's try the default directory as supplied. */
175 D(bug("[LDLoad] Trying defaultdir\n"));
176 path
[delimPos
] = ':';
177 seglist
= LDLoadSeg(path
);
179 FreeMem(path
, pathLen
);
182 seglist
= LDLoadSeg(name
);
188 Library *LDInit(seglist, DOSBase)
189 Initialise the library.
191 static struct Library
*LDInit(BPTR seglist
, struct List
*list
, STRPTR resname
, struct ExecBase
*SysBase
)
193 struct Node
*node
= NULL
;
196 /* we may not have any extension fields */
197 const int sizeofresident
= offsetof(struct Resident
, rt_Init
) + sizeof(APTR
);
201 STRPTR addr
= (STRPTR
)((IPTR
)BADDR(seg
) - sizeof(ULONG
));
202 ULONG size
= *(ULONG
*)addr
;
205 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
206 size
-= sizeof(BPTR
) + sizeof(ULONG
);
207 size
>= sizeofresident
;
209 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
212 struct Resident
*res
= (struct Resident
*)addr
;
213 if( res
->rt_MatchWord
== RTC_MATCHWORD
214 && res
->rt_MatchTag
== res
)
216 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
217 /* AOS compatibility requirement.
218 * Ramlib ignores InitResident() return code.
219 * After InitResident() it checks if lib/dev appeared
220 * in Exec lib/dev list via FindName().
222 * Evidently InitResident()'s return code was not
223 * reliable for some early AOS libraries.
226 InitResident(res
, seglist
);
227 node
= FindName(list
, res
->rt_Name
);
229 D(bug("[LDInit] Done calling InitResident(%p) on %s, seg %p, node %p\n", res
, res
->rt_Name
, BADDR(seglist
), node
));
231 return (struct Library
*)node
;
234 seg
= *(BPTR
*)BADDR(seg
);
236 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist
));
238 /* If struct Resident was not found, just run the code. SegList in A0.
239 * Required to load WB1.x devs:narrator.device. */
241 AROS_UFC1NR(void, BADDR(seglist
) + sizeof(ULONG
), AROS_UFCA(BPTR
, seglist
, A0
));
242 node
= FindName(list
, resname
);
244 D(bug("[LDInit] Done direct calling %s, seg %p, node %p\n", resname
, BADDR(seglist
), node
));
246 return (struct Library
*)node
;
249 static struct Library
*CallLDInit(BPTR seglist
, struct List
*list
, STRPTR resname
, struct Library
*DOSBase
, struct ExecBase
*SysBase
)
251 struct Library
*tmplib
;
254 tmplib
= LDInit(seglist
, list
, resname
, SysBase
);
260 #define ExecOpenLibrary(libname, version) \
261 AROS_CALL2(struct Library *, ldBase->__OpenLibrary, \
262 AROS_LCA(STRPTR, libname, A1), \
263 AROS_LCA(ULONG, version, D0), \
264 struct ExecBase *, SysBase)
266 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
267 AROS_CALL4(LONG, ldBase->__OpenDevice, \
268 AROS_LCA(STRPTR, devname, A0), \
269 AROS_LCA(IPTR, unitNumber, D0), \
270 AROS_LCA(struct IORequest *, iORequest, A1), \
271 AROS_LCA(ULONG, flags, D1), \
272 struct ExecBase *, SysBase)
276 struct Node ldon_Node
;
277 struct SignalSemaphore ldon_SigSem
;
278 ULONG ldon_AccessCount
;
280 struct Task
*ldon_FirstLocker
;
284 static struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct ExecBase
*SysBase
)
286 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
289 ULONG len
= strlen(name
);
290 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
293 CopyMem(name
, dupname
, len
);
295 ret
->ldon_Node
.ln_Name
= dupname
;
296 InitSemaphore(&ret
->ldon_SigSem
);
297 ret
->ldon_AccessCount
= 0;
300 ret
->ldon_FirstLocker
= FindTask(0);
311 static void ProcessLDMessage(struct IntLDDemonBase
*ldBase
, struct LDDMsg
*ldd
, struct ExecBase
*SysBase
);
313 static struct LDObjectNode
*LDRequestObject(STRPTR libname
, ULONG version
, STRPTR dir
, struct List
*list
, struct ExecBase
*SysBase
)
315 /* We use FilePart() because the liblist is built from resident IDs,
316 and contain no path. Eg. The user can request gadgets/foo.gadget,
317 but the resident only contains foo.gadget
319 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
320 #if defined(__AROSEXEC_SMP__)
321 void *ExecLockBase
= ldBase
->dl_ExecLockRes
;
323 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
324 STRPTR stripped_libname
= FilePart(libname
);
325 struct Library
*tmplib
;
326 struct LDObjectNode
*object
;
328 D(bug("[LDDemon] %s()\n", __func__
));
331 We get the DOS semaphore to prevent the following:
332 - task 1 tries to open foobar.library, needs to load it from disk...
333 - task 1 Permit()'s (since it's not doing list things)
334 - task switch (whilst LDDemon MAY get process next it might not)
335 - task 2 tries to open foobar.library, needs to load it from disk...
336 - it also requests LDDemon to open foobar.library, so it is now
337 trying to open it twice
339 We block all OpenLibrary() callers from searching the list until
340 all the other OpenLibrary() callers have returned. That way,
341 task #2 won't ask for foobar.library until task #1 has got its
342 response back from the LDDemon process.
344 falemagn: I changed the implementation of all that.
345 There's a list of "LDObjectNodes", that contain the name
346 of the object being opened. Since the problem is that more
347 processes can attempt to open the same device/library. Instead of
348 locking a global semaphore until the opening is done, we lock a
349 per-object semaphore, so that others libraries/devices can be opened
350 in the meantime. Before, a deadlock could happen if there was a
353 Process A opens L --------> LDDemon loads L and locks sem S
359 L spawns a process B and ----------> The process opens
360 waits for it to respond a library but gets loked
361 to a message <----/---- because sem S is locked
368 Hopefully this won't happen anymore now.
370 ObtainSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
372 object
= (struct LDObjectNode
*)FindName(&ldBase
->dl_LDObjectsList
, stripped_libname
);
375 object
= LDNewObjectNode(stripped_libname
, SysBase
);
378 AddTail(&ldBase
->dl_LDObjectsList
, (struct Node
*)object
);
384 object
->ldon_AccessCount
+= 1;
387 ReleaseSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
392 ObtainSemaphore(&object
->ldon_SigSem
);
394 /* Try to find the resident in the list */
395 #if defined(__AROSEXEC_SMP__)
396 ObtainSystemLock(list
, SPINLOCK_MODE_READ
, LOCKF_FORBID
);
398 tmplib
= (struct Library
*)FindName(list
, stripped_libname
);
399 #if defined(__AROSEXEC_SMP__)
400 ReleaseSystemLock(list
, LOCKF_FORBID
);
405 /* Try to load from disk if not found */
407 bzero(&ldd
, sizeof(ldd
));
409 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
410 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
411 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
412 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
414 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
416 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
417 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
418 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
420 ldd
.ldd_Name
= libname
;
421 ldd
.ldd_BaseDir
= dir
;
422 #if INIT_IN_LDDEMON_CONTEXT
426 D(bug("[LDCaller] Sending request for %s, InLDProcess %d\n",
427 stripped_libname
, (struct Process
*)FindTask(NULL
) == ldBase
->dl_LDDemonTask
));
429 #if INIT_IN_LDDEMON_CONTEXT
430 /* Direct call if already in LDDemon context */
431 if ((struct Process
*)FindTask(NULL
) == ldBase
->dl_LDDemonTask
) {
432 ProcessLDMessage(ldBase
, &ldd
, SysBase
);
436 SetSignal(0, SIGF_SINGLE
);
437 PutMsg(ldBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
438 WaitPort(&ldd
.ldd_ReplyPort
);
441 D(bug("[LDCaller] Returned 0x%p\n", ldd
.ldd_Return
));
443 #if INIT_IN_LDDEMON_CONTEXT
444 tmplib
= ldd
.ldd_Return
;
446 tmplib
= CallLDInit(ldd
.ldd_Return
, list
, stripped_libname
, DOSBase
, SysBase
);
453 * The library is not on disk so check Resident List.
454 * It can be there if it is resident but was flushed.
456 struct Resident
*resident
= FindResident(stripped_libname
);
459 * Check if the resident is of required type and version is correct.
460 * This relies on the fact that lh_Type is set correctly for exec lists.
461 * In AROS this is true (see rom/exec/prepareexecbase.c).
463 if (resident
&& (resident
->rt_Type
== list
->lh_Type
) && (resident
->rt_Version
>= version
))
464 InitResident(resident
, BNULL
);
470 static void LDReleaseObject(struct LDObjectNode
*object
, struct ExecBase
*SysBase
)
472 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
475 Release the semaphore here, after calling Open vector. This
476 means that library open is singlethreaded by the semaphore.
477 It also handles circular dependant libraries. (Won't deadlock),
478 and recursive OpenLibrary calls (Semaphores nest when obtained
479 several times in a row by the same task).
482 ObtainSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
484 if (--(object
->ldon_AccessCount
) == 0)
486 Remove((struct Node
*)object
);
488 * CHECKME: In LDRequestObject() we obtain the object semaphore also on a new object.
489 * So shouldn't we release it here too ?
492 FreeVec(object
->ldon_Node
.ln_Name
);
496 ReleaseSemaphore(&object
->ldon_SigSem
);
498 ReleaseSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
501 AROS_LH2(struct Library
*, OpenLibrary
,
502 AROS_LHA(STRPTR
, libname
, A1
),
503 AROS_LHA(ULONG
, version
, D0
),
504 struct ExecBase
*, SysBase
, 0, Lddemon
)
508 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
509 struct Library
*library
;
510 struct LDObjectNode
*object
;
512 D(bug("[LDDemon] %s()\n", __func__
));
514 object
= LDRequestObject(libname
, version
, "libs", &SysBase
->LibList
, SysBase
);
519 /* Call the EXEC's OpenLibrary function */
520 library
= ExecOpenLibrary(object
->ldon_Node
.ln_Name
, version
);
522 LDReleaseObject(object
, SysBase
);
529 AROS_LH4(LONG
, OpenDevice
,
530 AROS_LHA(STRPTR
, devname
, A0
),
531 AROS_LHA(IPTR
, unitNumber
, D0
),
532 AROS_LHA(struct IORequest
*, iORequest
, A1
),
533 AROS_LHA(ULONG
, flags
, D1
),
534 struct ExecBase
*, SysBase
, 0, Lddemon
)
538 struct LDObjectNode
*object
;
539 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
541 D(bug("[LDDemon] %s()\n", __func__
));
543 object
= LDRequestObject(devname
, 0, "devs", &SysBase
->DeviceList
, SysBase
);
547 /* Call exec.library/OpenDevice(), it will do the job */
548 ExecOpenDevice(object
->ldon_Node
.ln_Name
, unitNumber
, iORequest
, flags
);
549 LDReleaseObject(object
, SysBase
);
553 iORequest
->io_Error
= IOERR_OPENFAIL
;
554 iORequest
->io_Device
= NULL
;
555 iORequest
->io_Unit
= NULL
;
558 D(bug("[LDCaller] Open result: %d\n", iORequest
->io_Error
));
560 return iORequest
->io_Error
;
565 AROS_LH1(void, CloseLibrary
,
566 AROS_LHA(struct Library
*, library
, A1
),
567 struct ExecBase
*, SysBase
, 0, Lddemon
)
571 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
572 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
575 D(bug("[LDDemon] %s()\n", __func__
));
577 if( library
!= NULL
)
580 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
583 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
585 /* Safe to call from a Task */
594 AROS_LH1(void, CloseDevice
,
595 AROS_LHA(struct IORequest
*, iORequest
, A1
),
596 struct ExecBase
*, SysBase
, 0, Lddemon
)
599 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
600 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
601 BPTR seglist
= BNULL
;
603 D(bug("[LDDemon] %s()\n", __func__
));
606 if( iORequest
->io_Device
!= NULL
)
608 seglist
= AROS_LVO_CALL1(BPTR
,
609 AROS_LCA(struct IORequest
*, iORequest
, A1
),
610 struct Device
*, iORequest
->io_Device
, 2, );
611 iORequest
->io_Device
=(struct Device
*)-1;
614 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
622 AROS_LH1(void, RemLibrary
,
623 AROS_LHA(struct Library
*, library
, A1
),
624 struct ExecBase
*, SysBase
, 0, Lddemon
)
628 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
629 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
632 D(bug("[LDDemon] %s()\n", __func__
));
635 /* calling ExpungeLib: library ends up in D0 and A6 for compatibility */
636 seglist
= AROS_CALL1(BPTR
, __AROS_GETVECADDR(library
, 3),
637 AROS_LCA(struct Library
*, library
, D0
),
638 struct Library
*, library
642 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
650 AROS_UFH3(LONG
, LDFlush
,
651 AROS_UFHA(struct MemHandlerData
*, lmhd
, A0
),
652 AROS_UFHA(APTR
, data
, A1
),
653 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
658 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
659 #if defined(__AROSEXEC_SMP__)
660 void *ExecLockBase
= ldBase
->dl_ExecLockRes
;
662 struct Library
*library
;
664 D(bug("[LDDemon] %s()\n", __func__
));
665 ldBase
->dl_LDReturn
= MEM_DID_NOTHING
;
667 /* Forbid() is already done, but I don't want to rely on it. */
669 #if defined(__AROSEXEC_SMP__)
670 ObtainSystemLock(&SysBase
->LibList
, SPINLOCK_MODE_WRITE
, 0);
673 /* Follow the linked list of shared libraries. */
674 library
= (struct Library
*)SysBase
->LibList
.lh_Head
;
675 while(library
->lib_Node
.ln_Succ
!= NULL
)
677 /* Flush libraries with a 0 open count */
678 if( ! library
->lib_OpenCnt
)
680 /* the library list node will be wiped from memory */
681 struct Library
*nextLib
= (struct Library
*)library
->lib_Node
.ln_Succ
;
683 /* Did it really go away? */
684 if( ldBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
686 /* Yes! Return it. */
687 #if defined(__AROSEXEC_SMP__)
688 ReleaseSystemLock(&SysBase
->LibList
, 0);
691 return MEM_TRY_AGAIN
;
697 /* Go on to next library. */
698 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
701 #if defined(__AROSEXEC_SMP__)
702 ReleaseSystemLock(&SysBase
->LibList
, 0);
704 ObtainSystemLock(&SysBase
->DeviceList
, SPINLOCK_MODE_WRITE
, 0);
706 /* Do the same with the device list. */
707 library
= (struct Library
*)SysBase
->DeviceList
.lh_Head
;
708 while(library
->lib_Node
.ln_Succ
!= NULL
)
710 /* Flush libraries with a 0 open count */
711 if( ! library
->lib_OpenCnt
)
713 struct Library
*nextDev
= (struct Library
*)library
->lib_Node
.ln_Succ
;
714 RemDevice((struct Device
*)library
);
715 /* Did it really go away? */
716 if( ldBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
718 /* Yes! Return it. */
719 #if defined(__AROSEXEC_SMP__)
720 ReleaseSystemLock(&SysBase
->DeviceList
, 0);
723 return MEM_TRY_AGAIN
;
729 /* Go on to next library. */
730 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
733 #if defined(__AROSEXEC_SMP__)
734 ReleaseSystemLock(&SysBase
->DeviceList
, 0);
738 return MEM_DID_NOTHING
;
743 static void ProcessLDMessage(struct IntLDDemonBase
*ldBase
, struct LDDMsg
*ldd
, struct ExecBase
*SysBase
)
745 #if INIT_IN_LDDEMON_CONTEXT
746 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
749 D(bug("[LDDemon] Got a request for %s in %s\n", ldd
->ldd_Name
, ldd
->ldd_BaseDir
));
751 seglist
= LDLoad(ldBase
, ldd
->ldd_ReplyPort
.mp_SigTask
, ldd
->ldd_Name
, ldd
->ldd_BaseDir
, SysBase
);
753 #if INIT_IN_LDDEMON_CONTEXT
754 ldd
->ldd_Return
= CallLDInit(seglist
, ldd
->ldd_List
, FilePart(ldd
->ldd_Name
), ldBase
->dl_DOSBase
, SysBase
);
755 D(bug("[LDDemon] Replying with %p as result, seglist was %p\n", ldd
->ldd_Return
, seglist
));
757 ldd
->ldd_Return
= seglist
;
758 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
764 The LDDemon process entry. Sits around and does nothing until a
765 request for a library comes, when it will then find the library
766 and hopefully open it.
768 static AROS_PROCH(LDDemon
, argptr
, argsize
, SysBase
)
772 struct IntLDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
777 WaitPort(ldBase
->dl_LDDemonPort
);
778 while( (ldd
= (struct LDDMsg
*)GetMsg(ldBase
->dl_LDDemonPort
)) )
780 ProcessLDMessage(ldBase
, ldd
, SysBase
);
781 ReplyMsg((struct Message
*)ldd
);
782 } /* messages available */
791 static ULONG
LDDemon_Init(struct IntLDDemonBase
*ldBase
)
793 struct Library
*DOSBase
;
794 struct TagItem tags
[] =
796 { NP_Entry
, (IPTR
)LDDemon
},
799 { NP_WindowPtr
, -1 },
800 { NP_Name
, (IPTR
)ldDemonName
},
805 DOSBase
= TaggedOpenLibrary(TAGGEDOPEN_DOS
);
807 Alert( AN_RAMLib
| AG_OpenLib
| AO_DOSLib
| AT_DeadEnd
);
810 if ((ldBase
->dl_LDDemonPort
= CreateMsgPort()) == NULL
)
812 Alert( AN_RAMLib
| AG_NoMemory
| AT_DeadEnd
);
815 NEWLIST(&ldBase
->dl_Flavours
);
817 FreeSignal(ldBase
->dl_LDDemonPort
->mp_SigBit
);
818 ldBase
->dl_LDDemonPort
->mp_SigBit
= SIGBREAKB_CTRL_F
;
820 ldBase
->dl_LDHandler
.is_Node
.ln_Name
= (STRPTR
)ldDemonName
;
821 ldBase
->dl_LDHandler
.is_Node
.ln_Pri
= 0;
822 ldBase
->dl_LDHandler
.is_Code
= (VOID_FUNC
)LDFlush
;
823 ldBase
->dl_LDHandler
.is_Data
= NULL
;
825 ldBase
->dl_DOSBase
= DOSBase
;
827 NEWLIST(&ldBase
->dl_LDObjectsList
);
828 InitSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
830 SysBase
->ex_RamLibPrivate
= ldBase
;
832 AddMemHandler(&ldBase
->dl_LDHandler
);
834 #if defined(__AROSEXEC_SMP__)
835 ldBase
->dl_ExecLockRes
= OpenResource("execlock.resource");
839 * Grab the semaphore ourself. The reason for this is that it will
840 * cause all other tasks to wait until we have finished initialising
841 * before they try and open something.
843 ObtainSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
845 #define SetFunc(offs,ptr) \
846 SetFunction(&SysBase->LibNode, (-offs)*(LONG)LIB_VECTSIZE, \
847 AROS_SLIB_ENTRY(ptr,Lddemon,0))
849 /* Do not set the vectors until you have initialised everything else. */
850 ldBase
->__OpenLibrary
= SetFunc(92, OpenLibrary
);
851 ldBase
->__OpenDevice
= SetFunc(74, OpenDevice
);
852 (void)SetFunc(69, CloseLibrary
);
853 (void)SetFunc(75, CloseDevice
);
854 (void)SetFunc(67, RemLibrary
);
855 (void)SetFunc(73, RemLibrary
);
857 if( !(ldBase
->dl_LDDemonTask
= CreateNewProc((struct TagItem
*)tags
)) )
859 Alert( AT_DeadEnd
| AN_RAMLib
| AG_ProcCreate
);
862 /* Fix up the MsgPort */
864 ldBase
->dl_LDDemonPort
->mp_SigTask
= ldBase
->dl_LDDemonTask
;
866 /* Then unlock the semaphore to allow other processes to run. */
867 ReleaseSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
872 ADD2INITLIB(LDDemon_Init
, 0)