r4548@vps: verhaegs | 2007-04-23 10:55:24 -0400
[AROS.git] / rom / dos / lddemon.c
blob8f17be5ef4b9eb036a39eea3095af0ddca2b9918
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Loader for shared libraries and devices.
6 */
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>
18 #include <dos/dos.h>
19 #include <dos/dosextens.h>
20 #include <dos/dostags.h>
21 #include <aros/asmcall.h>
22 #define DEBUG 0
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
30 #include <string.h>
32 #undef SysBase
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);
57 struct LDDMsg
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 */
69 #ifdef LIBEND
70 #undef LIBEND
71 #endif
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 =
83 RTC_MATCHWORD,
84 (struct Resident *)&LDDemon_resident,
85 &LIBEND,
86 RTF_AFTERDOS,
87 VERSION_NUMBER,
88 NT_PROCESS,
89 -125,
90 (STRPTR)name,
91 (STRPTR)&version[6],
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
103 directories.
105 static BPTR
106 LDLoad(
107 struct Process *caller,
108 STRPTR name,
109 STRPTR basedir,
110 struct DosLibrary *DOSBase
113 struct ExecBase *SysBase = DOSBase->dl_SysBase;
114 struct Process *me = (struct Process *)FindTask(NULL);
115 BPTR seglist = NULL;
116 STRPTR path;
117 ULONG pathLen;
118 int delimPos;
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
124 though.
126 D(bug(
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);
135 if (path) {
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);
162 if (path) {
163 if (!seglist) {
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);
171 } else
172 seglist =LoadSeg(name);
174 return seglist;
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;
185 BPTR seg = seglist;
187 while(seg)
189 STRPTR addr= (STRPTR)((LONG)BADDR(seg)-sizeof(ULONG));
190 ULONG size = *(ULONG *)addr;
192 for(
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 )
203 struct Library *lib;
205 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
206 Forbid();
207 lib = InitResident(res, seglist);
208 Permit();
209 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res, res->rt_Name));
210 if( lib == NULL )
211 UnLoadSeg(seglist);
212 return lib;
215 seg = *(BPTR *)BADDR(seg);
217 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
218 UnLoadSeg(seglist);
219 return NULL;
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)
239 struct LDObjectNode
241 struct Node ldon_Node;
242 struct SignalSemaphore ldon_SigSem;
243 ULONG ldon_AccessCount;
244 #if CHECK_DEPENDENCY
245 struct Task *ldon_FirstLocker;
246 #endif
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);
254 if (ret)
256 ULONG len = strlen(name);
257 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
258 if (dupname)
260 CopyMem(name, dupname, len);
261 dupname[len] = '\0';
262 ret->ldon_Node.ln_Name = dupname;
263 InitSemaphore(&ret->ldon_SigSem);
264 ret->ldon_AccessCount = 0;
266 #if CHECK_DEPENDENCY
267 ret->ldon_FirstLocker = FindTask(0);
268 #endif
270 return ret;
272 FreeVec(ret);
275 return NULL;
278 VOID LDDestroyObjectNode(struct LDObjectNode *object, struct DosLibrary *DOSBase)
280 struct ExecBase *SysBase = DOSBase->dl_SysBase;
282 FreeVec(object->ldon_Node.ln_Name);
283 FreeVec(object);
286 AROS_LH2(struct Library *, OpenLibrary,
287 AROS_LHA(STRPTR, libname, A1),
288 AROS_LHA(ULONG, version, D0),
289 struct ExecBase *, SysBase, 0, Dos)
291 AROS_LIBFUNC_INIT
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
320 situation like this:
322 Process A opens L --------> LDDemon loads L and locks sem S
325 1 / \ 3
327 / 2 \
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
334 Proces B will never
335 respond to L.
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);
348 if (!object)
350 object = LDNewObjectNode(stripped_libname, DOSBase);
351 if (object)
353 AddTail(&DOSBase->dl_LDObjectsList, (struct Node *)object);
357 if (object)
359 object->ldon_AccessCount += 1;
361 #if CHECK_DEPENDENCY
362 else
364 struct Task *curtask = FindTask(0);
365 struct ETask *et = GetETask(curtask);
367 D(bug("Checking for circular dependency\n"));
368 if (et)
370 while (curtask && curtask != object->ldon_FirstLocker)
371 curtask = et->et_Parent;
373 if (curtask)
375 bug("Circular dependency found!\n");
376 object = NULL;
380 #endif
381 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
383 if (!object)
384 return NULL;
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 */
395 struct LDDMsg ldd;
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... :)
432 Forbid();
433 tmplib = (struct Library *)FindName(&SysBase->LibList, stripped_libname);
434 Permit();
436 if( tmplib != NULL )
437 library = tmplib;
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"));
451 else
452 library = NULL;
456 if (library == NULL)
459 the library is not on disk so
460 check Resident List
463 struct Resident *resident;
465 resident = FindResident(stripped_libname);
466 if (resident)
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);
489 else
490 ReleaseSemaphore(&object->ldon_SigSem);
491 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
493 return library;
495 AROS_LIBFUNC_EXIT
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)
505 AROS_LIBFUNC_INIT
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);
525 if (!object)
527 object = LDNewObjectNode(stripped_devname, DOSBase);
528 if (object)
530 AddTail(&DOSBase->dl_LDObjectsList, (struct Node*)object);
534 if (object)
536 object->ldon_AccessCount += 1;
538 #if CHECK_DEPENDENCY
539 else
541 struct Task *curtask = FindTask(0);
542 struct ETask *et = GetETask(curtask);
544 if (et)
546 while (curtask && curtask != object->ldon_FirstLocker)
547 curtask = et->et_Parent;
549 if (curtask)
551 bug("[LDCaller] Circular dependency found!\n");
552 object = NULL;
556 #endif
557 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
559 if (!object)
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 */
569 struct LDDMsg ldd;
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)
594 Forbid();
595 tmpdev = (struct Device *)FindName(&SysBase->DeviceList, stripped_devname);
596 Permit();
598 if(tmpdev != NULL)
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));
607 AROS_LVO_CALL3(void,
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);
627 else
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;
635 AROS_LIBFUNC_EXIT
638 AROS_LH1(void, CloseLibrary,
639 AROS_LHA(struct Library *, library, A1),
640 struct ExecBase *, SysBase, 0, Dos)
642 AROS_LIBFUNC_INIT
644 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
645 BPTR seglist;
647 if( library != NULL )
649 Forbid();
650 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
651 if( seglist )
653 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
655 /* Safe to call from a Task */
656 UnLoadSeg(seglist);
658 Permit();
661 AROS_LIBFUNC_EXIT
664 AROS_LH1(void, CloseDevice,
665 AROS_LHA(struct IORequest *, iORequest, A1),
666 struct ExecBase *, SysBase, 0, Dos)
668 AROS_LIBFUNC_INIT
669 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
670 BPTR seglist = NULL;
672 Forbid();
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;
679 if( seglist )
681 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
682 UnLoadSeg(seglist);
685 Permit();
686 AROS_LIBFUNC_EXIT
689 AROS_LH1(void, RemLibrary,
690 AROS_LHA(struct Library *, library, A1),
691 struct ExecBase *, SysBase, 0, Dos)
693 AROS_LIBFUNC_INIT
695 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
696 BPTR seglist;
698 Forbid();
699 seglist = AROS_LVO_CALL1(BPTR,
700 AROS_LCA(struct Library *, library, D0),
701 struct Library *, library, 3, );
702 if( seglist )
704 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
705 UnLoadSeg(seglist);
707 Permit();
709 AROS_LIBFUNC_EXIT
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)
718 AROS_USERFUNC_INIT
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. */
727 Forbid();
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 )
736 RemLibrary(library);
737 /* Did it really go away? */
738 if( DOSBase->dl_LDReturn != MEM_DID_NOTHING )
740 /* Yes! Return it. */
741 Permit();
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. */
761 Permit();
762 return MEM_TRY_AGAIN;
765 /* Go on to next library. */
766 library = (struct Library *)library->lib_Node.ln_Succ;
768 Permit();
769 return MEM_DID_NOTHING;
771 AROS_USERFUNC_EXIT
775 void LDDemon()
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)
786 AROS_USERFUNC_INIT
788 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
789 struct LDDMsg *ldd;
791 for(;;)
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,
801 ldd->ldd_Name,
802 ldd->ldd_BaseDir,
803 DOSBase);
805 if (ldd->ldd_Return == 0)
806 bug("[LDDemon] Could not open %s\n",ldd->ldd_Name);
807 else
808 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
809 ReplyMsg((struct Message *)ldd);
810 } /* messages available */
813 AROS_USERFUNC_EXIT
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)
822 AROS_USERFUNC_INIT
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 },
834 { NP_Input, 0 },
835 { NP_Output, 0 },
836 { NP_Name, (IPTR)ldDemonName },
837 { NP_StackSize, AROS_STACKSIZE },
838 { TAG_END , 0 }
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);
897 return 0;
899 AROS_USERFUNC_EXIT
902 const int LIBEND TEXT_SECTION = 1;