2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
5 Loader for shared libraries and devices.
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>
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>
36 #define INIT_IN_LDDEMON_CONTEXT 1
38 #define INIT_IN_LDDEMON_CONTEXT 0
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
);
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 */
76 BPTR ldd_Return
; /* Loaded seglist */
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
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
);
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
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
);
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
);
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
);
166 seglist
= LoadSeg(name
);
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
;
180 /* we may not have any extension fields */
181 const int sizeofresident
= offsetof(struct Resident
, rt_Init
) + sizeof(APTR
);
185 STRPTR addr
= (STRPTR
)((IPTR
)BADDR(seg
) - sizeof(ULONG
));
186 ULONG size
= *(ULONG
*)addr
;
189 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
190 size
-= sizeof(BPTR
) + sizeof(ULONG
);
191 size
>= sizeofresident
;
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.
210 InitResident(res
, seglist
);
211 node
= FindName(list
, res
->rt_Name
);
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
));
222 /* If struct Resident was not found, just run the code. SegList in A0.
223 * Required to load WB1.x devs:narrator.device. */
225 AROS_UFC1NR(void, BADDR(seglist
) + sizeof(ULONG
), AROS_UFCA(BPTR
, seglist
, A0
));
226 node
= FindName(list
, resname
);
228 D(bug("[LDInit] Done direct calling %s, seg %p, node %p\n", resname
, BADDR(seglist
), node
));
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
;
238 tmplib
= LDInit(seglist
, list
, resname
, SysBase
);
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)
260 struct Node ldon_Node
;
261 struct SignalSemaphore ldon_SigSem
;
262 ULONG ldon_AccessCount
;
264 struct Task
*ldon_FirstLocker
;
268 static struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct ExecBase
*SysBase
)
270 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
273 ULONG len
= strlen(name
);
274 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
277 CopyMem(name
, dupname
, len
);
279 ret
->ldon_Node
.ln_Name
= dupname
;
280 InitSemaphore(&ret
->ldon_SigSem
);
281 ret
->ldon_AccessCount
= 0;
284 ret
->ldon_FirstLocker
= FindTask(0);
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
;
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
335 Process A opens L --------> LDDemon loads L and locks sem S
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
350 Hopefully this won't happen anymore now.
352 ObtainSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
354 object
= (struct LDObjectNode
*)FindName(&ldBase
->dl_LDObjectsList
, stripped_libname
);
357 object
= LDNewObjectNode(stripped_libname
, SysBase
);
360 AddTail(&ldBase
->dl_LDObjectsList
, (struct Node
*)object
);
366 object
->ldon_AccessCount
+= 1;
369 ReleaseSemaphore(&ldBase
->dl_LDObjectsListSigSem
);
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
);
380 tmplib
= (struct Library
*)FindName(list
, stripped_libname
);
381 #if defined(__AROSEXEC_SMP__)
382 ReleaseSystemLock(list
, LOCKF_FORBID
);
387 /* Try to load from disk if not found */
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
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
);
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
;
428 tmplib
= CallLDInit(ldd
.ldd_Return
, list
, stripped_libname
, DOSBase
, SysBase
);
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
);
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
);
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
)
490 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
491 struct Library
*library
;
492 struct LDObjectNode
*object
;
494 object
= LDRequestObject(libname
, version
, "libs", &SysBase
->LibList
, SysBase
);
499 /* Call the EXEC's OpenLibrary function */
500 library
= ExecOpenLibrary(object
->ldon_Node
.ln_Name
, version
);
502 LDReleaseObject(object
, SysBase
);
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
)
518 struct LDObjectNode
*object
;
519 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
521 object
= LDRequestObject(devname
, 0, "devs", &SysBase
->DeviceList
, SysBase
);
525 /* Call exec.library/OpenDevice(), it will do the job */
526 ExecOpenDevice(object
->ldon_Node
.ln_Name
, unitNumber
, iORequest
, flags
);
527 LDReleaseObject(object
, SysBase
);
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
;
543 AROS_LH1(void, CloseLibrary
,
544 AROS_LHA(struct Library
*, library
, A1
),
545 struct ExecBase
*, SysBase
, 0, Dos
)
549 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
550 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
553 if( library
!= NULL
)
556 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
559 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
561 /* Safe to call from a Task */
570 AROS_LH1(void, CloseDevice
,
571 AROS_LHA(struct IORequest
*, iORequest
, A1
),
572 struct ExecBase
*, SysBase
, 0, Dos
)
575 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
576 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
577 BPTR seglist
= BNULL
;
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;
588 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
596 AROS_LH1(void, RemLibrary
,
597 AROS_LHA(struct Library
*, library
, A1
),
598 struct ExecBase
*, SysBase
, 0, Dos
)
602 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
603 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
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
614 ldBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
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
)
630 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
631 #if defined(__AROSEXEC_SMP__)
632 void *ExecLockBase
= ldBase
->dl_ExecLockRes
;
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. */
641 #if defined(__AROSEXEC_SMP__)
642 ObtainSystemLock(&SysBase
->LibList
, SPINLOCK_MODE_WRITE
, 0);
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
;
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);
663 return MEM_TRY_AGAIN
;
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);
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);
695 return MEM_TRY_AGAIN
;
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);
710 return MEM_DID_NOTHING
;
715 static void ProcessLDMessage(struct LDDemonBase
*ldBase
, struct LDDMsg
*ldd
, struct Library
*DOSBase
, struct ExecBase
*SysBase
)
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
));
726 ldd
->ldd_Return
= seglist
;
727 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
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
)
741 struct LDDemonBase
*ldBase
= SysBase
->ex_RamLibPrivate
;
742 struct Library
*DOSBase
= ldBase
->dl_DOSBase
;
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 */
761 static ULONG
LDDemon_Init(struct LDDemonBase
*ldBase
)
763 struct Library
*DOSBase
;
764 struct TagItem tags
[] =
766 { NP_Entry
, (IPTR
)LDDemon
},
769 { NP_WindowPtr
, -1 },
770 { NP_Name
, (IPTR
)ldDemonName
},
775 DOSBase
= TaggedOpenLibrary(TAGGEDOPEN_DOS
);
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");
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
);
840 ADD2INITLIB(LDDemon_Init
, 0)