New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / rom / dos / lddemon.c
blob21ec391689cf1a18c1a5a9270e290ff408ac4d27
1 /*
2 Copyright © 1995-2004, 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.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
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 struct DevProc *dp = NULL;
116 BPTR seglist = 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
122 though.
124 D(bug(
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);
137 if( seglist )
138 return seglist;
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);
146 if( seglist )
147 return seglist;
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);
162 FreeDeviceProc(dp);
163 return seglist;
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;
174 BPTR seg = seglist;
176 while(seg)
178 STRPTR addr= (STRPTR)((LONG)BADDR(seg)-sizeof(ULONG));
179 ULONG size = *(ULONG *)addr;
181 for(
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 )
192 struct Library *lib;
194 D(bug("[LDInit] Calling InitResident(%p) on %s\n", res, res->rt_Name));
195 Forbid();
196 lib = InitResident(res, seglist);
197 Permit();
198 D(bug("[LDInit] Done calling InitResident(%p) on %s\n", res, res->rt_Name));
199 if( lib == NULL )
200 UnLoadSeg(seglist);
201 return lib;
204 seg = *(BPTR *)BADDR(seg);
206 D(bug("[LDInit] Couldn't find Resident for %p\n", seglist));
207 UnLoadSeg(seglist);
208 return NULL;
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)
228 struct LDObjectNode
230 struct Node ldon_Node;
231 struct SignalSemaphore ldon_SigSem;
232 ULONG ldon_AccessCount;
233 #if CHECK_DEPENDENCY
234 struct Task *ldon_FirstLocker;
235 #endif
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);
243 if (ret)
245 ULONG len = strlen(name);
246 STRPTR dupname = AllocVec(len+1, MEMF_ANY);
247 if (dupname)
249 CopyMem(name, dupname, len);
250 dupname[len] = '\0';
251 ret->ldon_Node.ln_Name = dupname;
252 InitSemaphore(&ret->ldon_SigSem);
253 ret->ldon_AccessCount = 0;
255 #if CHECK_DEPENDENCY
256 ret->ldon_FirstLocker = FindTask(0);
257 #endif
259 return ret;
261 FreeVec(ret);
264 return NULL;
267 VOID LDDestroyObjectNode(struct LDObjectNode *object, struct DosLibrary *DOSBase)
269 struct ExecBase *SysBase = DOSBase->dl_SysBase;
271 FreeVec(object->ldon_Node.ln_Name);
272 FreeVec(object);
275 AROS_LH2(struct Library *, OpenLibrary,
276 AROS_LHA(STRPTR, libname, A1),
277 AROS_LHA(ULONG, version, D0),
278 struct ExecBase *, SysBase, 0, Dos)
280 AROS_LIBFUNC_INIT
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
309 situation like this:
311 Process A opens L --------> LDDemon loads L and locks sem S
314 1 / \ 3
316 / 2 \
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
323 Proces B will never
324 respond to L.
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);
337 if (!object)
339 object = LDNewObjectNode(stripped_libname, DOSBase);
340 if (object)
342 AddTail(&DOSBase->dl_LDObjectsList, (struct Node *)object);
346 if (object)
348 object->ldon_AccessCount += 1;
350 #if CHECK_DEPENDENCY
351 else
353 struct Task *curtask = FindTask(0);
354 struct ETask *et = GetETask(curtask);
356 D(bug("Checking for circular dependency\n"));
357 if (et)
359 while (curtask && curtask != object->ldon_FirstLocker)
360 curtask = et->et_Parent;
362 if (curtask)
364 bug("Circular dependency found!\n");
365 object = NULL;
369 #endif
370 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
372 if (!object)
373 return NULL;
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 */
384 struct LDDMsg ldd;
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... :)
421 Forbid();
422 tmplib = (struct Library *)FindName(&SysBase->LibList, stripped_libname);
423 Permit();
425 if( tmplib != NULL )
426 library = tmplib;
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"));
440 else
441 library = NULL;
445 if (library == NULL)
448 the library is not on disk so
449 check Resident List
452 struct Resident *resident;
454 resident = FindResident(stripped_libname);
455 if (resident)
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);
478 else
479 ReleaseSemaphore(&object->ldon_SigSem);
480 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
482 return library;
484 AROS_LIBFUNC_EXIT
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)
494 AROS_LIBFUNC_INIT
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);
514 if (!object)
516 object = LDNewObjectNode(stripped_devname, DOSBase);
517 if (object)
519 AddTail(&DOSBase->dl_LDObjectsList, (struct Node*)object);
523 if (object)
525 object->ldon_AccessCount += 1;
527 #if CHECK_DEPENDENCY
528 else
530 struct Task *curtask = FindTask(0);
531 struct ETask *et = GetETask(curtask);
533 if (et)
535 while (curtask && curtask != object->ldon_FirstLocker)
536 curtask = et->et_Parent;
538 if (curtask)
540 bug("[LDCaller] Circular dependency found!\n");
541 object = NULL;
545 #endif
546 ReleaseSemaphore(&DOSBase->dl_LDObjectsListSigSem);
548 if (!object)
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 */
558 struct LDDMsg ldd;
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)
583 Forbid();
584 tmpdev = (struct Device *)FindName(&SysBase->DeviceList, stripped_devname);
585 Permit();
587 if(tmpdev != NULL)
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));
596 AROS_LVO_CALL3(void,
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);
616 else
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;
624 AROS_LIBFUNC_EXIT
627 AROS_LH1(void, CloseLibrary,
628 AROS_LHA(struct Library *, library, A1),
629 struct ExecBase *, SysBase, 0, Dos)
631 AROS_LIBFUNC_INIT
633 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
634 BPTR seglist;
636 if( library != NULL )
638 Forbid();
639 seglist = AROS_LVO_CALL0(BPTR, struct Library *, library, 2, );
640 if( seglist )
642 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
644 /* Safe to call from a Task */
645 UnLoadSeg(seglist);
647 Permit();
650 AROS_LIBFUNC_EXIT
653 AROS_LH1(void, CloseDevice,
654 AROS_LHA(struct IORequest *, iORequest, A1),
655 struct ExecBase *, SysBase, 0, Dos)
657 AROS_LIBFUNC_INIT
658 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
659 BPTR seglist = NULL;
661 Forbid();
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;
668 if( seglist )
670 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
671 UnLoadSeg(seglist);
674 Permit();
675 AROS_LIBFUNC_EXIT
678 AROS_LH1(void, RemLibrary,
679 AROS_LHA(struct Library *, library, A1),
680 struct ExecBase *, SysBase, 0, Dos)
682 AROS_LIBFUNC_INIT
684 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
685 BPTR seglist;
687 Forbid();
688 seglist = AROS_LVO_CALL1(BPTR,
689 AROS_LCA(struct Library *, library, D0),
690 struct Library *, library, 3, );
691 if( seglist )
693 DOSBase->dl_LDReturn = MEM_TRY_AGAIN;
694 UnLoadSeg(seglist);
696 Permit();
698 AROS_LIBFUNC_EXIT
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)
707 AROS_USERFUNC_INIT
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. */
716 Forbid();
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 )
725 RemLibrary(library);
726 /* Did it really go away? */
727 if( DOSBase->dl_LDReturn != MEM_DID_NOTHING )
729 /* Yes! Return it. */
730 Permit();
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. */
750 Permit();
751 return MEM_TRY_AGAIN;
754 /* Go on to next library. */
755 library = (struct Library *)library->lib_Node.ln_Succ;
757 Permit();
758 return MEM_DID_NOTHING;
760 AROS_USERFUNC_EXIT
764 void LDDemon()
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)
775 AROS_USERFUNC_INIT
777 struct DosLibrary *DOSBase = SysBase->ex_RamLibPrivate;
778 struct LDDMsg *ldd;
780 for(;;)
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,
790 ldd->ldd_Name,
791 ldd->ldd_BaseDir,
792 DOSBase);
794 if (ldd->ldd_Return == 0)
795 bug("[LDDemon] Could not open %s\n",ldd->ldd_Name);
796 else
797 D(bug("[LDDemon] Replying with %p as result\n", ldd->ldd_Return));
798 ReplyMsg((struct Message *)ldd);
799 } /* messages available */
802 AROS_USERFUNC_EXIT
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)
811 AROS_USERFUNC_INIT
812 AROS_GET_SYSBASE
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 },
824 { NP_Input, 0 },
825 { NP_Output, 0 },
826 { NP_Name, (IPTR)ldDemonName },
827 { NP_StackSize, AROS_STACKSIZE },
828 { TAG_END , 0 }
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);
887 return 0;
889 AROS_USERFUNC_EXIT
892 const int LIBEND TEXT_SECTION = 1;