start service tasks separately in-case platforms need to perform additional set-up...
[AROS.git] / rom / lddemon / lddemon.c
blob229b9bfbfb2fa537578411fb663338a844889050
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Loader for shared libraries and devices.
6 */
8 #include <aros/asmcall.h>
9 #include <aros/debug.h>
10 #include <aros/symbolsets.h>
11 #include <exec/execbase.h>
12 #include <exec/resident.h>
13 #include <exec/memory.h>
14 #include <exec/errors.h>
15 #include <exec/devices.h>
16 #include <exec/ports.h>
17 #include <exec/alerts.h>
18 #include <exec/tasks.h>
19 #include <dos/dos.h>
20 #include <dos/dosextens.h>
21 #include <dos/dostags.h>
22 #include <proto/exec.h>
23 #include <proto/dos.h>
25 #include <stddef.h>
26 #include <string.h>
28 #include "lddemon.h"
30 #ifdef __mc68000
31 #define INIT_IN_LDDEMON_CONTEXT 1
32 #else
33 #define INIT_IN_LDDEMON_CONTEXT 0
34 #endif
36 #define CHECK_DEPENDENCY 1
38 /* Please leave them here! They are needed on Linux-M68K */
39 AROS_LD2(struct Library *, OpenLibrary,
40 AROS_LDA(STRPTR, libname, A1),
41 AROS_LDA(ULONG, version, D0),
42 struct ExecBase *, SysBase, 0, Dos);
43 AROS_LD4(LONG, OpenDevice,
44 AROS_LDA(STRPTR, devname, A0),
45 AROS_LDA(IPTR, unitNumber, D0),
46 AROS_LDA(struct IORequest *, iORequest, A1),
47 AROS_LDA(ULONG, flags, D1),
48 struct ExecBase *, SysBase, 0, Dos);
49 AROS_LD1(void, CloseLibrary,
50 AROS_LDA(struct Library *, library, A1),
51 struct ExecBase *, SysBase, 0, Dos);
52 AROS_LD1(void, CloseDevice,
53 AROS_LDA(struct IORequest *, iORequest, A1),
54 struct ExecBase *, SysBase, 0, Dos);
55 AROS_LD1(void, RemLibrary,
56 AROS_LDA(struct Library *, library, A1),
57 struct ExecBase *, SysBase, 0, Dos);
59 struct LDDMsg
61 struct Message ldd_Msg; /* Message link */
62 struct MsgPort ldd_ReplyPort; /* Callers ReplyPort */
64 STRPTR ldd_Name; /* Name of thing to load */
66 STRPTR ldd_BaseDir; /* Base directory to load from */
67 #if INIT_IN_LDDEMON_CONTEXT
68 struct Library *ldd_Return; /* Loaded and initialized Library */
69 struct List *ldd_List; /* List to add */
70 #else
71 BPTR ldd_Return; /* Loaded seglist */
72 #endif
75 static const char ldDemonName[] = "Lib & Dev Loader Daemon";
78 BPTR LDLoad( caller, name, basedir, DOSBase )
79 Try and load a segment from disk for the object <name>, relative
80 to directory <basedir>. Will also try <caller>'s current and home
81 directories.
83 static BPTR LDLoad(struct Process *caller, STRPTR name, STRPTR basedir,
84 struct Library *DOSBase, struct ExecBase *SysBase)
86 struct Process *me = (struct Process *)FindTask(NULL);
87 BPTR seglist = BNULL;
88 STRPTR path;
89 ULONG pathLen;
90 int delimPos;
93 If the caller was a process, we have more scope for loading
94 libraries. We can load them from the callers current directory,
95 or from the PROGDIR: assign. These could both be the same
96 though.
98 D(bug(
99 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
100 caller, caller->pr_Task.tc_Node.ln_Name, name, basedir
103 if (strncmp(name, "PROGDIR:", 8) == 0)
105 /* Special case for explicit PROGDIR-based path */
106 if (caller->pr_Task.tc_Node.ln_Type == NT_PROCESS)
108 if (caller->pr_HomeDir != BNULL)
110 BPTR oldHomeDir = me->pr_HomeDir;
111 D(bug("[LDLoad] Trying homedir\n"));
112 /* Temporarily override pr_HomeDir to let GetDeviceProc handle
113 PROGDIR: case correctly while opening library file */
114 me->pr_HomeDir = caller->pr_HomeDir;
115 seglist = LoadSeg(name);
116 me->pr_HomeDir = oldHomeDir;
120 else if (!strstr(name, ":")) {
121 delimPos = strlen(basedir);
122 pathLen = delimPos + strlen(name) + 2;
123 path = AllocMem(pathLen, MEMF_ANY);
124 if (path) {
125 strcpy(path, basedir);
126 path[delimPos] = '/';
127 strcpy(&path[delimPos + 1], name);
129 if (caller->pr_Task.tc_Node.ln_Type == NT_PROCESS)
131 /* Try the current directory of the caller */
133 D(bug("[LDLoad] Process\n"));
134 me->pr_CurrentDir = caller->pr_CurrentDir;
135 D(bug("[LDLoad] Trying currentdir\n"));
136 seglist = LoadSeg(name);
137 if ((!seglist) && path)
138 seglist = LoadSeg(path);
140 /* The the program directory of the caller */
141 if((!seglist) && (caller->pr_HomeDir != BNULL))
143 D(bug("[LDLoad] Trying homedir\n"));
144 me->pr_CurrentDir = caller->pr_HomeDir;
145 seglist = LoadSeg(name);
146 if ((!seglist) && path)
147 seglist = LoadSeg(path);
151 if (path) {
152 if (!seglist) {
153 /* Nup, let's try the default directory as supplied. */
154 D(bug("[LDLoad] Trying defaultdir\n"));
155 path[delimPos] = ':';
156 seglist = LoadSeg(path);
158 FreeMem(path, pathLen);
160 } else
161 seglist = LoadSeg(name);
163 return seglist;
167 Library *LDInit(seglist, DOSBase)
168 Initialise the library.
170 static struct Library *LDInit(BPTR seglist, struct List *list, STRPTR resname, struct ExecBase *SysBase)
172 struct Node *node = NULL;
173 BPTR seg = seglist;
175 /* we may not have any extension fields */
176 const int sizeofresident = offsetof(struct Resident, rt_Init) + sizeof(APTR);
178 while(seg)
180 STRPTR addr = (STRPTR)((IPTR)BADDR(seg) - sizeof(ULONG));
181 ULONG size = *(ULONG *)addr;
183 for(
184 addr += sizeof(BPTR) + sizeof(ULONG),
185 size -= sizeof(BPTR) + sizeof(ULONG);
186 size >= sizeofresident;
187 size -= 2, addr += 2
188 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
191 struct Resident *res = (struct Resident *)addr;
192 if( res->rt_MatchWord == RTC_MATCHWORD
193 && res->rt_MatchTag == res )
195 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
196 /* AOS compatibility requirement.
197 * Ramlib ignores InitResident() return code.
198 * After InitResident() it checks if lib/dev appeared
199 * in Exec lib/dev list via FindName().
201 * Evidently InitResident()'s return code was not
202 * reliable for some early AOS libraries.
204 Forbid();
205 InitResident(res, seglist);
206 node = FindName(list, res->rt_Name);
207 Permit();
208 D(bug("[LDInit] Done calling InitResident(%p) on %s, seg %p, node %p\n", res, res->rt_Name, BADDR(seglist), node));
210 return (struct Library*)node;
213 seg = *(BPTR *)BADDR(seg);
215 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
216 #ifdef __mc68000
217 /* If struct Resident was not found, just run the code. SegList in A0.
218 * Required to load WB1.x devs:narrator.device. */
219 Forbid();
220 AROS_UFC1NR(void, BADDR(seglist) + sizeof(ULONG), AROS_UFCA(BPTR, seglist, A0));
221 node = FindName(list, resname);
222 Permit();
223 D(bug("[LDInit] Done direct calling %s, seg %p, node %p\n", resname, BADDR(seglist), node));
224 #endif
225 return (struct Library*)node;
228 static struct Library *CallLDInit(BPTR seglist, struct List *list, STRPTR resname, struct Library *DOSBase, struct ExecBase *SysBase)
230 struct Library *tmplib;
231 if (!seglist)
232 return NULL;
233 tmplib = LDInit(seglist, list, resname, SysBase);
234 if (!tmplib)
235 UnLoadSeg(seglist);
236 return tmplib;
239 #define ExecOpenLibrary(libname, version) \
240 AROS_CALL2(struct Library *, ldBase->__OpenLibrary, \
241 AROS_LCA(STRPTR, libname, A1), \
242 AROS_LCA(ULONG, version, D0), \
243 struct ExecBase *, SysBase)
245 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
246 AROS_CALL4(LONG, ldBase->__OpenDevice, \
247 AROS_LCA(STRPTR, devname, A0), \
248 AROS_LCA(IPTR, unitNumber, D0), \
249 AROS_LCA(struct IORequest *, iORequest, A1), \
250 AROS_LCA(ULONG, flags, D1), \
251 struct ExecBase *, SysBase)
253 struct LDObjectNode
255 struct Node ldon_Node;
256 struct SignalSemaphore ldon_SigSem;
257 ULONG ldon_AccessCount;
258 #if CHECK_DEPENDENCY
259 struct Task *ldon_FirstLocker;
260 #endif
263 static struct LDObjectNode *LDNewObjectNode(STRPTR name, struct ExecBase *SysBase)
265 struct LDObjectNode *ret = AllocVec(sizeof(struct LDObjectNode), MEMF_ANY);
266 if (ret)
268 ULONG len = strlen(name);
269 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
270 if (dupname)
272 CopyMem(name, dupname, len);
273 dupname[len] = '\0';
274 ret->ldon_Node.ln_Name = dupname;
275 InitSemaphore(&ret->ldon_SigSem);
276 ret->ldon_AccessCount = 0;
278 #if CHECK_DEPENDENCY
279 ret->ldon_FirstLocker = FindTask(0);
280 #endif
282 return ret;
284 FreeVec(ret);
287 return NULL;
290 static void ProcessLDMessage(struct LDDemonBase *ldBase, struct LDDMsg *ldd, struct Library *DOSBase, struct ExecBase *SysBase);
292 static struct LDObjectNode *LDRequestObject(STRPTR libname, ULONG version, STRPTR dir, struct List *list, struct ExecBase *SysBase)
294 /* We use FilePart() because the liblist is built from resident IDs,
295 and contain no path. Eg. The user can request gadgets/foo.gadget,
296 but the resident only contains foo.gadget
298 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
299 struct Library *DOSBase = ldBase->dl_DOSBase;
300 STRPTR stripped_libname = FilePart(libname);
301 struct Library *tmplib;
302 struct LDObjectNode *object;
305 We get the DOS semaphore to prevent the following:
306 - task 1 tries to open foobar.library, needs to load it from disk...
307 - task 1 Permit()'s (since it's not doing list things)
308 - task switch (whilst LDDemon MAY get process next it might not)
309 - task 2 tries to open foobar.library, needs to load it from disk...
310 - it also requests LDDemon to open foobar.library, so it is now
311 trying to open it twice
313 We block all OpenLibrary() callers from searching the list until
314 all the other OpenLibrary() callers have returned. That way,
315 task #2 won't ask for foobar.library until task #1 has got its
316 response back from the LDDemon process.
318 falemagn: I changed the implementation of all that.
319 There's a list of "LDObjectNodes", that contain the name
320 of the object being opened. Since the problem is that more
321 processes can attempt to open the same device/library. Instead of
322 locking a global semaphore until the opening is done, we lock a
323 per-object semaphore, so that others libraries/devices can be opened
324 in the meantime. Before, a deadlock could happen if there was a
325 situation like this:
327 Process A opens L --------> LDDemon loads L and locks sem S
330 1 / \ 3
332 / 2 \
333 L spawns a process B and ----------> The process opens
334 waits for it to respond a library but gets loked
335 to a message <----/---- because sem S is locked
339 Proces B will never
340 respond to L.
342 Hopefully this won't happen anymore now.
344 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
346 object = (struct LDObjectNode *)FindName(&ldBase->dl_LDObjectsList, stripped_libname);
347 if (!object)
349 object = LDNewObjectNode(stripped_libname, SysBase);
350 if (object)
352 AddTail(&ldBase->dl_LDObjectsList, (struct Node *)object);
356 if (object)
358 object->ldon_AccessCount += 1;
361 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
363 if (!object)
364 return NULL;
366 ObtainSemaphore(&object->ldon_SigSem);
368 /* Try to find the resident in the list */
369 tmplib = (struct Library *)FindName(list, stripped_libname);
371 if (!tmplib)
373 /* Try to load from disk if not found */
374 struct LDDMsg ldd;
376 ldd.ldd_ReplyPort.mp_SigBit = SIGB_SINGLE;
377 ldd.ldd_ReplyPort.mp_SigTask = FindTask(NULL);
378 ldd.ldd_ReplyPort.mp_Flags = PA_SIGNAL;
379 ldd.ldd_ReplyPort.mp_Node.ln_Type = NT_MSGPORT;
381 NEWLIST(&ldd.ldd_ReplyPort.mp_MsgList);
383 ldd.ldd_Msg.mn_Node.ln_Type = NT_MESSAGE;
384 ldd.ldd_Msg.mn_Length = sizeof(struct LDDMsg);
385 ldd.ldd_Msg.mn_ReplyPort = &ldd.ldd_ReplyPort;
387 ldd.ldd_Name = libname;
388 ldd.ldd_BaseDir = dir;
389 #if INIT_IN_LDDEMON_CONTEXT
390 ldd.ldd_List = list;
391 #endif
393 D(bug("[LDCaller] Sending request for %s, InLDProcess %d\n",
394 stripped_libname, (struct Process*)FindTask(NULL) == ldBase->dl_LDDemonTask));
396 #if INIT_IN_LDDEMON_CONTEXT
397 /* Direct call if already in LDDemon context */
398 if ((struct Process*)FindTask(NULL) == ldBase->dl_LDDemonTask) {
399 ProcessLDMessage(ldBase, &ldd, DOSBase, SysBase);
400 } else
401 #endif
403 SetSignal(0, SIGF_SINGLE);
404 PutMsg(ldBase->dl_LDDemonPort, (struct Message *)&ldd);
405 WaitPort(&ldd.ldd_ReplyPort);
408 D(bug("[LDCaller] Returned 0x%p\n", ldd.ldd_Return));
410 #if INIT_IN_LDDEMON_CONTEXT
411 tmplib = ldd.ldd_Return;
412 #else
413 tmplib = CallLDInit(ldd.ldd_Return, list, stripped_libname, DOSBase, SysBase);
414 #endif
417 if (!tmplib)
420 * The library is not on disk so check Resident List.
421 * It can be there if it is resident but was flushed.
423 struct Resident *resident = FindResident(stripped_libname);
426 * Check if the resident is of required type and version is correct.
427 * This relies on the fact that lh_Type is set correctly for exec lists.
428 * In AROS this is true (see rom/exec/prepareexecbase.c).
430 if (resident && (resident->rt_Type == list->lh_Type) && (resident->rt_Version >= version))
431 InitResident(resident, BNULL);
434 return object;
437 static void LDReleaseObject(struct LDObjectNode *object, struct ExecBase *SysBase)
439 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
442 Release the semaphore here, after calling Open vector. This
443 means that library open is singlethreaded by the semaphore.
444 It also handles circular dependant libraries. (Won't deadlock),
445 and recursive OpenLibrary calls (Semaphores nest when obtained
446 several times in a row by the same task).
449 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
451 if (--(object->ldon_AccessCount) == 0)
453 Remove((struct Node *)object);
455 * CHECKME: In LDRequestObject() we obtain the object semaphore also on a new object.
456 * So shouldn't we release it here too ?
459 FreeVec(object->ldon_Node.ln_Name);
460 FreeVec(object);
462 else
463 ReleaseSemaphore(&object->ldon_SigSem);
465 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
468 AROS_LH2(struct Library *, OpenLibrary,
469 AROS_LHA(STRPTR, libname, A1),
470 AROS_LHA(ULONG, version, D0),
471 struct ExecBase *, SysBase, 0, Dos)
473 AROS_LIBFUNC_INIT
475 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
476 struct Library *library;
477 struct LDObjectNode *object = LDRequestObject(libname, version, "libs", &SysBase->LibList, SysBase);
479 if (!object)
480 return NULL;
482 /* Call the EXEC's OpenLibrary function */
483 library = ExecOpenLibrary(object->ldon_Node.ln_Name, version);
485 LDReleaseObject(object, SysBase);
487 return library;
489 AROS_LIBFUNC_EXIT
492 AROS_LH4(LONG, OpenDevice,
493 AROS_LHA(STRPTR, devname, A0),
494 AROS_LHA(IPTR, unitNumber, D0),
495 AROS_LHA(struct IORequest *, iORequest, A1),
496 AROS_LHA(ULONG, flags, D1),
497 struct ExecBase *, SysBase, 0, Dos)
499 AROS_LIBFUNC_INIT
501 struct LDObjectNode *object;
502 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
504 object = LDRequestObject(devname, 0, "devs", &SysBase->DeviceList, SysBase);
505 if (object)
507 /* Call exec.library/OpenDevice(), it will do the job */
508 ExecOpenDevice(object->ldon_Node.ln_Name, unitNumber, iORequest, flags);
509 LDReleaseObject(object, SysBase);
511 else
513 iORequest->io_Error = IOERR_OPENFAIL;
514 iORequest->io_Device = NULL;
515 iORequest->io_Unit = NULL;
518 D(bug("[LDCaller] Open result: %d\n", iORequest->io_Error));
520 return iORequest->io_Error;
522 AROS_LIBFUNC_EXIT
525 AROS_LH1(void, CloseLibrary,
526 AROS_LHA(struct Library *, library, A1),
527 struct ExecBase *, SysBase, 0, Dos)
529 AROS_LIBFUNC_INIT
531 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
532 struct Library *DOSBase = ldBase->dl_DOSBase;
533 BPTR seglist;
535 if( library != NULL )
537 Forbid();
538 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
539 if( seglist )
541 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
543 /* Safe to call from a Task */
544 UnLoadSeg(seglist);
546 Permit();
549 AROS_LIBFUNC_EXIT
552 AROS_LH1(void, CloseDevice,
553 AROS_LHA(struct IORequest *, iORequest, A1),
554 struct ExecBase *, SysBase, 0, Dos)
556 AROS_LIBFUNC_INIT
557 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
558 struct Library *DOSBase = ldBase->dl_DOSBase;
559 BPTR seglist = BNULL;
561 Forbid();
562 if( iORequest->io_Device != NULL )
564 seglist = AROS_LVO_CALL1(BPTR,
565 AROS_LCA(struct IORequest *, iORequest, A1),
566 struct Device *, iORequest->io_Device, 2, );
567 iORequest->io_Device=(struct Device *)-1;
568 if( seglist )
570 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
571 UnLoadSeg(seglist);
574 Permit();
575 AROS_LIBFUNC_EXIT
578 AROS_LH1(void, RemLibrary,
579 AROS_LHA(struct Library *, library, A1),
580 struct ExecBase *, SysBase, 0, Dos)
582 AROS_LIBFUNC_INIT
584 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
585 struct Library *DOSBase = ldBase->dl_DOSBase;
586 BPTR seglist;
588 Forbid();
589 /* calling ExpungeLib: library ends up in D0 and A6 for compatibility */
590 seglist = AROS_CALL1(BPTR, __AROS_GETVECADDR(library, 3),
591 AROS_LCA(struct Library *, library, D0),
592 struct Library *, library
594 if( seglist )
596 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
597 UnLoadSeg(seglist);
599 Permit();
601 AROS_LIBFUNC_EXIT
604 AROS_UFH3(LONG, LDFlush,
605 AROS_UFHA(struct MemHandlerData *, lmhd, A0),
606 AROS_UFHA(APTR, data, A1),
607 AROS_UFHA(struct ExecBase *, SysBase, A6)
610 AROS_USERFUNC_INIT
612 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
613 struct Library *library;
615 D(bug("[LDDemon] Flush called\n"));
616 ldBase->dl_LDReturn = MEM_DID_NOTHING;
618 /* Forbid() is already done, but I don't want to rely on it. */
619 Forbid();
621 /* Follow the linked list of shared libraries. */
622 library = (struct Library *)SysBase->LibList.lh_Head;
623 while(library->lib_Node.ln_Succ != NULL)
625 /* Flush libraries with a 0 open count */
626 if( ! library->lib_OpenCnt )
628 /* the library list node will be wiped from memory */
629 struct Library *nextLib = (struct Library *)library->lib_Node.ln_Succ;
630 RemLibrary(library);
631 /* Did it really go away? */
632 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
634 /* Yes! Return it. */
635 Permit();
636 return MEM_TRY_AGAIN;
638 library = nextLib;
640 else
642 /* Go on to next library. */
643 library = (struct Library *)library->lib_Node.ln_Succ;
647 /* Do the same with the device list. */
648 library = (struct Library *)SysBase->DeviceList.lh_Head;
649 while(library->lib_Node.ln_Succ != NULL)
651 /* Flush libraries with a 0 open count */
652 if( ! library->lib_OpenCnt )
654 struct Library *nextDev = (struct Library *)library->lib_Node.ln_Succ;
655 RemDevice((struct Device *)library);
656 /* Did it really go away? */
657 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
659 /* Yes! Return it. */
660 Permit();
661 return MEM_TRY_AGAIN;
663 library = nextDev;
665 else
667 /* Go on to next library. */
668 library = (struct Library *)library->lib_Node.ln_Succ;
671 Permit();
672 return MEM_DID_NOTHING;
674 AROS_USERFUNC_EXIT
677 static void ProcessLDMessage(struct LDDemonBase *ldBase, struct LDDMsg *ldd, struct Library *DOSBase, struct ExecBase *SysBase)
679 BPTR seglist;
680 D(bug("[LDDemon] Got a request for %s in %s\n", ldd->ldd_Name, ldd->ldd_BaseDir));
682 seglist = LDLoad(ldd->ldd_ReplyPort.mp_SigTask, ldd->ldd_Name, ldd->ldd_BaseDir, DOSBase, SysBase);
684 #if INIT_IN_LDDEMON_CONTEXT
685 ldd->ldd_Return = CallLDInit(seglist, ldd->ldd_List, FilePart(ldd->ldd_Name), DOSBase, SysBase);
686 D(bug("[LDDemon] Replying with %p as result, seglist was %p\n", ldd->ldd_Return, seglist));
687 #else
688 ldd->ldd_Return = seglist;
689 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
690 #endif
694 void LDDemon()
695 The LDDemon process entry. Sits around and does nothing until a
696 request for a library comes, when it will then find the library
697 and hopefully open it.
699 static AROS_PROCH(LDDemon, argptr, argsize, SysBase)
701 AROS_PROCFUNC_INIT
703 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
704 struct Library *DOSBase = ldBase->dl_DOSBase;
705 struct LDDMsg *ldd;
707 for(;;)
709 WaitPort(ldBase->dl_LDDemonPort);
710 while( (ldd = (struct LDDMsg *)GetMsg(ldBase->dl_LDDemonPort)) )
712 ProcessLDMessage(ldBase, ldd, DOSBase, SysBase);
713 ReplyMsg((struct Message *)ldd);
714 } /* messages available */
717 /* lddemon died */
718 return 0;
720 AROS_PROCFUNC_EXIT
723 static ULONG LDDemon_Init(struct LDDemonBase *ldBase)
725 struct Library *DOSBase;
726 struct TagItem tags[] =
728 { NP_Entry, (IPTR)LDDemon },
729 { NP_Input, 0 },
730 { NP_Output, 0 },
731 { NP_WindowPtr, -1 },
732 { NP_Name, (IPTR)ldDemonName },
733 { NP_Priority, 5 },
734 { TAG_END , 0 }
737 DOSBase = TaggedOpenLibrary(TAGGEDOPEN_DOS);
738 if (!DOSBase) {
739 Alert( AN_RAMLib | AG_OpenLib | AO_DOSLib | AT_DeadEnd );
742 if ((ldBase->dl_LDDemonPort = CreateMsgPort()) == NULL )
744 Alert( AN_RAMLib | AG_NoMemory | AT_DeadEnd );
747 FreeSignal(ldBase->dl_LDDemonPort->mp_SigBit);
748 ldBase->dl_LDDemonPort->mp_SigBit = SIGBREAKB_CTRL_F;
750 ldBase->dl_LDHandler.is_Node.ln_Name = (STRPTR)ldDemonName;
751 ldBase->dl_LDHandler.is_Node.ln_Pri = 0;
752 ldBase->dl_LDHandler.is_Code = (VOID_FUNC)LDFlush;
753 ldBase->dl_LDHandler.is_Data = NULL;
755 ldBase->dl_DOSBase = DOSBase;
757 NEWLIST(&ldBase->dl_LDObjectsList);
758 InitSemaphore(&ldBase->dl_LDObjectsListSigSem);
760 SysBase->ex_RamLibPrivate = ldBase;
762 AddMemHandler(&ldBase->dl_LDHandler);
765 * Grab the semaphore ourself. The reason for this is that it will
766 * cause all other tasks to wait until we have finished initialising
767 * before they try and open something.
769 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
771 #define SetFunc(offs,ptr) \
772 SetFunction(&SysBase->LibNode, (-offs)*(LONG)LIB_VECTSIZE, \
773 AROS_SLIB_ENTRY(ptr,Dos,0))
775 /* Do not set the vectors until you have initialised everything else. */
776 ldBase->__OpenLibrary = SetFunc(92, OpenLibrary);
777 ldBase->__OpenDevice = SetFunc(74, OpenDevice);
778 (void)SetFunc(69, CloseLibrary);
779 (void)SetFunc(75, CloseDevice);
780 (void)SetFunc(67, RemLibrary);
781 (void)SetFunc(73, RemLibrary);
783 if( !(ldBase->dl_LDDemonTask = CreateNewProc((struct TagItem *)tags)) )
785 Alert( AT_DeadEnd | AN_RAMLib | AG_ProcCreate );
788 /* Fix up the MsgPort */
790 ldBase->dl_LDDemonPort->mp_SigTask = ldBase->dl_LDDemonTask;
792 /* Then unlock the semaphore to allow other processes to run. */
793 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
795 return TRUE;
798 ADD2INITLIB(LDDemon_Init, 0)