2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Loader for shared libraries and devices.
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>
20 #include <dos/dosextens.h>
21 #include <dos/dostags.h>
22 #include <proto/exec.h>
23 #include <proto/dos.h>
31 #define INIT_IN_LDDEMON_CONTEXT 1
33 #define INIT_IN_LDDEMON_CONTEXT 0
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
);
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 */
71 BPTR ldd_Return
; /* Loaded seglist */
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
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
);
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
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
);
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
);
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
);
161 seglist
= LoadSeg(name
);
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
;
175 /* we may not have any extension fields */
176 const int sizeofresident
= offsetof(struct Resident
, rt_Init
) + sizeof(APTR
);
180 STRPTR addr
= (STRPTR
)((IPTR
)BADDR(seg
) - sizeof(ULONG
));
181 ULONG size
= *(ULONG
*)addr
;
184 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
185 size
-= sizeof(BPTR
) + sizeof(ULONG
);
186 size
>= sizeofresident
;
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.
205 InitResident(res
, seglist
);
206 node
= FindName(list
, res
->rt_Name
);
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
));
217 /* If struct Resident was not found, just run the code. SegList in A0.
218 * Required to load WB1.x devs:narrator.device. */
220 AROS_UFC1NR(void, BADDR(seglist
) + sizeof(ULONG
), AROS_UFCA(BPTR
, seglist
, A0
));
221 node
= FindName(list
, resname
);
223 D(bug("[LDInit] Done direct calling %s, seg %p, node %p\n", resname
, BADDR(seglist
), node
));
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
;
233 tmplib
= LDInit(seglist
, list
, resname
, SysBase
);
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)
255 struct Node ldon_Node
;
256 struct SignalSemaphore ldon_SigSem
;
257 ULONG ldon_AccessCount
;
259 struct Task
*ldon_FirstLocker
;
263 static struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct ExecBase
*SysBase
)
265 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
268 ULONG len
= strlen(name
);
269 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
272 CopyMem(name
, dupname
, len
);
274 ret
->ldon_Node
.ln_Name
= dupname
;
275 InitSemaphore(&ret
->ldon_SigSem
);
276 ret
->ldon_AccessCount
= 0;
279 ret
->ldon_FirstLocker
= FindTask(0);
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
327 Process A opens L --------> LDDemon loads L and locks sem S
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
342 Hopefully this won't happen anymore now.
344 ObtainSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
346 object
= (struct LDObjectNode
*)FindName(&ldBase
->dl_LDObjectsList
, stripped_libname
);
349 object
= LDNewObjectNode(stripped_libname
, SysBase
);
352 AddTail(&ldBase
->dl_LDObjectsList
, (struct Node
*)object
);
358 object
->ldon_AccessCount
+= 1;
361 ReleaseSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
366 ObtainSemaphore(&object
->ldon_SigSem
);
368 /* Try to find the resident in the list */
369 tmplib
= (struct Library
*)FindName(list
, stripped_libname
);
373 /* Try to load from disk if not found */
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
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
);
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
;
413 tmplib
= CallLDInit(ldd
.ldd_Return
, list
, stripped_libname
, DOSBase
, SysBase
);
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
);
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
);
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
)
475 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
476 struct Library
*library
;
477 struct LDObjectNode
*object
= LDRequestObject(libname
, version
, "libs", &SysBase
->LibList
, SysBase
);
482 /* Call the EXEC's OpenLibrary function */
483 library
= ExecOpenLibrary(object
->ldon_Node
.ln_Name
, version
);
485 LDReleaseObject(object
, SysBase
);
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
)
501 struct LDObjectNode
*object
;
502 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
504 object
= LDRequestObject(devname
, 0, "devs", &SysBase
->DeviceList
, SysBase
);
507 /* Call exec.library/OpenDevice(), it will do the job */
508 ExecOpenDevice(object
->ldon_Node
.ln_Name
, unitNumber
, iORequest
, flags
);
509 LDReleaseObject(object
, SysBase
);
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
;
525 AROS_LH1(void, CloseLibrary
,
526 AROS_LHA(struct Library
*, library
, A1
),
527 struct ExecBase
*, SysBase
, 0, Dos
)
531 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
532 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
535 if( library
!= NULL
)
538 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
541 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
543 /* Safe to call from a Task */
552 AROS_LH1(void, CloseDevice
,
553 AROS_LHA(struct IORequest
*, iORequest
, A1
),
554 struct ExecBase
*, SysBase
, 0, Dos
)
557 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
558 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
559 BPTR seglist
= BNULL
;
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;
570 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
578 AROS_LH1(void, RemLibrary
,
579 AROS_LHA(struct Library
*, library
, A1
),
580 struct ExecBase
*, SysBase
, 0, Dos
)
584 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
585 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
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
596 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
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
)
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. */
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
;
631 /* Did it really go away? */
632 if( ldBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
634 /* Yes! Return it. */
636 return MEM_TRY_AGAIN
;
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. */
661 return MEM_TRY_AGAIN
;
667 /* Go on to next library. */
668 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
672 return MEM_DID_NOTHING
;
677 static void ProcessLDMessage(struct LDDemonBase
*ldBase
, struct LDDMsg
*ldd
, struct Library
*DOSBase
, struct ExecBase
*SysBase
)
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
));
688 ldd
->ldd_Return
= seglist
;
689 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
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
)
703 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
704 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
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 */
723 static ULONG
LDDemon_Init(struct LDDemonBase
*ldBase
)
725 struct Library
*DOSBase
;
726 struct TagItem tags
[] =
728 { NP_Entry
, (IPTR
)LDDemon
},
731 { NP_WindowPtr
, -1 },
732 { NP_Name
, (IPTR
)ldDemonName
},
737 DOSBase
= TaggedOpenLibrary(TAGGEDOPEN_DOS
);
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
);
798 ADD2INITLIB(LDDemon_Init
, 0)