Use AROS_LE2WORD when appropriate
[AROS.git] / rom / lddemon / lddemon.c
blob450973a4b1384c5232fbda21f930693e55bd4b4e
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 #define CHECK_DEPENDENCY 1
32 /* Please leave them here! They are needed on Linux-M68K */
33 AROS_LD2(struct Library *, OpenLibrary,
34 AROS_LDA(STRPTR, libname, A1),
35 AROS_LDA(ULONG, version, D0),
36 struct ExecBase *, SysBase, 0, Dos);
37 AROS_LD4(LONG, OpenDevice,
38 AROS_LDA(STRPTR, devname, A0),
39 AROS_LDA(IPTR, unitNumber, D0),
40 AROS_LDA(struct IORequest *, iORequest, A1),
41 AROS_LDA(ULONG, flags, D1),
42 struct ExecBase *, SysBase, 0, Dos);
43 AROS_LD1(void, CloseLibrary,
44 AROS_LDA(struct Library *, library, A1),
45 struct ExecBase *, SysBase, 0, Dos);
46 AROS_LD1(void, CloseDevice,
47 AROS_LDA(struct IORequest *, iORequest, A1),
48 struct ExecBase *, SysBase, 0, Dos);
49 AROS_LD1(void, RemLibrary,
50 AROS_LDA(struct Library *, library, A1),
51 struct ExecBase *, SysBase, 0, Dos);
53 struct LDDMsg
55 struct Message ldd_Msg; /* Message link */
56 struct MsgPort ldd_ReplyPort; /* Callers ReplyPort */
58 STRPTR ldd_Name; /* Name of thing to load */
60 STRPTR ldd_BaseDir; /* Base directory to load from */
61 BPTR ldd_Return; /* Loaded seglist */
64 static const char ldDemonName[] = "Lib & Dev Loader Daemon";
67 BPTR LDLoad( caller, name, basedir, DOSBase )
68 Try and load a segment from disk for the object <name>, relative
69 to directory <basedir>. Will also try <caller>'s current and home
70 directories.
72 static BPTR LDLoad(struct Process *caller, STRPTR name, STRPTR basedir,
73 struct Library *DOSBase, struct ExecBase *SysBase)
75 struct Process *me = (struct Process *)FindTask(NULL);
76 BPTR seglist = BNULL;
77 STRPTR path;
78 ULONG pathLen;
79 int delimPos;
82 If the caller was a process, we have more scope for loading
83 libraries. We can load them from the callers current directory,
84 or from the PROGDIR: assign. These could both be the same
85 though.
87 D(bug(
88 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
89 caller, caller->pr_Task.tc_Node.ln_Name, name, basedir
90 ));
92 if (strncmp(name, "PROGDIR:", 8) == 0)
94 /* Special case for explicit PROGDIR-based path */
95 if (caller->pr_Task.tc_Node.ln_Type == NT_PROCESS)
97 if (caller->pr_HomeDir != BNULL)
99 BPTR oldHomeDir = me->pr_HomeDir;
100 D(bug("[LDLoad] Trying homedir\n"));
101 /* Temporarily override pr_HomeDir to let GetDeviceProc handle
102 PROGDIR: case correctly while opening library file */
103 me->pr_HomeDir = caller->pr_HomeDir;
104 seglist = LoadSeg(name);
105 me->pr_HomeDir = oldHomeDir;
109 else if (!strstr(name, ":")) {
110 delimPos = strlen(basedir);
111 pathLen = delimPos + strlen(name) + 2;
112 path = AllocMem(pathLen, MEMF_ANY);
113 if (path) {
114 strcpy(path, basedir);
115 path[delimPos] = '/';
116 strcpy(&path[delimPos + 1], name);
118 if (caller->pr_Task.tc_Node.ln_Type == NT_PROCESS)
120 /* Try the current directory of the caller */
122 D(bug("[LDLoad] Process\n"));
123 me->pr_CurrentDir = caller->pr_CurrentDir;
124 D(bug("[LDLoad] Trying currentdir\n"));
125 seglist = LoadSeg(name);
126 if ((!seglist) && path)
127 seglist = LoadSeg(path);
129 /* The the program directory of the caller */
130 if((!seglist) && (caller->pr_HomeDir != BNULL))
132 D(bug("[LDLoad] Trying homedir\n"));
133 me->pr_CurrentDir = caller->pr_HomeDir;
134 seglist = LoadSeg(name);
135 if ((!seglist) && path)
136 seglist = LoadSeg(path);
140 if (path) {
141 if (!seglist) {
142 /* Nup, let's try the default directory as supplied. */
143 D(bug("[LDLoad] Trying defaultdir\n"));
144 path[delimPos] = ':';
145 seglist = LoadSeg(path);
147 FreeMem(path, pathLen);
149 } else
150 seglist = LoadSeg(name);
152 return seglist;
156 Library *LDInit(seglist, DOSBase)
157 Initialise the library.
159 static struct Library *LDInit(BPTR seglist, struct List *list, STRPTR resname, struct ExecBase *SysBase)
161 struct Node *node = NULL;
162 BPTR seg = seglist;
164 /* we may not have any extension fields */
165 const int sizeofresident = offsetof(struct Resident, rt_Init) + sizeof(APTR);
167 while(seg)
169 STRPTR addr = (STRPTR)((IPTR)BADDR(seg) - sizeof(ULONG));
170 ULONG size = *(ULONG *)addr;
172 for(
173 addr += sizeof(BPTR) + sizeof(ULONG),
174 size -= sizeof(BPTR) + sizeof(ULONG);
175 size >= sizeofresident;
176 size -= 2, addr += 2
177 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
180 struct Resident *res = (struct Resident *)addr;
181 if( res->rt_MatchWord == RTC_MATCHWORD
182 && res->rt_MatchTag == res )
184 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
185 /* AOS compatibility requirement.
186 * Ramlib ignores InitResident() return code.
187 * After InitResident() it checks if lib/dev appeared
188 * in Exec lib/dev list via FindName().
190 * Evidently InitResident()'s return code was not
191 * reliable for some early AOS libraries.
193 Forbid();
194 InitResident(res, seglist);
195 node = FindName(list, res->rt_Name);
196 Permit();
197 D(bug("[LDInit] Done calling InitResident(%p) on %s, seg %p, node %p\n", res, res->rt_Name, BADDR(seglist), node));
199 return (struct Library*)node;
202 seg = *(BPTR *)BADDR(seg);
204 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
205 #ifdef __mc68000
206 /* If struct Resident was not found, just run the code. SegList in A0.
207 * Required to load WB1.x devs:narrator.device. */
208 Forbid();
209 AROS_UFC1NR(void, BADDR(seglist) + sizeof(ULONG), AROS_UFCA(BPTR, seglist, A0));
210 node = FindName(list, resname);
211 Permit();
212 D(bug("[LDInit] Done direct calling %s, seg %p, node %p\n", resname, BADDR(seglist), node));
213 #endif
214 return (struct Library*)node;
217 #define ExecOpenLibrary(libname, version) \
218 AROS_CALL2(struct Library *, ldBase->__OpenLibrary, \
219 AROS_LCA(STRPTR, libname, A1), \
220 AROS_LCA(ULONG, version, D0), \
221 struct ExecBase *, SysBase)
223 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
224 AROS_CALL4(LONG, ldBase->__OpenDevice, \
225 AROS_LCA(STRPTR, devname, A0), \
226 AROS_LCA(IPTR, unitNumber, D0), \
227 AROS_LCA(struct IORequest *, iORequest, A1), \
228 AROS_LCA(ULONG, flags, D1), \
229 struct ExecBase *, SysBase)
231 struct LDObjectNode
233 struct Node ldon_Node;
234 struct SignalSemaphore ldon_SigSem;
235 ULONG ldon_AccessCount;
236 #if CHECK_DEPENDENCY
237 struct Task *ldon_FirstLocker;
238 #endif
241 static struct LDObjectNode *LDNewObjectNode(STRPTR name, struct ExecBase *SysBase)
243 struct LDObjectNode *ret = AllocVec(sizeof(struct LDObjectNode), MEMF_ANY);
244 if (ret)
246 ULONG len = strlen(name);
247 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
248 if (dupname)
250 CopyMem(name, dupname, len);
251 dupname[len] = '\0';
252 ret->ldon_Node.ln_Name = dupname;
253 InitSemaphore(&ret->ldon_SigSem);
254 ret->ldon_AccessCount = 0;
256 #if CHECK_DEPENDENCY
257 ret->ldon_FirstLocker = FindTask(0);
258 #endif
260 return ret;
262 FreeVec(ret);
265 return NULL;
268 static struct LDObjectNode *LDRequestObject(STRPTR libname, ULONG version, STRPTR dir, struct List *list, struct ExecBase *SysBase)
270 /* We use FilePart() because the liblist is built from resident IDs,
271 and contain no path. Eg. The user can request gadgets/foo.gadget,
272 but the resident only contains foo.gadget
274 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
275 struct Library *DOSBase = ldBase->dl_DOSBase;
276 STRPTR stripped_libname = FilePart(libname);
277 struct Library *tmplib;
278 struct LDObjectNode *object;
281 We get the DOS semaphore to prevent the following:
282 - task 1 tries to open foobar.library, needs to load it from disk...
283 - task 1 Permit()'s (since it's not doing list things)
284 - task switch (whilst LDDemon MAY get process next it might not)
285 - task 2 tries to open foobar.library, needs to load it from disk...
286 - it also requests LDDemon to open foobar.library, so it is now
287 trying to open it twice
289 We block all OpenLibrary() callers from searching the list until
290 all the other OpenLibrary() callers have returned. That way,
291 task #2 won't ask for foobar.library until task #1 has got its
292 response back from the LDDemon process.
294 falemagn: I changed the implementation of all that.
295 There's a list of "LDObjectNodes", that contain the name
296 of the object being opened. Since the problem is that more
297 processes can attempt to open the same device/library. Instead of
298 locking a global semaphore until the opening is done, we lock a
299 per-object semaphore, so that others libraries/devices can be opened
300 in the meantime. Before, a deadlock could happen if there was a
301 situation like this:
303 Process A opens L --------> LDDemon loads L and locks sem S
306 1 / \ 3
308 / 2 \
309 L spawns a process B and ----------> The process opens
310 waits for it to respond a library but gets loked
311 to a message <----/---- because sem S is locked
315 Proces B will never
316 respond to L.
318 Hopefully this won't happen anymore now.
320 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
322 object = (struct LDObjectNode *)FindName(&ldBase->dl_LDObjectsList, stripped_libname);
323 if (!object)
325 object = LDNewObjectNode(stripped_libname, SysBase);
326 if (object)
328 AddTail(&ldBase->dl_LDObjectsList, (struct Node *)object);
332 if (object)
334 object->ldon_AccessCount += 1;
337 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
339 if (!object)
340 return NULL;
342 ObtainSemaphore(&object->ldon_SigSem);
344 /* Try to find the resident in the list */
345 tmplib = (struct Library *)FindName(list, stripped_libname);
347 if (!tmplib)
349 /* Try to load from disk if not found */
350 struct LDDMsg ldd;
352 ldd.ldd_ReplyPort.mp_SigBit = SIGB_SINGLE;
353 ldd.ldd_ReplyPort.mp_SigTask = FindTask(NULL);
354 ldd.ldd_ReplyPort.mp_Flags = PA_SIGNAL;
355 ldd.ldd_ReplyPort.mp_Node.ln_Type = NT_MSGPORT;
357 NEWLIST(&ldd.ldd_ReplyPort.mp_MsgList);
359 ldd.ldd_Msg.mn_Node.ln_Type = NT_MESSAGE;
360 ldd.ldd_Msg.mn_Length = sizeof(struct LDDMsg);
361 ldd.ldd_Msg.mn_ReplyPort = &ldd.ldd_ReplyPort;
363 ldd.ldd_Name = libname;
364 ldd.ldd_BaseDir = dir;
366 SetSignal(0, SIGF_SINGLE);
367 D(bug("[LDCaller] Sending request for %s\n", stripped_libname));
369 PutMsg(ldBase->dl_LDDemonPort, (struct Message *)&ldd);
370 WaitPort(&ldd.ldd_ReplyPort);
372 D(bug("[LDCaller] Returned 0x%p\n", ldd.ldd_Return));
374 if (ldd.ldd_Return)
376 tmplib = LDInit(ldd.ldd_Return, list, stripped_libname, SysBase);
377 if (!tmplib)
378 UnLoadSeg(ldd.ldd_Return);
382 if (!tmplib)
385 * The library is not on disk so check Resident List.
386 * It can be there if it is resident but was flushed.
388 struct Resident *resident = FindResident(stripped_libname);
391 * Check if the resident is of required type and version is correct.
392 * This relies on the fact that lh_Type is set correctly for exec lists.
393 * In AROS this is true (see rom/exec/prepareexecbase.c).
395 if (resident && (resident->rt_Type == list->lh_Type) && (resident->rt_Version >= version))
396 InitResident(resident, BNULL);
399 return object;
402 static void LDReleaseObject(struct LDObjectNode *object, struct ExecBase *SysBase)
404 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
407 Release the semaphore here, after calling Open vector. This
408 means that library open is singlethreaded by the semaphore.
409 It also handles circular dependant libraries. (Won't deadlock),
410 and recursive OpenLibrary calls (Semaphores nest when obtained
411 several times in a row by the same task).
414 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
416 if (--(object->ldon_AccessCount) == 0)
418 Remove((struct Node *)object);
420 * CHECKME: In LDRequestObject() we obtain the object semaphore also on a new object.
421 * So shouldn't we release it here too ?
424 FreeVec(object->ldon_Node.ln_Name);
425 FreeVec(object);
427 else
428 ReleaseSemaphore(&object->ldon_SigSem);
430 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
433 AROS_LH2(struct Library *, OpenLibrary,
434 AROS_LHA(STRPTR, libname, A1),
435 AROS_LHA(ULONG, version, D0),
436 struct ExecBase *, SysBase, 0, Dos)
438 AROS_LIBFUNC_INIT
440 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
441 struct Library *library;
442 struct LDObjectNode *object = LDRequestObject(libname, version, "libs", &SysBase->LibList, SysBase);
444 if (!object)
445 return NULL;
447 /* Call the EXEC's OpenLibrary function */
448 library = ExecOpenLibrary(object->ldon_Node.ln_Name, version);
450 LDReleaseObject(object, SysBase);
452 return library;
454 AROS_LIBFUNC_EXIT
457 AROS_LH4(LONG, OpenDevice,
458 AROS_LHA(STRPTR, devname, A0),
459 AROS_LHA(IPTR, unitNumber, D0),
460 AROS_LHA(struct IORequest *, iORequest, A1),
461 AROS_LHA(ULONG, flags, D1),
462 struct ExecBase *, SysBase, 0, Dos)
464 AROS_LIBFUNC_INIT
466 struct LDObjectNode *object;
467 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
469 object = LDRequestObject(devname, 0, "devs", &SysBase->DeviceList, SysBase);
470 if (object)
472 /* Call exec.library/OpenDevice(), it will do the job */
473 ExecOpenDevice(object->ldon_Node.ln_Name, unitNumber, iORequest, flags);
474 LDReleaseObject(object, SysBase);
476 else
478 iORequest->io_Error = IOERR_OPENFAIL;
479 iORequest->io_Device = NULL;
480 iORequest->io_Unit = NULL;
483 D(bug("[LDCaller] Open result: %d\n", iORequest->io_Error));
485 return iORequest->io_Error;
487 AROS_LIBFUNC_EXIT
490 AROS_LH1(void, CloseLibrary,
491 AROS_LHA(struct Library *, library, A1),
492 struct ExecBase *, SysBase, 0, Dos)
494 AROS_LIBFUNC_INIT
496 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
497 struct Library *DOSBase = ldBase->dl_DOSBase;
498 BPTR seglist;
500 if( library != NULL )
502 Forbid();
503 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
504 if( seglist )
506 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
508 /* Safe to call from a Task */
509 UnLoadSeg(seglist);
511 Permit();
514 AROS_LIBFUNC_EXIT
517 AROS_LH1(void, CloseDevice,
518 AROS_LHA(struct IORequest *, iORequest, A1),
519 struct ExecBase *, SysBase, 0, Dos)
521 AROS_LIBFUNC_INIT
522 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
523 struct Library *DOSBase = ldBase->dl_DOSBase;
524 BPTR seglist = BNULL;
526 Forbid();
527 if( iORequest->io_Device != NULL )
529 seglist = AROS_LVO_CALL1(BPTR,
530 AROS_LCA(struct IORequest *, iORequest, A1),
531 struct Device *, iORequest->io_Device, 2, );
532 iORequest->io_Device=(struct Device *)-1;
533 if( seglist )
535 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
536 UnLoadSeg(seglist);
539 Permit();
540 AROS_LIBFUNC_EXIT
543 AROS_LH1(void, RemLibrary,
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 Forbid();
554 /* calling ExpungeLib: library ends up in D0 and A6 for compatibility */
555 seglist = AROS_CALL1(BPTR, __AROS_GETVECADDR(library, 3),
556 AROS_LCA(struct Library *, library, D0),
557 struct Library *, library
559 if( seglist )
561 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
562 UnLoadSeg(seglist);
564 Permit();
566 AROS_LIBFUNC_EXIT
569 AROS_UFH3(LONG, LDFlush,
570 AROS_UFHA(struct MemHandlerData *, lmhd, A0),
571 AROS_UFHA(APTR, data, A1),
572 AROS_UFHA(struct ExecBase *, SysBase, A6)
575 AROS_USERFUNC_INIT
577 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
578 struct Library *library;
580 D(bug("[LDDemon] Flush called\n"));
581 ldBase->dl_LDReturn = MEM_DID_NOTHING;
583 /* Forbid() is already done, but I don't want to rely on it. */
584 Forbid();
586 /* Follow the linked list of shared libraries. */
587 library = (struct Library *)SysBase->LibList.lh_Head;
588 while(library->lib_Node.ln_Succ != NULL)
590 /* Flush libraries with a 0 open count */
591 if( ! library->lib_OpenCnt )
593 /* the library list node will be wiped from memory */
594 struct Library *nextLib = (struct Library *)library->lib_Node.ln_Succ;
595 RemLibrary(library);
596 /* Did it really go away? */
597 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
599 /* Yes! Return it. */
600 Permit();
601 return MEM_TRY_AGAIN;
603 library = nextLib;
605 else
607 /* Go on to next library. */
608 library = (struct Library *)library->lib_Node.ln_Succ;
612 /* Do the same with the device list. */
613 library = (struct Library *)SysBase->DeviceList.lh_Head;
614 while(library->lib_Node.ln_Succ != NULL)
616 /* Flush libraries with a 0 open count */
617 if( ! library->lib_OpenCnt )
619 struct Library *nextDev = (struct Library *)library->lib_Node.ln_Succ;
620 RemDevice((struct Device *)library);
621 /* Did it really go away? */
622 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
624 /* Yes! Return it. */
625 Permit();
626 return MEM_TRY_AGAIN;
628 library = nextDev;
630 else
632 /* Go on to next library. */
633 library = (struct Library *)library->lib_Node.ln_Succ;
636 Permit();
637 return MEM_DID_NOTHING;
639 AROS_USERFUNC_EXIT
643 void LDDemon()
644 The LDDemon process entry. Sits around and does nothing until a
645 request for a library comes, when it will then find the library
646 and hopefully open it.
648 static AROS_PROCH(LDDemon, argptr, argsize, SysBase)
650 AROS_PROCFUNC_INIT
652 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
653 struct Library *DOSBase = ldBase->dl_DOSBase;
654 struct LDDMsg *ldd;
656 for(;;)
658 WaitPort(ldBase->dl_LDDemonPort);
659 while( (ldd = (struct LDDMsg *)GetMsg(ldBase->dl_LDDemonPort)) )
661 D(bug("[LDDemon] Got a request for %s in %s\n", ldd->ldd_Name, ldd->ldd_BaseDir));
663 ldd->ldd_Return = LDLoad(ldd->ldd_ReplyPort.mp_SigTask, ldd->ldd_Name, ldd->ldd_BaseDir, DOSBase, SysBase);
665 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
666 ReplyMsg((struct Message *)ldd);
667 } /* messages available */
670 /* lddemon died */
671 return 0;
673 AROS_PROCFUNC_EXIT
676 static ULONG LDDemon_Init(struct LDDemonBase *ldBase)
678 struct Library *DOSBase;
679 struct TagItem tags[] =
681 { NP_Entry, (IPTR)LDDemon },
682 { NP_Input, 0 },
683 { NP_Output, 0 },
684 { NP_WindowPtr, -1 },
685 { NP_Name, (IPTR)ldDemonName },
686 { NP_Priority, 5 },
687 { TAG_END , 0 }
690 DOSBase = TaggedOpenLibrary(TAGGEDOPEN_DOS);
691 if (!DOSBase) {
692 Alert( AN_RAMLib | AG_OpenLib | AO_DOSLib | AT_DeadEnd );
695 if ((ldBase->dl_LDDemonPort = CreateMsgPort()) == NULL )
697 Alert( AN_RAMLib | AG_NoMemory | AT_DeadEnd );
700 FreeSignal(ldBase->dl_LDDemonPort->mp_SigBit);
701 ldBase->dl_LDDemonPort->mp_SigBit = SIGBREAKB_CTRL_F;
703 ldBase->dl_LDHandler.is_Node.ln_Name = (STRPTR)ldDemonName;
704 ldBase->dl_LDHandler.is_Node.ln_Pri = 0;
705 ldBase->dl_LDHandler.is_Code = (VOID_FUNC)LDFlush;
706 ldBase->dl_LDHandler.is_Data = NULL;
708 ldBase->dl_DOSBase = DOSBase;
710 NEWLIST(&ldBase->dl_LDObjectsList);
711 InitSemaphore(&ldBase->dl_LDObjectsListSigSem);
713 SysBase->ex_RamLibPrivate = ldBase;
715 AddMemHandler(&ldBase->dl_LDHandler);
718 * Grab the semaphore ourself. The reason for this is that it will
719 * cause all other tasks to wait until we have finished initialising
720 * before they try and open something.
722 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
724 #define SetFunc(offs,ptr) \
725 SetFunction(&SysBase->LibNode, (-offs)*(LONG)LIB_VECTSIZE, \
726 AROS_SLIB_ENTRY(ptr,Dos,0))
728 /* Do not set the vectors until you have initialised everything else. */
729 ldBase->__OpenLibrary = SetFunc(92, OpenLibrary);
730 ldBase->__OpenDevice = SetFunc(74, OpenDevice);
731 (void)SetFunc(69, CloseLibrary);
732 (void)SetFunc(75, CloseDevice);
733 (void)SetFunc(67, RemLibrary);
734 (void)SetFunc(73, RemLibrary);
736 if( !(ldBase->dl_LDDemonTask = CreateNewProc((struct TagItem *)tags)) )
738 Alert( AT_DeadEnd | AN_RAMLib | AG_ProcCreate );
741 /* Fix up the MsgPort */
743 ldBase->dl_LDDemonPort->mp_SigTask = ldBase->dl_LDDemonTask;
745 /* Then unlock the semaphore to allow other processes to run. */
746 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
748 return TRUE;
751 ADD2INITLIB(LDDemon_Init, 0)