2 Copyright © 1995-2004, The AROS Development Team. All rights reserved.
5 Loader for shared libraries and devices.
8 #include <exec/execbase.h>
9 #include <exec/resident.h>
10 #include <exec/memory.h>
11 #include <exec/errors.h>
12 #include <exec/libraries.h>
13 #include <exec/devices.h>
14 #include <exec/ports.h>
15 #include <exec/lists.h>
16 #include <exec/alerts.h>
17 #include <exec/tasks.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <aros/asmcall.h>
23 #include <aros/debug.h>
25 #include <proto/exec.h>
26 #include <proto/dos.h>
27 #include "dos_intern.h"
28 #include LC_LIBDEFS_FILE
34 #define CHECK_DEPENDENCY 1
36 /* Please leave them here! They are needed on Linux-M68K */
37 AROS_LD2(struct Library
*, OpenLibrary
,
38 AROS_LDA(STRPTR
, libname
, A1
),
39 AROS_LDA(ULONG
, version
, D0
),
40 struct ExecBase
*, SysBase
, 0, Dos
);
41 AROS_LD4(BYTE
, OpenDevice
,
42 AROS_LDA(STRPTR
, devname
, A0
),
43 AROS_LDA(ULONG
, unitNumber
, D0
),
44 AROS_LDA(struct IORequest
*, iORequest
, A1
),
45 AROS_LDA(ULONG
, flags
, D1
),
46 struct ExecBase
*, SysBase
, 0, Dos
);
47 AROS_LD1(void, CloseLibrary
,
48 AROS_LDA(struct Library
*, library
, A1
),
49 struct ExecBase
*, SysBase
, 0, Dos
);
50 AROS_LD1(void, CloseDevice
,
51 AROS_LDA(struct IORequest
*, iORequest
, A1
),
52 struct ExecBase
*, SysBase
, 0, Dos
);
53 AROS_LD1(void, RemLibrary
,
54 AROS_LDA(struct Library
*, library
, A1
),
55 struct ExecBase
*, SysBase
, 0, Dos
);
59 struct Message ldd_Msg
; /* Message link */
60 struct MsgPort ldd_ReplyPort
; /* Callers ReplyPort */
62 STRPTR ldd_Name
; /* Name of thing to load */
63 ULONG ldd_Version
; /* Version of thing to load */
65 STRPTR ldd_BaseDir
; /* Base directory to load from */
66 struct Library
* ldd_Return
; /* The result */
72 #define LIBEND LDDemon_end
74 #include <libcore/compiler.h>
76 static const char name
[];
77 static const char version
[];
78 extern const int LIBEND TEXT_SECTION
;
79 static ULONG
AROS_SLIB_ENTRY(Init
, LDDemon
)();
81 const struct Resident LDDemon_resident
=
84 (struct Resident
*)&LDDemon_resident
,
92 AROS_SLIB_ENTRY(Init
,LDDemon
)
95 static const char name
[] = "LDDemon";
96 static const char version
[] = "$VER: LDDemon 41.2 (17.3.2001)\r\n";
97 static const char ldDemonName
[] = "Lib & Dev Loader Daemon";
100 BPTR LDLoad( caller, name, basedir, DOSBase )
101 Try and load a segment from disk for the object <name>, relative
102 to directory <basedir>. Will also try <caller>'s current and home
107 struct Process
*caller
,
110 struct DosLibrary
*DOSBase
113 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
114 struct Process
*me
= (struct Process
*)FindTask(NULL
);
115 struct DevProc
*dp
= NULL
;
119 If the caller was a process, we have more scope for loading
120 libraries. We can load them from the callers current directory,
121 or from the PROGDIR: assign. These could both be the same
125 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
126 caller
, caller
->pr_Task
.tc_Node
.ln_Name
, name
, basedir
129 if (__is_process(caller
))
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
);
140 /* The the program directory of the caller */
141 if( caller
->pr_HomeDir
!= NULL
)
143 D(bug("[LDLoad] Trying homedir\n"));
144 me
->pr_CurrentDir
= caller
->pr_HomeDir
;
145 seglist
= LoadSeg(name
);
151 /* Nup, lets try the default directory as supplied. */
152 while( seglist
== NULL
153 && (dp
= GetDeviceProc( basedir
, dp
)) != NULL
156 D(bug("[LDLoad] Trying default dir, dp=%p\n", dp
));
157 /* XXX: There is something bad here if dvp_Lock == NULL */
158 me
->pr_CurrentDir
= dp
->dvp_Lock
;
159 seglist
= LoadSeg(name
);
167 Library *LDInit(seglist, DOSBase)
168 Initialise the library.
170 static struct Library
*
171 LDInit(BPTR seglist
, struct DosLibrary
*DOSBase
)
173 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
178 STRPTR addr
= (STRPTR
)((LONG
)BADDR(seg
)-sizeof(ULONG
));
179 ULONG size
= *(ULONG
*)addr
;
182 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
183 size
-= sizeof(BPTR
) + sizeof(ULONG
);
184 size
>= sizeof(struct Resident
) ;
185 size
-= AROS_PTRALIGN
, addr
+= AROS_PTRALIGN
188 struct Resident
*res
= (struct Resident
*)addr
;
189 if( res
->rt_MatchWord
== RTC_MATCHWORD
190 && res
->rt_MatchTag
== res
)
194 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
196 lib
= InitResident(res
, seglist
);
198 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
204 seg
= *(BPTR
*)BADDR(seg
);
206 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist
));
211 struct Library
*AROS_SLIB_ENTRY(OpenLibrary
, Exec
)();
212 BYTE
AROS_SLIB_ENTRY(OpenDevice
, Exec
)();
214 #define ExecOpenLibrary(libname, version) \
215 AROS_CALL2(struct Library *, &AROS_SLIB_ENTRY(OpenLibrary, Exec), \
216 AROS_LCA(STRPTR, libname, A1), \
217 AROS_LCA(ULONG, version, D0), \
218 struct ExecBase *, SysBase)
220 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
221 AROS_CALL4(BYTE, &AROS_SLIB_ENTRY(OpenDevice, Exec), \
222 AROS_LCA(STRPTR, devname, A0), \
223 AROS_LCA(ULONG, unitNumber, D0), \
224 AROS_LCA(struct IORequest *, iORequest, A1), \
225 AROS_LCA(ULONG, flags, D1), \
226 struct ExecBase *, SysBase)
230 struct Node ldon_Node
;
231 struct SignalSemaphore ldon_SigSem
;
232 ULONG ldon_AccessCount
;
234 struct Task
*ldon_FirstLocker
;
238 struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct DosLibrary
*DOSBase
)
240 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
242 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
245 ULONG len
= strlen(name
);
246 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
249 CopyMem(name
, dupname
, len
);
251 ret
->ldon_Node
.ln_Name
= dupname
;
252 InitSemaphore(&ret
->ldon_SigSem
);
253 ret
->ldon_AccessCount
= 0;
256 ret
->ldon_FirstLocker
= FindTask(0);
267 VOID
LDDestroyObjectNode(struct LDObjectNode
*object
, struct DosLibrary
*DOSBase
)
269 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
271 FreeVec(object
->ldon_Node
.ln_Name
);
275 AROS_LH2(struct Library
*, OpenLibrary
,
276 AROS_LHA(STRPTR
, libname
, A1
),
277 AROS_LHA(ULONG
, version
, D0
),
278 struct ExecBase
*, SysBase
, 0, Dos
)
281 AROS_LIBBASE_EXT_DECL(struct ExecBase
*,SysBase
)
283 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
284 struct Library
*library
, *tmplib
;
285 STRPTR stripped_libname
;
286 struct LDObjectNode
*object
;
289 We get the DOS semaphore to prevent the following:
290 - task 1 tries to open foobar.library, needs to load it from disk...
291 - task 1 Permit()'s (since its not doing list things)
292 - task switch (whilst LDDemon MAY get process next it might not)
293 - task 2 tries to open foobar.library, needs to load it from disk...
294 - it also requests LDDemon to open foobar.library, so it is now
295 trying to open it twice
297 We block all OpenLibrary() callers from searching the list until
298 all the other OpenLibrary() callers have returned. That way,
299 task #2 won't ask for foobar.library until task #1 has got its
300 response back from the LDDemon process.
302 falemagn: I changed the implementation of all that.
303 There's a list of "LDObjectNodes", that contain the name
304 of the object being opened. Since the problem is that more
305 processes can attempt to open the same device/library Instead of
306 locking a global semaphore until the opening is done, we lock a
307 per-object semaphore, so that others libraries/devices can be opened
308 in the meantime. Beofore a deadlock could happen if there was a
311 Process A opens L --------> LDDemon loads L and locks sem S
317 L spawns a process B and ----------> The process opens
318 waits for it to respond a library but gets loked
319 to a message <----/---- because sem S is locked
326 Hopefully this won't happen anymore now.
330 /* We use FilePart() because the liblist is built from resident IDs,
331 and contain no path. Eg. The user can request gadgets/foo.gadget,
332 but the resident only contains foo.gadget
334 stripped_libname
= FilePart(libname
);
335 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
336 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_libname
);
339 object
= LDNewObjectNode(stripped_libname
, DOSBase
);
342 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
348 object
->ldon_AccessCount
+= 1;
353 struct Task
*curtask
= FindTask(0);
354 struct ETask
*et
= GetETask(curtask
);
356 D(bug("Checking for circular dependency\n"));
359 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
360 curtask
= et
->et_Parent
;
364 bug("Circular dependency found!\n");
370 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
376 ObtainSemaphore(&object
->ldon_SigSem
);
378 /* Call the EXEC's OpenLibrary function */
379 library
= ExecOpenLibrary(stripped_libname
, version
);
381 if( library
== NULL
)
383 /* Use stack for now, this could be a security hole */
386 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
387 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
388 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
389 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
390 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
392 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
394 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
395 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
397 ldd
.ldd_Name
= libname
;
398 ldd
.ldd_Version
= version
;
399 ldd
.ldd_BaseDir
= "libs:";
401 SetSignal(0, SIGF_SINGLE
);
402 D(bug("[LDCaller] Sending request for %s v%ld\n", libname
, version
));
403 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
404 WaitPort(&ldd
.ldd_ReplyPort
);
405 D(bug("[LDCaller] Returned\n"));
407 library
= LDInit(ldd
.ldd_Return
, DOSBase
);
409 if( library
!= NULL
)
412 We have to Forbid() here because we need to look through the list
413 again, we also need to call the libOpen vector, which wants us
414 under a Forbidden state.
416 falemagn: well, it doesn't want us under a Forbidden state, it just
417 wants to be single threaded, and it is, in fact, so no
418 need for Forbid()/Permit() around open. I Hope... :)
422 tmplib
= (struct Library
*)FindName(&SysBase
->LibList
, stripped_libname
);
428 if(library
->lib_Version
>= version
)
430 D(bug("[LDCaller] Calling libOpen() of %s\n",
431 library
->lib_Node
.ln_Name
));
433 library
= AROS_LVO_CALL1(struct Library
*,
434 AROS_LCA(ULONG
, version
, D0
),
435 struct Library
*, library
, 1,
438 D(bug("[LDCaller] libOpen() returned\n"));
448 the library is not on disk so
452 struct Resident
*resident
;
454 resident
= FindResident(stripped_libname
);
457 if (resident
->rt_Version
>= version
)
459 if (InitResident(resident
, NULL
))
460 library
= ExecOpenLibrary(stripped_libname
, version
);
466 Release the semaphore here, after calling Open vector. This
467 means that library open is singlethreaded by the semaphore.
468 It also handles circular dependant libraries. (Won't deadlock),
469 and recursive OpenLibrary calls (Semaphores nest when obtained
470 several times in a row by the same task).
472 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
473 if (--(object
->ldon_AccessCount
) == 0)
475 Remove((struct Node
*)object
);
476 LDDestroyObjectNode(object
, DOSBase
);
479 ReleaseSemaphore(&object
->ldon_SigSem
);
480 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
487 AROS_LH4(BYTE
, OpenDevice
,
488 AROS_LHA(STRPTR
, devname
, A0
),
489 AROS_LHA(ULONG
, unitNumber
, D0
),
490 AROS_LHA(struct IORequest
*, iORequest
, A1
),
491 AROS_LHA(ULONG
, flags
, D1
),
492 struct ExecBase
*, SysBase
, 0, Dos
)
496 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
497 struct Device
*tmpdev
;
498 STRPTR stripped_devname
;
499 struct LDObjectNode
*object
;
501 iORequest
->io_Error
= IOERR_OPENFAIL
;
502 iORequest
->io_Device
= NULL
;
504 /* We use FilePart() because the liblist is built from resident IDs,
505 and contain no path. Eg. The user can request gadgets/foo.gadget,
506 but the resident only contains foo.gadget
509 stripped_devname
= FilePart(devname
);
511 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
512 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_devname
);
516 object
= LDNewObjectNode(stripped_devname
, DOSBase
);
519 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
525 object
->ldon_AccessCount
+= 1;
530 struct Task
*curtask
= FindTask(0);
531 struct ETask
*et
= GetETask(curtask
);
535 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
536 curtask
= et
->et_Parent
;
540 bug("[LDCaller] Circular dependency found!\n");
546 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
549 return IOERR_OPENFAIL
;
551 ObtainSemaphore(&object
->ldon_SigSem
);
553 ExecOpenDevice(stripped_devname
, unitNumber
, iORequest
, flags
);
555 if (iORequest
->io_Error
)
557 /* Use stack for now, this could be a security hole */
560 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
561 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
562 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
563 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
564 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
566 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
567 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
568 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
570 ldd
.ldd_Name
= devname
;
571 ldd
.ldd_BaseDir
= "devs:";
573 SetSignal(0, SIGF_SINGLE
);
574 D(bug("[LDCaller] Sending request for %s\n", devname
));
575 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
576 WaitPort(&ldd
.ldd_ReplyPort
);
577 D(bug("[LDCaller] Returned\n"));
579 iORequest
->io_Device
= (struct Device
*)LDInit(ldd
.ldd_Return
, DOSBase
);
581 if(iORequest
->io_Device
)
584 tmpdev
= (struct Device
*)FindName(&SysBase
->DeviceList
, stripped_devname
);
588 iORequest
->io_Device
= tmpdev
;
590 iORequest
->io_Error
= 0;
591 iORequest
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
593 D(bug("[LDCaller] Calling devOpen() of %s unit %ld\n",
594 iORequest
->io_Device
->dd_Library
.lib_Node
.ln_Name
, unitNumber
));
597 AROS_LCA(struct IORequest
*, iORequest
, A1
),
598 AROS_LCA(ULONG
, unitNumber
, D0
),
599 AROS_LCA(ULONG
, flags
, D1
),
600 struct Device
*, iORequest
->io_Device
, 1,
603 D(bug("[LDCaller] devOpen() returned\n"));
605 if (iORequest
->io_Error
)
606 iORequest
->io_Device
= NULL
;
610 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
611 if (--(object
->ldon_AccessCount
) == 0)
613 Remove((struct Node
*)object
);
614 LDDestroyObjectNode(object
, DOSBase
);
617 ReleaseSemaphore(&object
->ldon_SigSem
);
618 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
620 D(bug("%s", iORequest
->io_Error
?"[LDCaller] Couldn't open the device\n":""));
622 return iORequest
->io_Error
;
627 AROS_LH1(void, CloseLibrary
,
628 AROS_LHA(struct Library
*, library
, A1
),
629 struct ExecBase
*, SysBase
, 0, Dos
)
633 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
636 if( library
!= NULL
)
639 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
642 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
644 /* Safe to call from a Task */
653 AROS_LH1(void, CloseDevice
,
654 AROS_LHA(struct IORequest
*, iORequest
, A1
),
655 struct ExecBase
*, SysBase
, 0, Dos
)
658 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
662 if( iORequest
->io_Device
!= NULL
)
664 seglist
= AROS_LVO_CALL1(BPTR
,
665 AROS_LCA(struct IORequest
*, iORequest
, A1
),
666 struct Device
, iORequest
->io_Device
, 2, );
667 iORequest
->io_Device
=(struct Device
*)-1;
670 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
678 AROS_LH1(void, RemLibrary
,
679 AROS_LHA(struct Library
*, library
, A1
),
680 struct ExecBase
*, SysBase
, 0, Dos
)
684 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
688 seglist
= AROS_LVO_CALL1(BPTR
,
689 AROS_LCA(struct Library
*, library
, D0
),
690 struct Library
*, library
, 3, );
693 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
701 AROS_UFH3(LONG
, LDFlush
,
702 AROS_UFHA(struct MemHandlerData
*, lmhd
, A0
),
703 AROS_UFHA(APTR
, data
, A1
),
704 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
709 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
710 struct Library
*library
;
712 D(bug("[LDDemon] Flush called\n"));
713 DOSBase
->dl_LDReturn
= MEM_DID_NOTHING
;
715 /* Forbid() is already done, but I don't want to rely on it. */
718 /* Follow the linked list of shared libraries. */
719 library
= (struct Library
*)SysBase
->LibList
.lh_Head
;
720 while(library
->lib_Node
.ln_Succ
!= NULL
)
722 /* Flush libraries with a 0 open count */
723 if( ! library
->lib_OpenCnt
)
726 /* Did it really go away? */
727 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
729 /* Yes! Return it. */
731 return MEM_TRY_AGAIN
;
734 /* Go on to next library. */
735 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
738 /* Do the same with the device list. */
739 library
= (struct Library
*)SysBase
->DeviceList
.lh_Head
;
740 while(library
->lib_Node
.ln_Succ
!= NULL
)
742 /* Flush libraries with a 0 open count */
743 if( ! library
->lib_OpenCnt
)
745 RemDevice((struct Device
*)library
);
746 /* Did it really go away? */
747 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
749 /* Yes! Return it. */
751 return MEM_TRY_AGAIN
;
754 /* Go on to next library. */
755 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
758 return MEM_DID_NOTHING
;
765 The LDDemon process entry. Sits around and does nothing until a
766 request for a library comes, when it will then find the library
767 and hopefully open it.
769 AROS_UFH3(void, LDDemon
,
770 AROS_UFHA(STRPTR
, argstr
, A0
),
771 AROS_UFHA(ULONG
, arglen
, D0
),
772 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
777 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
782 WaitPort(DOSBase
->dl_LDDemonPort
);
783 while( (ldd
= (struct LDDMsg
*)GetMsg(DOSBase
->dl_LDDemonPort
)) )
785 D(bug("[LDDemon] Got a request for %s in %s\n",
786 ldd
->ldd_Name
, ldd
->ldd_BaseDir
));
788 ldd
->ldd_Return
= LDLoad(
789 ldd
->ldd_ReplyPort
.mp_SigTask
,
794 if (ldd
->ldd_Return
== 0)
795 bug("[LDDemon] Could not open %s\n",ldd
->ldd_Name
);
797 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
798 ReplyMsg((struct Message
*)ldd
);
799 } /* messages available */
805 AROS_UFH3(ULONG
, AROS_SLIB_ENTRY(Init
, LDDemon
),
806 AROS_UFHA(ULONG
, dummy
, D0
),
807 AROS_UFHA(BPTR
, segList
, A0
),
808 AROS_UFHA(struct ExecBase
*, sysBase
, A6
)
814 struct Library
*AROS_SLIB_ENTRY(OpenLibrary
,Dos
)();
815 BYTE
AROS_SLIB_ENTRY(OpenDevice
,Dos
)();
816 void AROS_SLIB_ENTRY(CloseLibrary
,Dos
)();
817 void AROS_SLIB_ENTRY(CloseDevice
,Dos
)();
818 void AROS_SLIB_ENTRY(RemLibrary
,Dos
)();
820 struct DosLibrary
*DOSBase
;
821 struct TagItem tags
[] =
823 { NP_Entry
, (IPTR
)LDDemon
},
826 { NP_Name
, (IPTR
)ldDemonName
},
827 { NP_StackSize
, AROS_STACKSIZE
},
831 /* We want version v41 of DOS, since it corresponds to AROS atm... */
832 if((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 41)) == NULL
)
834 Alert(AT_DeadEnd
| AN_RAMLib
| AG_OpenLib
| AO_DOSLib
);
837 SysBase
->ex_RamLibPrivate
= DOSBase
;
839 if( (DOSBase
->dl_LDDemonPort
= CreateMsgPort()) == NULL
)
841 Alert( AN_RAMLib
| AG_NoMemory
| AT_DeadEnd
);
844 FreeSignal(DOSBase
->dl_LDDemonPort
->mp_SigBit
);
845 DOSBase
->dl_LDDemonPort
->mp_SigBit
= SIGBREAKB_CTRL_F
;
847 DOSBase
->dl_LDHandler
.is_Node
.ln_Name
= (STRPTR
)ldDemonName
;
848 DOSBase
->dl_LDHandler
.is_Node
.ln_Pri
= 0;
849 DOSBase
->dl_LDHandler
.is_Code
= (void (*)())LDFlush
;
850 DOSBase
->dl_LDHandler
.is_Data
= NULL
;
852 NEWLIST(&DOSBase
->dl_LDObjectsList
);
853 InitSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
854 AddMemHandler(&DOSBase
->dl_LDHandler
);
857 * Grab the semaphore ourself. The reason for this is that it will
858 * cause all other tasks to wait until we have finished initialising
859 * before they try and open something.
861 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
863 #define SetFunc(offs,ptr) \
864 (void)SetFunction(&SysBase->LibNode, (offs)*LIB_VECTSIZE, \
865 AROS_SLIB_ENTRY(ptr,Dos))
867 /* Do not set the vectors until you have initialised everything else. */
868 SetFunc(-92, OpenLibrary
);
869 SetFunc(-74, OpenDevice
);
870 SetFunc(-69, CloseLibrary
);
871 SetFunc(-75, CloseDevice
);
872 SetFunc(-67, RemLibrary
);
873 SetFunc(-73, RemLibrary
);
875 if( !(DOSBase
->dl_LDDemonTask
= CreateNewProc((struct TagItem
*)tags
)) )
877 Alert( AT_DeadEnd
| AN_RAMLib
| AG_ProcCreate
);
880 /* Fix up the MsgPort */
882 DOSBase
->dl_LDDemonPort
->mp_SigTask
= DOSBase
->dl_LDDemonTask
;
884 /* Then unlock the semaphore to allow other processes to run. */
885 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
892 const int LIBEND TEXT_SECTION
= 1;