tools/genmodule: Fix error in tests/clib/execl; should also fix gcc
[AROS.git] / rom / lddemon / lddemon.c
blob66d92b086a79981ea96c82963228a0d8b7a5c226
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, struct ExecBase *SysBase)
161 BPTR seg = seglist;
163 /* we may not have any extension fields */
164 const int sizeofresident = offsetof(struct Resident, rt_Init) + sizeof(APTR);
166 while(seg)
168 STRPTR addr = (STRPTR)((IPTR)BADDR(seg) - sizeof(ULONG));
169 ULONG size = *(ULONG *)addr;
171 for(
172 addr += sizeof(BPTR) + sizeof(ULONG),
173 size -= sizeof(BPTR) + sizeof(ULONG);
174 size >= sizeofresident;
175 size -= 2, addr += 2
176 // size -= AROS_PTRALIGN, addr += AROS_PTRALIGN
179 struct Resident *res = (struct Resident *)addr;
180 if( res->rt_MatchWord == RTC_MATCHWORD
181 && res->rt_MatchTag == res )
183 struct Node *node;
185 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
186 /* AOS compatibility requirement.
187 * Ramlib ignores InitResident() return code.
188 * After InitResident() it checks if lib/dev appeared
189 * in Exec lib/dev list via FindName().
191 * Evidently InitResident()'s return code was not
192 * reliable for some early AOS libraries.
194 Forbid();
195 InitResident(res, seglist);
196 node = FindName(list, res->rt_Name);
197 Permit();
198 D(bug("[LDInit] Done calling InitResident(%p) on %s, seg %p, node %p\n", res, res->rt_Name, BADDR(seglist), node));
200 return (struct Library*)node;
203 seg = *(BPTR *)BADDR(seg);
205 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
206 return NULL;
209 #define ExecOpenLibrary(libname, version) \
210 AROS_CALL2(struct Library *, ldBase->__OpenLibrary, \
211 AROS_LCA(STRPTR, libname, A1), \
212 AROS_LCA(ULONG, version, D0), \
213 struct ExecBase *, SysBase)
215 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
216 AROS_CALL4(LONG, ldBase->__OpenDevice, \
217 AROS_LCA(STRPTR, devname, A0), \
218 AROS_LCA(IPTR, unitNumber, D0), \
219 AROS_LCA(struct IORequest *, iORequest, A1), \
220 AROS_LCA(ULONG, flags, D1), \
221 struct ExecBase *, SysBase)
223 struct LDObjectNode
225 struct Node ldon_Node;
226 struct SignalSemaphore ldon_SigSem;
227 ULONG ldon_AccessCount;
228 #if CHECK_DEPENDENCY
229 struct Task *ldon_FirstLocker;
230 #endif
233 static struct LDObjectNode *LDNewObjectNode(STRPTR name, struct ExecBase *SysBase)
235 struct LDObjectNode *ret = AllocVec(sizeof(struct LDObjectNode), MEMF_ANY);
236 if (ret)
238 ULONG len = strlen(name);
239 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
240 if (dupname)
242 CopyMem(name, dupname, len);
243 dupname[len] = '\0';
244 ret->ldon_Node.ln_Name = dupname;
245 InitSemaphore(&ret->ldon_SigSem);
246 ret->ldon_AccessCount = 0;
248 #if CHECK_DEPENDENCY
249 ret->ldon_FirstLocker = FindTask(0);
250 #endif
252 return ret;
254 FreeVec(ret);
257 return NULL;
260 static struct LDObjectNode *LDRequestObject(STRPTR libname, ULONG version, STRPTR dir, struct List *list, struct ExecBase *SysBase)
262 /* We use FilePart() because the liblist is built from resident IDs,
263 and contain no path. Eg. The user can request gadgets/foo.gadget,
264 but the resident only contains foo.gadget
266 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
267 struct Library *DOSBase = ldBase->dl_DOSBase;
268 STRPTR stripped_libname = FilePart(libname);
269 struct Library *tmplib;
270 struct LDObjectNode *object;
273 We get the DOS semaphore to prevent the following:
274 - task 1 tries to open foobar.library, needs to load it from disk...
275 - task 1 Permit()'s (since it's not doing list things)
276 - task switch (whilst LDDemon MAY get process next it might not)
277 - task 2 tries to open foobar.library, needs to load it from disk...
278 - it also requests LDDemon to open foobar.library, so it is now
279 trying to open it twice
281 We block all OpenLibrary() callers from searching the list until
282 all the other OpenLibrary() callers have returned. That way,
283 task #2 won't ask for foobar.library until task #1 has got its
284 response back from the LDDemon process.
286 falemagn: I changed the implementation of all that.
287 There's a list of "LDObjectNodes", that contain the name
288 of the object being opened. Since the problem is that more
289 processes can attempt to open the same device/library. Instead of
290 locking a global semaphore until the opening is done, we lock a
291 per-object semaphore, so that others libraries/devices can be opened
292 in the meantime. Before, a deadlock could happen if there was a
293 situation like this:
295 Process A opens L --------> LDDemon loads L and locks sem S
298 1 / \ 3
300 / 2 \
301 L spawns a process B and ----------> The process opens
302 waits for it to respond a library but gets loked
303 to a message <----/---- because sem S is locked
307 Proces B will never
308 respond to L.
310 Hopefully this won't happen anymore now.
312 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
314 object = (struct LDObjectNode *)FindName(&ldBase->dl_LDObjectsList, stripped_libname);
315 if (!object)
317 object = LDNewObjectNode(stripped_libname, SysBase);
318 if (object)
320 AddTail(&ldBase->dl_LDObjectsList, (struct Node *)object);
324 if (object)
326 object->ldon_AccessCount += 1;
329 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
331 if (!object)
332 return NULL;
334 ObtainSemaphore(&object->ldon_SigSem);
336 /* Try to find the resident in the list */
337 tmplib = (struct Library *)FindName(list, stripped_libname);
339 if (!tmplib)
341 /* Try to load from disk if not found */
342 struct LDDMsg ldd;
344 ldd.ldd_ReplyPort.mp_SigBit = SIGB_SINGLE;
345 ldd.ldd_ReplyPort.mp_SigTask = FindTask(NULL);
346 ldd.ldd_ReplyPort.mp_Flags = PA_SIGNAL;
347 ldd.ldd_ReplyPort.mp_Node.ln_Type = NT_MSGPORT;
349 NEWLIST(&ldd.ldd_ReplyPort.mp_MsgList);
351 ldd.ldd_Msg.mn_Node.ln_Type = NT_MESSAGE;
352 ldd.ldd_Msg.mn_Length = sizeof(struct LDDMsg);
353 ldd.ldd_Msg.mn_ReplyPort = &ldd.ldd_ReplyPort;
355 ldd.ldd_Name = libname;
356 ldd.ldd_BaseDir = dir;
358 SetSignal(0, SIGF_SINGLE);
359 D(bug("[LDCaller] Sending request for %s\n", stripped_libname));
361 PutMsg(ldBase->dl_LDDemonPort, (struct Message *)&ldd);
362 WaitPort(&ldd.ldd_ReplyPort);
364 D(bug("[LDCaller] Returned 0x%p\n", ldd.ldd_Return));
366 if (ldd.ldd_Return)
368 tmplib = LDInit(ldd.ldd_Return, list, SysBase);
369 if (!tmplib)
370 UnLoadSeg(ldd.ldd_Return);
374 if (!tmplib)
377 * The library is not on disk so check Resident List.
378 * It can be there if it is resident but was flushed.
380 struct Resident *resident = FindResident(stripped_libname);
383 * Check if the resident is of required type and version is correct.
384 * This relies on the fact that lh_Type is set correctly for exec lists.
385 * In AROS this is true (see rom/exec/prepareexecbase.c).
387 if (resident && (resident->rt_Type == list->lh_Type) && (resident->rt_Version >= version))
388 InitResident(resident, BNULL);
391 return object;
394 static void LDReleaseObject(struct LDObjectNode *object, struct ExecBase *SysBase)
396 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
399 Release the semaphore here, after calling Open vector. This
400 means that library open is singlethreaded by the semaphore.
401 It also handles circular dependant libraries. (Won't deadlock),
402 and recursive OpenLibrary calls (Semaphores nest when obtained
403 several times in a row by the same task).
406 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
408 if (--(object->ldon_AccessCount) == 0)
410 Remove((struct Node *)object);
412 * CHECKME: In LDRequestObject() we obtain the object semaphore also on a new object.
413 * So shouldn't we release it here too ?
416 FreeVec(object->ldon_Node.ln_Name);
417 FreeVec(object);
419 else
420 ReleaseSemaphore(&object->ldon_SigSem);
422 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
425 AROS_LH2(struct Library *, OpenLibrary,
426 AROS_LHA(STRPTR, libname, A1),
427 AROS_LHA(ULONG, version, D0),
428 struct ExecBase *, SysBase, 0, Dos)
430 AROS_LIBFUNC_INIT
432 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
433 struct Library *library;
434 struct LDObjectNode *object = LDRequestObject(libname, version, "libs", &SysBase->LibList, SysBase);
436 if (!object)
437 return NULL;
439 /* Call the EXEC's OpenLibrary function */
440 library = ExecOpenLibrary(object->ldon_Node.ln_Name, version);
442 LDReleaseObject(object, SysBase);
444 return library;
446 AROS_LIBFUNC_EXIT
449 AROS_LH4(LONG, OpenDevice,
450 AROS_LHA(STRPTR, devname, A0),
451 AROS_LHA(IPTR, unitNumber, D0),
452 AROS_LHA(struct IORequest *, iORequest, A1),
453 AROS_LHA(ULONG, flags, D1),
454 struct ExecBase *, SysBase, 0, Dos)
456 AROS_LIBFUNC_INIT
458 struct LDObjectNode *object;
459 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
461 object = LDRequestObject(devname, 0, "devs", &SysBase->DeviceList, SysBase);
462 if (object)
464 /* Call exec.library/OpenDevice(), it will do the job */
465 ExecOpenDevice(object->ldon_Node.ln_Name, unitNumber, iORequest, flags);
466 LDReleaseObject(object, SysBase);
468 else
470 iORequest->io_Error = IOERR_OPENFAIL;
471 iORequest->io_Device = NULL;
472 iORequest->io_Unit = NULL;
475 D(bug("[LDCaller] Open result: %d\n", iORequest->io_Error));
477 return iORequest->io_Error;
479 AROS_LIBFUNC_EXIT
482 AROS_LH1(void, CloseLibrary,
483 AROS_LHA(struct Library *, library, A1),
484 struct ExecBase *, SysBase, 0, Dos)
486 AROS_LIBFUNC_INIT
488 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
489 struct Library *DOSBase = ldBase->dl_DOSBase;
490 BPTR seglist;
492 if( library != NULL )
494 Forbid();
495 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
496 if( seglist )
498 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
500 /* Safe to call from a Task */
501 UnLoadSeg(seglist);
503 Permit();
506 AROS_LIBFUNC_EXIT
509 AROS_LH1(void, CloseDevice,
510 AROS_LHA(struct IORequest *, iORequest, A1),
511 struct ExecBase *, SysBase, 0, Dos)
513 AROS_LIBFUNC_INIT
514 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
515 struct Library *DOSBase = ldBase->dl_DOSBase;
516 BPTR seglist = BNULL;
518 Forbid();
519 if( iORequest->io_Device != NULL )
521 seglist = AROS_LVO_CALL1(BPTR,
522 AROS_LCA(struct IORequest *, iORequest, A1),
523 struct Device *, iORequest->io_Device, 2, );
524 iORequest->io_Device=(struct Device *)-1;
525 if( seglist )
527 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
528 UnLoadSeg(seglist);
531 Permit();
532 AROS_LIBFUNC_EXIT
535 AROS_LH1(void, RemLibrary,
536 AROS_LHA(struct Library *, library, A1),
537 struct ExecBase *, SysBase, 0, Dos)
539 AROS_LIBFUNC_INIT
541 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
542 struct Library *DOSBase = ldBase->dl_DOSBase;
543 BPTR seglist;
545 Forbid();
546 /* calling ExpungeLib: library ends up in D0 and A6 for compatibility */
547 seglist = AROS_CALL1(BPTR, __AROS_GETVECADDR(library, 3),
548 AROS_LCA(struct Library *, library, D0),
549 struct Library *, library
551 if( seglist )
553 ldBase->dl_LDReturn = MEM_TRY_AGAIN;
554 UnLoadSeg(seglist);
556 Permit();
558 AROS_LIBFUNC_EXIT
561 AROS_UFH3(LONG, LDFlush,
562 AROS_UFHA(struct MemHandlerData *, lmhd, A0),
563 AROS_UFHA(APTR, data, A1),
564 AROS_UFHA(struct ExecBase *, SysBase, A6)
567 AROS_USERFUNC_INIT
569 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
570 struct Library *library;
572 D(bug("[LDDemon] Flush called\n"));
573 ldBase->dl_LDReturn = MEM_DID_NOTHING;
575 /* Forbid() is already done, but I don't want to rely on it. */
576 Forbid();
578 /* Follow the linked list of shared libraries. */
579 library = (struct Library *)SysBase->LibList.lh_Head;
580 while(library->lib_Node.ln_Succ != NULL)
582 /* Flush libraries with a 0 open count */
583 if( ! library->lib_OpenCnt )
585 /* the library list node will be wiped from memory */
586 struct Library *nextLib = (struct Library *)library->lib_Node.ln_Succ;
587 RemLibrary(library);
588 /* Did it really go away? */
589 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
591 /* Yes! Return it. */
592 Permit();
593 return MEM_TRY_AGAIN;
595 library = nextLib;
597 else
599 /* Go on to next library. */
600 library = (struct Library *)library->lib_Node.ln_Succ;
604 /* Do the same with the device list. */
605 library = (struct Library *)SysBase->DeviceList.lh_Head;
606 while(library->lib_Node.ln_Succ != NULL)
608 /* Flush libraries with a 0 open count */
609 if( ! library->lib_OpenCnt )
611 struct Library *nextDev = (struct Library *)library->lib_Node.ln_Succ;
612 RemDevice((struct Device *)library);
613 /* Did it really go away? */
614 if( ldBase->dl_LDReturn != MEM_DID_NOTHING )
616 /* Yes! Return it. */
617 Permit();
618 return MEM_TRY_AGAIN;
620 library = nextDev;
622 else
624 /* Go on to next library. */
625 library = (struct Library *)library->lib_Node.ln_Succ;
628 Permit();
629 return MEM_DID_NOTHING;
631 AROS_USERFUNC_EXIT
635 void LDDemon()
636 The LDDemon process entry. Sits around and does nothing until a
637 request for a library comes, when it will then find the library
638 and hopefully open it.
640 static AROS_ENTRY(VOID, LDDemon,
641 AROS_UFHA(APTR, argptr, A0),
642 AROS_UFHA(APTR, argsize, D0),
643 struct ExecBase *, SysBase)
645 AROS_USERFUNC_INIT
647 struct LDDemonBase *ldBase = SysBase->ex_RamLibPrivate;
648 struct Library *DOSBase = ldBase->dl_DOSBase;
649 struct LDDMsg *ldd;
651 for(;;)
653 WaitPort(ldBase->dl_LDDemonPort);
654 while( (ldd = (struct LDDMsg *)GetMsg(ldBase->dl_LDDemonPort)) )
656 D(bug("[LDDemon] Got a request for %s in %s\n", ldd->ldd_Name, ldd->ldd_BaseDir));
658 ldd->ldd_Return = LDLoad(ldd->ldd_ReplyPort.mp_SigTask, ldd->ldd_Name, ldd->ldd_BaseDir, DOSBase, SysBase);
660 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
661 ReplyMsg((struct Message *)ldd);
662 } /* messages available */
665 AROS_USERFUNC_EXIT
668 static ULONG LDDemon_Init(struct LDDemonBase *ldBase)
670 struct Library *DOSBase;
671 struct TagItem tags[] =
673 { NP_Entry, (IPTR)LDDemon },
674 { NP_Input, 0 },
675 { NP_Output, 0 },
676 { NP_WindowPtr, -1 },
677 { NP_Name, (IPTR)ldDemonName },
678 { NP_Priority, 5 },
679 { TAG_END , 0 }
682 DOSBase = TaggedOpenLibrary(TAGGEDOPEN_DOS);
683 if (!DOSBase) {
684 Alert( AN_RAMLib | AG_OpenLib | AO_DOSLib | AT_DeadEnd );
687 if ((ldBase->dl_LDDemonPort = CreateMsgPort()) == NULL )
689 Alert( AN_RAMLib | AG_NoMemory | AT_DeadEnd );
692 FreeSignal(ldBase->dl_LDDemonPort->mp_SigBit);
693 ldBase->dl_LDDemonPort->mp_SigBit = SIGBREAKB_CTRL_F;
695 ldBase->dl_LDHandler.is_Node.ln_Name = (STRPTR)ldDemonName;
696 ldBase->dl_LDHandler.is_Node.ln_Pri = 0;
697 ldBase->dl_LDHandler.is_Code = (void (*)())LDFlush;
698 ldBase->dl_LDHandler.is_Data = NULL;
700 ldBase->dl_DOSBase = DOSBase;
702 NEWLIST(&ldBase->dl_LDObjectsList);
703 InitSemaphore(&ldBase->dl_LDObjectsListSigSem);
705 SysBase->ex_RamLibPrivate = ldBase;
707 AddMemHandler(&ldBase->dl_LDHandler);
710 * Grab the semaphore ourself. The reason for this is that it will
711 * cause all other tasks to wait until we have finished initialising
712 * before they try and open something.
714 ObtainSemaphore(&ldBase->dl_LDObjectsListSigSem);
716 #define SetFunc(offs,ptr) \
717 SetFunction(&SysBase->LibNode, (-offs)*(LONG)LIB_VECTSIZE, \
718 AROS_SLIB_ENTRY(ptr,Dos,0))
720 /* Do not set the vectors until you have initialised everything else. */
721 ldBase->__OpenLibrary = SetFunc(92, OpenLibrary);
722 ldBase->__OpenDevice = SetFunc(74, OpenDevice);
723 (void)SetFunc(69, CloseLibrary);
724 (void)SetFunc(75, CloseDevice);
725 (void)SetFunc(67, RemLibrary);
726 (void)SetFunc(73, RemLibrary);
728 if( !(ldBase->dl_LDDemonTask = CreateNewProc((struct TagItem *)tags)) )
730 Alert( AT_DeadEnd | AN_RAMLib | AG_ProcCreate );
733 /* Fix up the MsgPort */
735 ldBase->dl_LDDemonPort->mp_SigTask = ldBase->dl_LDDemonTask;
737 /* Then unlock the semaphore to allow other processes to run. */
738 ReleaseSemaphore(&ldBase->dl_LDObjectsListSigSem);
740 return TRUE;
743 ADD2INITLIB(LDDemon_Init, 0)