amiga-libnix2/sources/misc/detach.c

88 lines
2.9 KiB
C

#include <exec/memory.h>
#include <dos/dostags.h>
#include <dos/dosextens.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <stdlib.h>
#include "stabs.h"
/* Sorry, but the assembler code produced by gcc for this function is too bad.
* This one is much better!
*/
#ifdef CreateNewProcTags
#undef CreateNewProcTags
static APTR createnewproctags(APTR DOSBase,ULONG Tag,...)
{ return CreateNewProc((struct TagItem *)&Tag); }
#define CreateNewProcTags(tag...) createnewproctags(DOSBase,tag)
#endif
extern struct WBStart *_WBenchMsg;
extern char *__commandline;
extern void *__SaveSP;
extern char __dosname[];
extern char *__procname;
extern long __priority;
extern unsigned long __stack;
/* I must close a library after my child is running -
* and closing a library requires a working dispatcher (IMHO).
* Also semaphores are much smarter ;). Therefore:
*/
static struct SignalSemaphore *sem = NULL;
void __initdetach(void)
{ struct Library *DOSBase,*SysBase = *(struct Library **)4;
struct SignalSemaphore *sema;
if (_WBenchMsg)
return;
if ((sema=sem)) { /* I must be the child process */
ObtainSemaphore(sema); /* Assert that my parent is already dead */
ReleaseSemaphore(sema);
FreeMem(sema,sizeof(*sema));
return;
}
/* I must be the parent */
if ((sem=sema=(struct SignalSemaphore *)AllocMem(sizeof(*sema),MEMF_PUBLIC|MEMF_CLEAR))) {
InitSemaphore(sema);
if ((DOSBase=OpenLibrary(__dosname,37))) {
struct CommandLineInterface *cli = Cli();
APTR pr,stack = __SaveSP;
ObtainSemaphore(sema); /* Assert that my child is suspended until I'm finished */
pr = CreateNewProcTags(NP_Seglist,cli->cli_Module, /* child process gets my seglist */
NP_FreeSeglist,1, /* and must free it */
NP_Cli,1, /* it must be a CLI process */
NP_StackSize,__stack, /* it gets a stack */
NP_Name,(ULONG)__procname, /* a name */
NP_Priority,__priority, /* a priority */
NP_Arguments,(ULONG)__commandline,/* and my commandline Arguments */
TAG_END);
CloseLibrary(DOSBase);
if (pr) {
cli->cli_Module = 0; /* I'm no longer owner of this */
/* Adjust stack, release semaphore and return 0 in one.
* Maybe the 3 movel are a bit too cautious, but they ARE working
*/
asm("movel %0,sp;movel %1,a6;movel %2,a0;moveql #0,d0;jmp a6@(-570)"::
"r"(stack),"r"(SysBase),"r"(sema):"sp","a6","a0");
}
ReleaseSemaphore(sema); /* Again only caution - you never know */
}
FreeMem(sema,sizeof(*sema)); /* Couldn't start child :( */
}
exit(20);
}
ADD2INIT(__initdetach,-70); /* A very high priority */