2 Copyright © 1995-2007, 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.3 (11.3.2007)\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
);
121 If the caller was a process, we have more scope for loading
122 libraries. We can load them from the callers current directory,
123 or from the PROGDIR: assign. These could both be the same
127 "[LDLoad] caller=(%p) %s, name=%s, basedir=%s\n",
128 caller
, caller
->pr_Task
.tc_Node
.ln_Name
, name
, basedir
131 if (!strstr(name
, ":")) {
132 delimPos
= strlen(basedir
);
133 pathLen
= delimPos
+ strlen(name
) + 2;
134 path
= AllocMem(pathLen
, MEMF_ANY
);
136 strcpy(path
, basedir
);
137 path
[delimPos
] = '/';
138 strcpy(&path
[delimPos
+ 1], name
);
140 if (__is_process(caller
))
142 /* Try the current directory of the caller */
144 D(bug("[LDLoad] Process\n"));
145 me
->pr_CurrentDir
= caller
->pr_CurrentDir
;
146 D(bug("[LDLoad] Trying currentdir\n"));
147 seglist
= LoadSeg(name
);
148 if ((!seglist
) && path
)
149 seglist
= LoadSeg(path
);
151 /* The the program directory of the caller */
152 if((!seglist
) && (caller
->pr_HomeDir
!= NULL
))
154 D(bug("[LDLoad] Trying homedir\n"));
155 me
->pr_CurrentDir
= caller
->pr_HomeDir
;
156 seglist
= LoadSeg(name
);
157 if ((!seglist
) && path
)
158 seglist
= LoadSeg(path
);
164 /* Nup, lets try the default directory as supplied. */
165 D(bug("[LDLoad] Trying defaultir\n"));
166 path
[delimPos
] = ':';
167 seglist
= LoadSeg(path
);
169 FreeMem(path
, pathLen
);
172 seglist
=LoadSeg(name
);
178 Library *LDInit(seglist, DOSBase)
179 Initialise the library.
181 static struct Library
*
182 LDInit(BPTR seglist
, struct DosLibrary
*DOSBase
)
184 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
189 STRPTR addr
= (STRPTR
)((LONG
)BADDR(seg
)-sizeof(ULONG
));
190 ULONG size
= *(ULONG
*)addr
;
193 addr
+= sizeof(BPTR
) + sizeof(ULONG
),
194 size
-= sizeof(BPTR
) + sizeof(ULONG
);
195 size
>= sizeof(struct Resident
) ;
196 size
-= AROS_PTRALIGN
, addr
+= AROS_PTRALIGN
199 struct Resident
*res
= (struct Resident
*)addr
;
200 if( res
->rt_MatchWord
== RTC_MATCHWORD
201 && res
->rt_MatchTag
== res
)
205 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
207 lib
= InitResident(res
, seglist
);
209 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res
, res
->rt_Name
));
215 seg
= *(BPTR
*)BADDR(seg
);
217 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist
));
222 struct Library
*AROS_SLIB_ENTRY(OpenLibrary
, Exec
)();
223 BYTE
AROS_SLIB_ENTRY(OpenDevice
, Exec
)();
225 #define ExecOpenLibrary(libname, version) \
226 AROS_CALL2(struct Library *, &AROS_SLIB_ENTRY(OpenLibrary, Exec), \
227 AROS_LCA(STRPTR, libname, A1), \
228 AROS_LCA(ULONG, version, D0), \
229 struct ExecBase *, SysBase)
231 #define ExecOpenDevice(devname, unitNumber, iORequest, flags) \
232 AROS_CALL4(BYTE, &AROS_SLIB_ENTRY(OpenDevice, Exec), \
233 AROS_LCA(STRPTR, devname, A0), \
234 AROS_LCA(ULONG, unitNumber, D0), \
235 AROS_LCA(struct IORequest *, iORequest, A1), \
236 AROS_LCA(ULONG, flags, D1), \
237 struct ExecBase *, SysBase)
241 struct Node ldon_Node
;
242 struct SignalSemaphore ldon_SigSem
;
243 ULONG ldon_AccessCount
;
245 struct Task
*ldon_FirstLocker
;
249 struct LDObjectNode
*LDNewObjectNode(STRPTR name
, struct DosLibrary
*DOSBase
)
251 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
253 struct LDObjectNode
*ret
= AllocVec(sizeof(struct LDObjectNode
), MEMF_ANY
);
256 ULONG len
= strlen(name
);
257 STRPTR dupname
= AllocVec(len
+1, MEMF_ANY
);
260 CopyMem(name
, dupname
, len
);
262 ret
->ldon_Node
.ln_Name
= dupname
;
263 InitSemaphore(&ret
->ldon_SigSem
);
264 ret
->ldon_AccessCount
= 0;
267 ret
->ldon_FirstLocker
= FindTask(0);
278 VOID
LDDestroyObjectNode(struct LDObjectNode
*object
, struct DosLibrary
*DOSBase
)
280 struct ExecBase
*SysBase
= DOSBase
->dl_SysBase
;
282 FreeVec(object
->ldon_Node
.ln_Name
);
286 AROS_LH2(struct Library
*, OpenLibrary
,
287 AROS_LHA(STRPTR
, libname
, A1
),
288 AROS_LHA(ULONG
, version
, D0
),
289 struct ExecBase
*, SysBase
, 0, Dos
)
292 AROS_LIBBASE_EXT_DECL(struct ExecBase
*,SysBase
)
294 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
295 struct Library
*library
, *tmplib
;
296 STRPTR stripped_libname
;
297 struct LDObjectNode
*object
;
300 We get the DOS semaphore to prevent the following:
301 - task 1 tries to open foobar.library, needs to load it from disk...
302 - task 1 Permit()'s (since its not doing list things)
303 - task switch (whilst LDDemon MAY get process next it might not)
304 - task 2 tries to open foobar.library, needs to load it from disk...
305 - it also requests LDDemon to open foobar.library, so it is now
306 trying to open it twice
308 We block all OpenLibrary() callers from searching the list until
309 all the other OpenLibrary() callers have returned. That way,
310 task #2 won't ask for foobar.library until task #1 has got its
311 response back from the LDDemon process.
313 falemagn: I changed the implementation of all that.
314 There's a list of "LDObjectNodes", that contain the name
315 of the object being opened. Since the problem is that more
316 processes can attempt to open the same device/library Instead of
317 locking a global semaphore until the opening is done, we lock a
318 per-object semaphore, so that others libraries/devices can be opened
319 in the meantime. Beofore a deadlock could happen if there was a
322 Process A opens L --------> LDDemon loads L and locks sem S
328 L spawns a process B and ----------> The process opens
329 waits for it to respond a library but gets loked
330 to a message <----/---- because sem S is locked
337 Hopefully this won't happen anymore now.
341 /* We use FilePart() because the liblist is built from resident IDs,
342 and contain no path. Eg. The user can request gadgets/foo.gadget,
343 but the resident only contains foo.gadget
345 stripped_libname
= FilePart(libname
);
346 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
347 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_libname
);
350 object
= LDNewObjectNode(stripped_libname
, DOSBase
);
353 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
359 object
->ldon_AccessCount
+= 1;
364 struct Task
*curtask
= FindTask(0);
365 struct ETask
*et
= GetETask(curtask
);
367 D(bug("Checking for circular dependency\n"));
370 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
371 curtask
= et
->et_Parent
;
375 bug("Circular dependency found!\n");
381 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
387 ObtainSemaphore(&object
->ldon_SigSem
);
389 /* Call the EXEC's OpenLibrary function */
390 library
= ExecOpenLibrary(stripped_libname
, version
);
392 if( library
== NULL
)
394 /* Use stack for now, this could be a security hole */
397 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
398 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
399 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
400 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
401 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
403 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
405 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
406 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
408 ldd
.ldd_Name
= libname
;
409 ldd
.ldd_Version
= version
;
410 ldd
.ldd_BaseDir
= "libs";
412 SetSignal(0, SIGF_SINGLE
);
413 D(bug("[LDCaller] Sending request for %s v%ld\n", libname
, version
));
414 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
415 WaitPort(&ldd
.ldd_ReplyPort
);
416 D(bug("[LDCaller] Returned\n"));
418 library
= LDInit(ldd
.ldd_Return
, DOSBase
);
420 if( library
!= NULL
)
423 We have to Forbid() here because we need to look through the list
424 again, we also need to call the libOpen vector, which wants us
425 under a Forbidden state.
427 falemagn: well, it doesn't want us under a Forbidden state, it just
428 wants to be single threaded, and it is, in fact, so no
429 need for Forbid()/Permit() around open. I Hope... :)
433 tmplib
= (struct Library
*)FindName(&SysBase
->LibList
, stripped_libname
);
439 if(library
->lib_Version
>= version
)
441 D(bug("[LDCaller] Calling libOpen() of %s\n",
442 library
->lib_Node
.ln_Name
));
444 library
= AROS_LVO_CALL1(struct Library
*,
445 AROS_LCA(ULONG
, version
, D0
),
446 struct Library
*, library
, 1,
449 D(bug("[LDCaller] libOpen() returned\n"));
459 the library is not on disk so
463 struct Resident
*resident
;
465 resident
= FindResident(stripped_libname
);
468 if (resident
->rt_Version
>= version
)
470 if (InitResident(resident
, NULL
))
471 library
= ExecOpenLibrary(stripped_libname
, version
);
477 Release the semaphore here, after calling Open vector. This
478 means that library open is singlethreaded by the semaphore.
479 It also handles circular dependant libraries. (Won't deadlock),
480 and recursive OpenLibrary calls (Semaphores nest when obtained
481 several times in a row by the same task).
483 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
484 if (--(object
->ldon_AccessCount
) == 0)
486 Remove((struct Node
*)object
);
487 LDDestroyObjectNode(object
, DOSBase
);
490 ReleaseSemaphore(&object
->ldon_SigSem
);
491 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
498 AROS_LH4(BYTE
, OpenDevice
,
499 AROS_LHA(STRPTR
, devname
, A0
),
500 AROS_LHA(ULONG
, unitNumber
, D0
),
501 AROS_LHA(struct IORequest
*, iORequest
, A1
),
502 AROS_LHA(ULONG
, flags
, D1
),
503 struct ExecBase
*, SysBase
, 0, Dos
)
507 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
508 struct Device
*tmpdev
;
509 STRPTR stripped_devname
;
510 struct LDObjectNode
*object
;
512 iORequest
->io_Error
= IOERR_OPENFAIL
;
513 iORequest
->io_Device
= NULL
;
515 /* We use FilePart() because the liblist is built from resident IDs,
516 and contain no path. Eg. The user can request gadgets/foo.gadget,
517 but the resident only contains foo.gadget
520 stripped_devname
= FilePart(devname
);
522 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
523 object
= (struct LDObjectNode
*)FindName(&DOSBase
->dl_LDObjectsList
, stripped_devname
);
527 object
= LDNewObjectNode(stripped_devname
, DOSBase
);
530 AddTail(&DOSBase
->dl_LDObjectsList
, (struct Node
*)object
);
536 object
->ldon_AccessCount
+= 1;
541 struct Task
*curtask
= FindTask(0);
542 struct ETask
*et
= GetETask(curtask
);
546 while (curtask
&& curtask
!= object
->ldon_FirstLocker
)
547 curtask
= et
->et_Parent
;
551 bug("[LDCaller] Circular dependency found!\n");
557 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
560 return IOERR_OPENFAIL
;
562 ObtainSemaphore(&object
->ldon_SigSem
);
564 ExecOpenDevice(stripped_devname
, unitNumber
, iORequest
, flags
);
566 if (iORequest
->io_Error
)
568 /* Use stack for now, this could be a security hole */
571 ldd
.ldd_ReplyPort
.mp_SigBit
= SIGB_SINGLE
;
572 ldd
.ldd_ReplyPort
.mp_SigTask
= FindTask(NULL
);
573 NEWLIST(&ldd
.ldd_ReplyPort
.mp_MsgList
);
574 ldd
.ldd_ReplyPort
.mp_Flags
= PA_SIGNAL
;
575 ldd
.ldd_ReplyPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
577 ldd
.ldd_Msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
578 ldd
.ldd_Msg
.mn_Length
= sizeof(struct LDDMsg
);
579 ldd
.ldd_Msg
.mn_ReplyPort
= &ldd
.ldd_ReplyPort
;
581 ldd
.ldd_Name
= devname
;
582 ldd
.ldd_BaseDir
= "devs";
584 SetSignal(0, SIGF_SINGLE
);
585 D(bug("[LDCaller] Sending request for %s\n", devname
));
586 PutMsg(DOSBase
->dl_LDDemonPort
, (struct Message
*)&ldd
);
587 WaitPort(&ldd
.ldd_ReplyPort
);
588 D(bug("[LDCaller] Returned\n"));
590 iORequest
->io_Device
= (struct Device
*)LDInit(ldd
.ldd_Return
, DOSBase
);
592 if(iORequest
->io_Device
)
595 tmpdev
= (struct Device
*)FindName(&SysBase
->DeviceList
, stripped_devname
);
599 iORequest
->io_Device
= tmpdev
;
601 iORequest
->io_Error
= 0;
602 iORequest
->io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
604 D(bug("[LDCaller] Calling devOpen() of %s unit %ld\n",
605 iORequest
->io_Device
->dd_Library
.lib_Node
.ln_Name
, unitNumber
));
608 AROS_LCA(struct IORequest
*, iORequest
, A1
),
609 AROS_LCA(ULONG
, unitNumber
, D0
),
610 AROS_LCA(ULONG
, flags
, D1
),
611 struct Device
*, iORequest
->io_Device
, 1,
614 D(bug("[LDCaller] devOpen() returned\n"));
616 if (iORequest
->io_Error
)
617 iORequest
->io_Device
= NULL
;
621 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
622 if (--(object
->ldon_AccessCount
) == 0)
624 Remove((struct Node
*)object
);
625 LDDestroyObjectNode(object
, DOSBase
);
628 ReleaseSemaphore(&object
->ldon_SigSem
);
629 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
631 D(bug("%s", iORequest
->io_Error
?"[LDCaller] Couldn't open the device\n":""));
633 return iORequest
->io_Error
;
638 AROS_LH1(void, CloseLibrary
,
639 AROS_LHA(struct Library
*, library
, A1
),
640 struct ExecBase
*, SysBase
, 0, Dos
)
644 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
647 if( library
!= NULL
)
650 seglist
= AROS_LVO_CALL0(BPTR
, struct Library
*, library
, 2, );
653 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
655 /* Safe to call from a Task */
664 AROS_LH1(void, CloseDevice
,
665 AROS_LHA(struct IORequest
*, iORequest
, A1
),
666 struct ExecBase
*, SysBase
, 0, Dos
)
669 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
673 if( iORequest
->io_Device
!= NULL
)
675 seglist
= AROS_LVO_CALL1(BPTR
,
676 AROS_LCA(struct IORequest
*, iORequest
, A1
),
677 struct Device
, iORequest
->io_Device
, 2, );
678 iORequest
->io_Device
=(struct Device
*)-1;
681 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
689 AROS_LH1(void, RemLibrary
,
690 AROS_LHA(struct Library
*, library
, A1
),
691 struct ExecBase
*, SysBase
, 0, Dos
)
695 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
699 seglist
= AROS_LVO_CALL1(BPTR
,
700 AROS_LCA(struct Library
*, library
, D0
),
701 struct Library
*, library
, 3, );
704 DOSBase
->dl_LDReturn
= MEM_TRY_AGAIN
;
712 AROS_UFH3(LONG
, LDFlush
,
713 AROS_UFHA(struct MemHandlerData
*, lmhd
, A0
),
714 AROS_UFHA(APTR
, data
, A1
),
715 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
720 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
721 struct Library
*library
;
723 D(bug("[LDDemon] Flush called\n"));
724 DOSBase
->dl_LDReturn
= MEM_DID_NOTHING
;
726 /* Forbid() is already done, but I don't want to rely on it. */
729 /* Follow the linked list of shared libraries. */
730 library
= (struct Library
*)SysBase
->LibList
.lh_Head
;
731 while(library
->lib_Node
.ln_Succ
!= NULL
)
733 /* Flush libraries with a 0 open count */
734 if( ! library
->lib_OpenCnt
)
737 /* Did it really go away? */
738 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
740 /* Yes! Return it. */
742 return MEM_TRY_AGAIN
;
745 /* Go on to next library. */
746 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
749 /* Do the same with the device list. */
750 library
= (struct Library
*)SysBase
->DeviceList
.lh_Head
;
751 while(library
->lib_Node
.ln_Succ
!= NULL
)
753 /* Flush libraries with a 0 open count */
754 if( ! library
->lib_OpenCnt
)
756 RemDevice((struct Device
*)library
);
757 /* Did it really go away? */
758 if( DOSBase
->dl_LDReturn
!= MEM_DID_NOTHING
)
760 /* Yes! Return it. */
762 return MEM_TRY_AGAIN
;
765 /* Go on to next library. */
766 library
= (struct Library
*)library
->lib_Node
.ln_Succ
;
769 return MEM_DID_NOTHING
;
776 The LDDemon process entry. Sits around and does nothing until a
777 request for a library comes, when it will then find the library
778 and hopefully open it.
780 AROS_UFH3(void, LDDemon
,
781 AROS_UFHA(STRPTR
, argstr
, A0
),
782 AROS_UFHA(ULONG
, arglen
, D0
),
783 AROS_UFHA(struct ExecBase
*, SysBase
, A6
)
788 struct DosLibrary
*DOSBase
= SysBase
->ex_RamLibPrivate
;
793 WaitPort(DOSBase
->dl_LDDemonPort
);
794 while( (ldd
= (struct LDDMsg
*)GetMsg(DOSBase
->dl_LDDemonPort
)) )
796 D(bug("[LDDemon] Got a request for %s in %s\n",
797 ldd
->ldd_Name
, ldd
->ldd_BaseDir
));
799 ldd
->ldd_Return
= LDLoad(
800 ldd
->ldd_ReplyPort
.mp_SigTask
,
805 if (ldd
->ldd_Return
== 0)
806 bug("[LDDemon] Could not open %s\n",ldd
->ldd_Name
);
808 D(bug("[LDDemon] Replying with %p as result\n", ldd
->ldd_Return
));
809 ReplyMsg((struct Message
*)ldd
);
810 } /* messages available */
816 AROS_UFH3(ULONG
, AROS_SLIB_ENTRY(Init
, LDDemon
),
817 AROS_UFHA(ULONG
, dummy
, D0
),
818 AROS_UFHA(BPTR
, segList
, A0
),
819 AROS_UFHA(struct ExecBase
*, sysBase
, A6
)
824 struct Library
*AROS_SLIB_ENTRY(OpenLibrary
,Dos
)();
825 BYTE
AROS_SLIB_ENTRY(OpenDevice
,Dos
)();
826 void AROS_SLIB_ENTRY(CloseLibrary
,Dos
)();
827 void AROS_SLIB_ENTRY(CloseDevice
,Dos
)();
828 void AROS_SLIB_ENTRY(RemLibrary
,Dos
)();
830 struct DosLibrary
*DOSBase
;
831 struct TagItem tags
[] =
833 { NP_Entry
, (IPTR
)LDDemon
},
836 { NP_Name
, (IPTR
)ldDemonName
},
837 { NP_StackSize
, AROS_STACKSIZE
},
841 /* We want version v41 of DOS, since it corresponds to AROS atm... */
842 if((DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library", 41)) == NULL
)
844 Alert(AT_DeadEnd
| AN_RAMLib
| AG_OpenLib
| AO_DOSLib
);
847 SysBase
->ex_RamLibPrivate
= DOSBase
;
849 if( (DOSBase
->dl_LDDemonPort
= CreateMsgPort()) == NULL
)
851 Alert( AN_RAMLib
| AG_NoMemory
| AT_DeadEnd
);
854 FreeSignal(DOSBase
->dl_LDDemonPort
->mp_SigBit
);
855 DOSBase
->dl_LDDemonPort
->mp_SigBit
= SIGBREAKB_CTRL_F
;
857 DOSBase
->dl_LDHandler
.is_Node
.ln_Name
= (STRPTR
)ldDemonName
;
858 DOSBase
->dl_LDHandler
.is_Node
.ln_Pri
= 0;
859 DOSBase
->dl_LDHandler
.is_Code
= (void (*)())LDFlush
;
860 DOSBase
->dl_LDHandler
.is_Data
= NULL
;
862 NEWLIST(&DOSBase
->dl_LDObjectsList
);
863 InitSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
864 AddMemHandler(&DOSBase
->dl_LDHandler
);
867 * Grab the semaphore ourself. The reason for this is that it will
868 * cause all other tasks to wait until we have finished initialising
869 * before they try and open something.
871 ObtainSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
873 #define SetFunc(offs,ptr) \
874 (void)SetFunction(&SysBase->LibNode, (offs)*LIB_VECTSIZE, \
875 AROS_SLIB_ENTRY(ptr,Dos))
877 /* Do not set the vectors until you have initialised everything else. */
878 SetFunc(-92, OpenLibrary
);
879 SetFunc(-74, OpenDevice
);
880 SetFunc(-69, CloseLibrary
);
881 SetFunc(-75, CloseDevice
);
882 SetFunc(-67, RemLibrary
);
883 SetFunc(-73, RemLibrary
);
885 if( !(DOSBase
->dl_LDDemonTask
= CreateNewProc((struct TagItem
*)tags
)) )
887 Alert( AT_DeadEnd
| AN_RAMLib
| AG_ProcCreate
);
890 /* Fix up the MsgPort */
892 DOSBase
->dl_LDDemonPort
->mp_SigTask
= DOSBase
->dl_LDDemonTask
;
894 /* Then unlock the semaphore to allow other processes to run. */
895 ReleaseSemaphore(&DOSBase
->dl_LDObjectsListSigSem
);
902 const int LIBEND TEXT_SECTION
= 1;