export the cxx flags separately
[AROS.git] / rom / lddemon / lddemon.c
blobe6e2ad1116d8dfa163655217fdb42dc2204324d3
1 /*
2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Loader for shared libraries and devices.
6 */
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>
21 #include <dos/dos.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>
27 #include <resources/execlock.h>
28 #include <aros/types/spinlock_s.h>
30 #include <stddef.h>
31 #include <string.h>
33 #include "lddemon.h"
35 #ifdef __mc68000
36 #define INIT_IN_LDDEMON_CONTEXT 1
37 #else
38 #define INIT_IN_LDDEMON_CONTEXT 0
39 #endif
41 #define CHECK_DEPENDENCY 1
43 /* Please leave them here! They are needed on Linux-M68K */
44 AROS_LD2(struct Library *, OpenLibrary,
45 AROS_LDA(STRPTR, libname, A1),
46 AROS_LDA(ULONG, version, D0),
47 struct ExecBase *, SysBase, 0, Dos);
48 AROS_LD4(LONG, OpenDevice,
49 AROS_LDA(STRPTR, devname, A0),
50 AROS_LDA(IPTR, unitNumber, D0),
51 AROS_LDA(struct IORequest *, iORequest, A1),
52 AROS_LDA(ULONG, flags, D1),
53 struct ExecBase *, SysBase, 0, Dos);
54 AROS_LD1(void, CloseLibrary,
55 AROS_LDA(struct Library *, library, A1),
56 struct ExecBase *, SysBase, 0, Dos);
57 AROS_LD1(void, CloseDevice,
58 AROS_LDA(struct IORequest *, iORequest, A1),
59 struct ExecBase *, SysBase, 0, Dos);
60 AROS_LD1(void, RemLibrary,
61 AROS_LDA(struct Library *, library, A1),
62 struct ExecBase *, SysBase, 0, Dos);
64 struct LDDMsg
66 struct Message ldd_Msg; /* Message link */
67 struct MsgPort ldd_ReplyPort; /* Callers ReplyPort */
69 STRPTR ldd_Name; /* Name of thing to load */
71 STRPTR ldd_BaseDir; /* Base directory to load from */
72 #if INIT_IN_LDDEMON_CONTEXT
73 struct Library *ldd_Return; /* Loaded and initialized Library */
74 struct List *ldd_List; /* List to add */
75 #else
76 BPTR ldd_Return; /* Loaded seglist */
77 #endif
80 static const char ldDemonName[] = "Lib & Dev Loader Daemon";
83 BPTR LDLoad( caller, name, basedir, DOSBase )
84 Try and load a segment from disk for the object <name>, relative
85 to directory <basedir>. Will also try <caller>'s current and home
86 directories.
88 static BPTR LDLoad(struct Process *caller, STRPTR name, STRPTR basedir,
89 struct Library *DOSBase, struct ExecBase *SysBase)
91 struct Process *me = (struct Process *)FindTask(NULL);
92 BPTR seglist = BNULL;
93 STRPTR path;
94 ULONG pathLen;
95 int delimPos;
98 If the caller was a process, we have more scope for loading
99 libraries. We can load them from the callers current directory,
100 or from the PROGDIR: assign. These could both be the same
101 though.
103 D(bug(
104 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
105 caller, caller->pr_Task.tc_Node.ln_Name, name, basedir
108 if (strncmp(name, "PROGDIR:", 8) == 0)
110 /* Special case for explicit PROGDIR-based path */
111 if (caller->pr_Task.tc_Node.ln_Type == NT_PROCESS)
113 if (caller->pr_HomeDir != BNULL)
115 BPTR oldHomeDir = me->pr_HomeDir;
116 D(bug("[LDLoad] Trying homedir\n"));
117 /* Temporarily override pr_HomeDir to let GetDeviceProc handle
118 PROGDIR: case correctly while opening library file */
119 me->pr_HomeDir = caller->pr_HomeDir;
120 seglist = LoadSeg(name);
121 me->pr_HomeDir = oldHomeDir;
125 else if (!strstr(name, ":")) {
126 delimPos = strlen(basedir);
127 pathLen = delimPos + strlen(name) + 2;
128 path = AllocMem(pathLen, MEMF_ANY);
129 if (path) {
130 strcpy(path, basedir);
131 path[delimPos] = '/';
132 strcpy(&path[delimPos + 1], name);
134 if (caller->pr_Task.tc_Node.ln_Type == NT_PROCESS)
136 /* Try the current directory of the caller */
138 D(bug("[LDLoad] Process\n"));
139 me->pr_CurrentDir = caller->pr_CurrentDir;
140 D(bug("[LDLoad] Trying currentdir\n"));
141 seglist = LoadSeg(name);
142 if ((!seglist) && path)
143 seglist = LoadSeg(path);
145 /* The the program directory of the caller */
146 if((!seglist) && (caller->pr_HomeDir != BNULL))
148 D(bug("[LDLoad] Trying homedir\n"));
149 me->pr_CurrentDir = caller->pr_HomeDir;
150 seglist = LoadSeg(name);
151 if ((!seglist) && path)
152 seglist = LoadSeg(path);
156 if (path) {
157 if (!seglist) {
158 /* Nup, let's try the default directory as supplied. */
159 D(bug("[LDLoad] Trying defaultdir\n"));
160 path[delimPos] = ':';
161 seglist = LoadSeg(path);
163 FreeMem(path, pathLen);
165 } else
166 seglist = LoadSeg(name);
168 return seglist;
172 Library *LDInit(seglist, DOSBase)
173 Initialise the library.
175 static struct Library *LDInit(BPTR seglist, struct List *list, STRPTR resname, struct ExecBase *SysBase)
177 struct Node *node = NULL;
178 BPTR seg = seglist;
180 /* we may not have any extension fields */
181 const int sizeofresident = offsetof(struct Resident, rt_Init) + sizeof(APTR);
183 while(seg)
185 STRPTR addr = (STRPTR)((IPTR)BADDR(seg) - sizeof(ULONG));
186 ULONG size = *(ULONG *)addr;
188 for(
189 addr += sizeof(BPTR) + sizeof(ULONG),
190 size -= sizeof(BPTR) + sizeof(ULONG);
191 size >= sizeofresident;
192 size -= 2, addr += 2
193 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
196 struct Resident *res = (struct Resident *)addr;
197 if( res->rt_MatchWord == RTC_MATCHWORD
198 && res->rt_MatchTag == res )
200 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
201 /* AOS compatibility requirement.
202 * Ramlib ignores InitResident() return code.
203 * After InitResident() it checks if lib/dev appeared
204 * in Exec lib/dev list via FindName().
206 * Evidently InitResident()'s return code was not
207 * reliable for some early AOS libraries.
209 Forbid();
210 InitResident(res, seglist);
211 node = FindName(list, res->rt_Name);
212 Permit();
213 D(bug("[LDInit] Done calling InitResident(%p) on %s, seg %p, node %p\n", res, res->rt_Name, BADDR(seglist), node));
215 return (struct Library*)node;
218 seg = *(BPTR *)BADDR(seg);
220 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
221 #ifdef __mc68000
222 /* If struct Resident was not found, just run the code. SegList in A0.
223 * Required to load WB1.x devs:narrator.device. */
224 Forbid();
225 AROS_UFC1NR(void, BADDR(seglist) + sizeof(ULONG), AROS_UFCA(BPTR, seglist, A0));
226 node = FindName(list, resname);
227 Permit();
228 D(bug("[LDInit] Done direct calling %s, seg %p, node %p\n", resname, BADDR(seglist), node));
229 #endif
230 return (struct Library*)node;
233 static struct Library *CallLDInit(BPTR seglist, struct List *list, STRPTR resname, struct Library *DOSBase, struct ExecBase *SysBase)
235 struct Library *tmplib;
236 if (!seglist)
237 return NULL;
238 tmplib = LDInit(seglist, list, resname, SysBase);
239 if (!tmplib)
240 UnLoadSeg(seglist);
241 return tmplib;
244 #define ExecOpenLibrary(libname, version) \
245 AROS_CALL2(struct Library *, ldBase->__OpenLibrary, \
246 AROS_LCA(STRPTR, libname, A1), \
247 AROS_LCA(ULONG, version, D0), \
248 struct ExecBase *, SysBase)
250 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
251 AROS_CALL4(LONG, ldBase->__OpenDevice, \
252 AROS_LCA(STRPTR, devname, A0), \
253 AROS_LCA(IPTR, unitNumber, D0), \
254 AROS_LCA(struct IORequest *, iORequest, A1), \
255 AROS_LCA(ULONG, flags, D1), \
256 struct ExecBase *, SysBase)
258 struct LDObjectNode
260 struct Node ldon_Node;
261 struct SignalSemaphore ldon_SigSem;
262 ULONG ldon_AccessCount;
263 #if CHECK_DEPENDENCY
264 struct Task *ldon_FirstLocker;
265 #endif
268 static struct LDObjectNode *LDNewObjectNode(STRPTR name, struct ExecBase *SysBase)
270 struct LDObjectNode *ret = AllocVec(sizeof(struct LDObjectNode), MEMF_ANY);
271 if (ret)
273 ULONG len = strlen(name);
274 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
275 if (dupname)
277 CopyMem(name, dupname, len);
278 dupname[len] = '\0';
279 ret->ldon_Node.ln_Name = dupname;
280 InitSemaphore(&ret->ldon_SigSem);
281 ret->ldon_AccessCount = 0;
283 #if CHECK_DEPENDENCY
284 ret->ldon_FirstLocker = FindTask(0);
285 #endif
287 return ret;
289 FreeVec(ret);
292 return NULL;
295 static void ProcessLDMessage(struct LDDemonBase *ldBase, struct LDDMsg *ldd, struct Library *DOSBase, struct ExecBase *SysBase);
297 static struct LDObjectNode *LDRequestObject(STRPTR libname, ULONG version, STRPTR dir, struct List *list, struct ExecBase *SysBase)
299 /* We use FilePart() because the liblist is built from resident IDs,
300 and contain no path. Eg. The user can request gadgets/foo.gadget,
301 but the resident only contains foo.gadget
303 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
304 #if defined(__AROSEXEC_SMP__)
305 void *ExecLockBase = ldBase->dl_ExecLockRes;
306 #endif
307 struct Library *DOSBase = ldBase->dl_DOSBase;
308 STRPTR stripped_libname = FilePart(libname);
309 struct Library *tmplib;
310 struct LDObjectNode *object;
313 We get the DOS semaphore to prevent the following:
314 - task 1 tries to open foobar.library, needs to load it from disk...
315 - task 1 Permit()'s (since it's not doing list things)
316 - task switch (whilst LDDemon MAY get process next it might not)
317 - task 2 tries to open foobar.library, needs to load it from disk...
318 - it also requests LDDemon to open foobar.library, so it is now
319 trying to open it twice
321 We block all OpenLibrary() callers from searching the list until
322 all the other OpenLibrary() callers have returned. That way,
323 task #2 won't ask for foobar.library until task #1 has got its
324 response back from the LDDemon process.
326 falemagn: I changed the implementation of all that.
327 There's a list of "LDObjectNodes", that contain the name
328 of the object being opened. Since the problem is that more
329 processes can attempt to open the same device/library. Instead of
330 locking a global semaphore until the opening is done, we lock a
331 per-object semaphore, so that others libraries/devices can be opened
332 in the meantime. Before, a deadlock could happen if there was a
333 situation like this:
335 Process A opens L --------> LDDemon loads L and locks sem S
338 1 / \ 3
340 / 2 \
341 L spawns a process B and ----------> The process opens
342 waits for it to respond a library but gets loked
343 to a message <----/---- because sem S is locked
347 Proces B will never
348 respond to L.
350 Hopefully this won't happen anymore now.
352 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
354 object = (struct LDObjectNode *)FindName(&ldBase->dl_LDObjectsList, stripped_libname);
355 if (!object)
357 object = LDNewObjectNode(stripped_libname, SysBase);
358 if (object)
360 AddTail(&ldBase->dl_LDObjectsList, (struct Node *)object);
364 if (object)
366 object->ldon_AccessCount += 1;
369 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
371 if (!object)
372 return NULL;
374 ObtainSemaphore(&object->ldon_SigSem);
376 /* Try to find the resident in the list */
377 #if defined(__AROSEXEC_SMP__)
378 ObtainSystemLock(list, SPINLOCK_MODE_READ, LOCKF_FORBID);
379 #endif
380 tmplib = (struct Library *)FindName(list, stripped_libname);
381 #if defined(__AROSEXEC_SMP__)
382 ReleaseSystemLock(list, LOCKF_FORBID);
383 #endif
385 if (!tmplib)
387 /* Try to load from disk if not found */
388 struct LDDMsg ldd;
389 bzero(&ldd, sizeof(ldd));
391 ldd.ldd_ReplyPort.mp_SigBit = SIGB_SINGLE;
392 ldd.ldd_ReplyPort.mp_SigTask = FindTask(NULL);
393 ldd.ldd_ReplyPort.mp_Flags = PA_SIGNAL;
394 ldd.ldd_ReplyPort.mp_Node.ln_Type = NT_MSGPORT;
396 NEWLIST(&ldd.ldd_ReplyPort.mp_MsgList);
398 ldd.ldd_Msg.mn_Node.ln_Type = NT_MESSAGE;
399 ldd.ldd_Msg.mn_Length = sizeof(struct LDDMsg);
400 ldd.ldd_Msg.mn_ReplyPort = &ldd.ldd_ReplyPort;
402 ldd.ldd_Name = libname;
403 ldd.ldd_BaseDir = dir;
404 #if INIT_IN_LDDEMON_CONTEXT
405 ldd.ldd_List = list;
406 #endif
408 D(bug("[LDCaller] Sending request for %s, InLDProcess %d\n",
409 stripped_libname, (struct Process*)FindTask(NULL) == ldBase->dl_LDDemonTask));
411 #if INIT_IN_LDDEMON_CONTEXT
412 /* Direct call if already in LDDemon context */
413 if ((struct Process*)FindTask(NULL) == ldBase->dl_LDDemonTask) {
414 ProcessLDMessage(ldBase, &ldd, DOSBase, SysBase);
415 } else
416 #endif
418 SetSignal(0, SIGF_SINGLE);
419 PutMsg(ldBase->dl_LDDemonPort, (struct Message *)&ldd);
420 WaitPort(&ldd.ldd_ReplyPort);
423 D(bug("[LDCaller] Returned 0x%p\n", ldd.ldd_Return));
425 #if INIT_IN_LDDEMON_CONTEXT
426 tmplib = ldd.ldd_Return;
427 #else
428 tmplib = CallLDInit(ldd.ldd_Return, list, stripped_libname, DOSBase, SysBase);
429 #endif
432 if (!tmplib)
435 * The library is not on disk so check Resident List.
436 * It can be there if it is resident but was flushed.
438 struct Resident *resident = FindResident(stripped_libname);
441 * Check if the resident is of required type and version is correct.
442 * This relies on the fact that lh_Type is set correctly for exec lists.
443 * In AROS this is true (see rom/exec/prepareexecbase.c).
445 if (resident && (resident->rt_Type == list->lh_Type) && (resident->rt_Version >= version))
446 InitResident(resident, BNULL);
449 return object;
452 static void LDReleaseObject(struct LDObjectNode *object, struct ExecBase *SysBase)
454 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
457 Release the semaphore here, after calling Open vector. This
458 means that library open is singlethreaded by the semaphore.
459 It also handles circular dependant libraries. (Won't deadlock),
460 and recursive OpenLibrary calls (Semaphores nest when obtained
461 several times in a row by the same task).
464 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
466 if (--(object->ldon_AccessCount) == 0)
468 Remove((struct Node *)object);
470 * CHECKME: In LDRequestObject() we obtain the object semaphore also on a new object.
471 * So shouldn't we release it here too ?
474 FreeVec(object->ldon_Node.ln_Name);
475 FreeVec(object);
477 else
478 ReleaseSemaphore(&object->ldon_SigSem);
480 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
483 AROS_LH2(struct Library *, OpenLibrary,
484 AROS_LHA(STRPTR, libname, A1),
485 AROS_LHA(ULONG, version, D0),
486 struct ExecBase *, SysBase, 0, Dos)
488 AROS_LIBFUNC_INIT
490 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
491 struct Library *library;
492 struct LDObjectNode *object;
494 object = LDRequestObject(libname, version, "libs", &SysBase->LibList, SysBase);
496 if (!object)
497 return NULL;
499 /* Call the EXEC's OpenLibrary function */
500 library = ExecOpenLibrary(object->ldon_Node.ln_Name, version);
502 LDReleaseObject(object, SysBase);
504 return library;
506 AROS_LIBFUNC_EXIT
509 AROS_LH4(LONG, OpenDevice,
510 AROS_LHA(STRPTR, devname, A0),
511 AROS_LHA(IPTR, unitNumber, D0),
512 AROS_LHA(struct IORequest *, iORequest, A1),
513 AROS_LHA(ULONG, flags, D1),
514 struct ExecBase *, SysBase, 0, Dos)
516 AROS_LIBFUNC_INIT
518 struct LDObjectNode *object;
519 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
521 object = LDRequestObject(devname, 0, "devs", &SysBase->DeviceList, SysBase);
523 if (object)
525 /* Call exec.library/OpenDevice(), it will do the job */
526 ExecOpenDevice(object->ldon_Node.ln_Name, unitNumber, iORequest, flags);
527 LDReleaseObject(object, SysBase);
529 else
531 iORequest->io_Error = IOERR_OPENFAIL;
532 iORequest->io_Device = NULL;
533 iORequest->io_Unit = NULL;
536 D(bug("[LDCaller] Open result: %d\n", iORequest->io_Error));
538 return iORequest->io_Error;
540 AROS_LIBFUNC_EXIT
543 AROS_LH1(void, CloseLibrary,
544 AROS_LHA(struct Library *, library, A1),
545 struct ExecBase *, SysBase, 0, Dos)
547 AROS_LIBFUNC_INIT
549 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
550 struct Library *DOSBase = ldBase->dl_DOSBase;
551 BPTR seglist;
553 if( library != NULL )
555 Forbid();
556 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
557 if( seglist )
559 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
561 /* Safe to call from a Task */
562 UnLoadSeg(seglist);
564 Permit();
567 AROS_LIBFUNC_EXIT
570 AROS_LH1(void, CloseDevice,
571 AROS_LHA(struct IORequest *, iORequest, A1),
572 struct ExecBase *, SysBase, 0, Dos)
574 AROS_LIBFUNC_INIT
575 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
576 struct Library *DOSBase = ldBase->dl_DOSBase;
577 BPTR seglist = BNULL;
579 Forbid();
580 if( iORequest->io_Device != NULL )
582 seglist = AROS_LVO_CALL1(BPTR,
583 AROS_LCA(struct IORequest *, iORequest, A1),
584 struct Device *, iORequest->io_Device, 2, );
585 iORequest->io_Device=(struct Device *)-1;
586 if( seglist )
588 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
589 UnLoadSeg(seglist);
592 Permit();
593 AROS_LIBFUNC_EXIT
596 AROS_LH1(void, RemLibrary,
597 AROS_LHA(struct Library *, library, A1),
598 struct ExecBase *, SysBase, 0, Dos)
600 AROS_LIBFUNC_INIT
602 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
603 struct Library *DOSBase = ldBase->dl_DOSBase;
604 BPTR seglist;
606 Forbid();
607 /* calling ExpungeLib: library ends up in D0 and A6 for compatibility */
608 seglist = AROS_CALL1(BPTR, __AROS_GETVECADDR(library, 3),
609 AROS_LCA(struct Library *, library, D0),
610 struct Library *, library
612 if( seglist )
614 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
615 UnLoadSeg(seglist);
617 Permit();
619 AROS_LIBFUNC_EXIT
622 AROS_UFH3(LONG, LDFlush,
623 AROS_UFHA(struct MemHandlerData *, lmhd, A0),
624 AROS_UFHA(APTR, data, A1),
625 AROS_UFHA(struct ExecBase *, SysBase, A6)
628 AROS_USERFUNC_INIT
630 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
631 #if defined(__AROSEXEC_SMP__)
632 void *ExecLockBase = ldBase->dl_ExecLockRes;
633 #endif
634 struct Library *library;
636 D(bug("[LDDemon] Flush called\n"));
637 ldBase->dl_LDReturn = MEM_DID_NOTHING;
639 /* Forbid() is already done, but I don't want to rely on it. */
640 Forbid();
641 #if defined(__AROSEXEC_SMP__)
642 ObtainSystemLock(&SysBase->LibList, SPINLOCK_MODE_WRITE, 0);
643 #endif
645 /* Follow the linked list of shared libraries. */
646 library = (struct Library *)SysBase->LibList.lh_Head;
647 while(library->lib_Node.ln_Succ != NULL)
649 /* Flush libraries with a 0 open count */
650 if( ! library->lib_OpenCnt )
652 /* the library list node will be wiped from memory */
653 struct Library *nextLib = (struct Library *)library->lib_Node.ln_Succ;
654 RemLibrary(library);
655 /* Did it really go away? */
656 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
658 /* Yes! Return it. */
659 #if defined(__AROSEXEC_SMP__)
660 ReleaseSystemLock(&SysBase->LibList, 0);
661 #endif
662 Permit();
663 return MEM_TRY_AGAIN;
665 library = nextLib;
667 else
669 /* Go on to next library. */
670 library = (struct Library *)library->lib_Node.ln_Succ;
673 #if defined(__AROSEXEC_SMP__)
674 ReleaseSystemLock(&SysBase->LibList, 0);
676 ObtainSystemLock(&SysBase->DeviceList, SPINLOCK_MODE_WRITE, 0);
677 #endif
678 /* Do the same with the device list. */
679 library = (struct Library *)SysBase->DeviceList.lh_Head;
680 while(library->lib_Node.ln_Succ != NULL)
682 /* Flush libraries with a 0 open count */
683 if( ! library->lib_OpenCnt )
685 struct Library *nextDev = (struct Library *)library->lib_Node.ln_Succ;
686 RemDevice((struct Device *)library);
687 /* Did it really go away? */
688 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
690 /* Yes! Return it. */
691 #if defined(__AROSEXEC_SMP__)
692 ReleaseSystemLock(&SysBase->DeviceList, 0);
693 #endif
694 Permit();
695 return MEM_TRY_AGAIN;
697 library = nextDev;
699 else
701 /* Go on to next library. */
702 library = (struct Library *)library->lib_Node.ln_Succ;
705 #if defined(__AROSEXEC_SMP__)
706 ReleaseSystemLock(&SysBase->DeviceList, 0);
707 #endif
708 Permit();
710 return MEM_DID_NOTHING;
712 AROS_USERFUNC_EXIT
715 static void ProcessLDMessage(struct LDDemonBase *ldBase, struct LDDMsg *ldd, struct Library *DOSBase, struct ExecBase *SysBase)
717 BPTR seglist;
718 D(bug("[LDDemon] Got a request for %s in %s\n", ldd->ldd_Name, ldd->ldd_BaseDir));
720 seglist = LDLoad(ldd->ldd_ReplyPort.mp_SigTask, ldd->ldd_Name, ldd->ldd_BaseDir, DOSBase, SysBase);
722 #if INIT_IN_LDDEMON_CONTEXT
723 ldd->ldd_Return = CallLDInit(seglist, ldd->ldd_List, FilePart(ldd->ldd_Name), DOSBase, SysBase);
724 D(bug("[LDDemon] Replying with %p as result, seglist was %p\n", ldd->ldd_Return, seglist));
725 #else
726 ldd->ldd_Return = seglist;
727 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
728 #endif
732 void LDDemon()
733 The LDDemon process entry. Sits around and does nothing until a
734 request for a library comes, when it will then find the library
735 and hopefully open it.
737 static AROS_PROCH(LDDemon, argptr, argsize, SysBase)
739 AROS_PROCFUNC_INIT
741 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
742 struct Library *DOSBase = ldBase->dl_DOSBase;
743 struct LDDMsg *ldd;
745 for(;;)
747 WaitPort(ldBase->dl_LDDemonPort);
748 while( (ldd = (struct LDDMsg *)GetMsg(ldBase->dl_LDDemonPort)) )
750 ProcessLDMessage(ldBase, ldd, DOSBase, SysBase);
751 ReplyMsg((struct Message *)ldd);
752 } /* messages available */
755 /* lddemon died */
756 return 0;
758 AROS_PROCFUNC_EXIT
761 static ULONG LDDemon_Init(struct LDDemonBase *ldBase)
763 struct Library *DOSBase;
764 struct TagItem tags[] =
766 { NP_Entry, (IPTR)LDDemon },
767 { NP_Input, 0 },
768 { NP_Output, 0 },
769 { NP_WindowPtr, -1 },
770 { NP_Name, (IPTR)ldDemonName },
771 { NP_Priority, 5 },
772 { TAG_END , 0 }
775 DOSBase = TaggedOpenLibrary(TAGGEDOPEN_DOS);
776 if (!DOSBase) {
777 Alert( AN_RAMLib | AG_OpenLib | AO_DOSLib | AT_DeadEnd );
780 if ((ldBase->dl_LDDemonPort = CreateMsgPort()) == NULL )
782 Alert( AN_RAMLib | AG_NoMemory | AT_DeadEnd );
785 FreeSignal(ldBase->dl_LDDemonPort->mp_SigBit);
786 ldBase->dl_LDDemonPort->mp_SigBit = SIGBREAKB_CTRL_F;
788 ldBase->dl_LDHandler.is_Node.ln_Name = (STRPTR)ldDemonName;
789 ldBase->dl_LDHandler.is_Node.ln_Pri = 0;
790 ldBase->dl_LDHandler.is_Code = (VOID_FUNC)LDFlush;
791 ldBase->dl_LDHandler.is_Data = NULL;
793 ldBase->dl_DOSBase = DOSBase;
795 NEWLIST(&ldBase->dl_LDObjectsList);
796 InitSemaphore(&ldBase->dl_LDObjectsListSigSem);
798 SysBase->ex_RamLibPrivate = ldBase;
800 AddMemHandler(&ldBase->dl_LDHandler);
802 #if defined(__AROSEXEC_SMP__)
803 ldBase->dl_ExecLockRes = OpenResource("execlock.resource");
804 #endif
807 * Grab the semaphore ourself. The reason for this is that it will
808 * cause all other tasks to wait until we have finished initialising
809 * before they try and open something.
811 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
813 #define SetFunc(offs,ptr) \
814 SetFunction(&SysBase->LibNode, (-offs)*(LONG)LIB_VECTSIZE, \
815 AROS_SLIB_ENTRY(ptr,Dos,0))
817 /* Do not set the vectors until you have initialised everything else. */
818 ldBase->__OpenLibrary = SetFunc(92, OpenLibrary);
819 ldBase->__OpenDevice = SetFunc(74, OpenDevice);
820 (void)SetFunc(69, CloseLibrary);
821 (void)SetFunc(75, CloseDevice);
822 (void)SetFunc(67, RemLibrary);
823 (void)SetFunc(73, RemLibrary);
825 if( !(ldBase->dl_LDDemonTask = CreateNewProc((struct TagItem *)tags)) )
827 Alert( AT_DeadEnd | AN_RAMLib | AG_ProcCreate );
830 /* Fix up the MsgPort */
832 ldBase->dl_LDDemonPort->mp_SigTask = ldBase->dl_LDDemonTask;
834 /* Then unlock the semaphore to allow other processes to run. */
835 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
837 return TRUE;
840 ADD2INITLIB(LDDemon_Init, 0)