/* * Thread library. */ #include "threadimpl.h" typedef struct Mainarg Mainarg; struct Mainarg { int argc; char **argv; }; int _threadmainpid; int mainstacksize; int _callsthreaddaemonize; static int passtomainpid; extern void (*_sysfatal)(char*, va_list); static void mainlauncher(void *arg) { Mainarg *a; a = arg; _threadmaininit(); threadmain(a->argc, a->argv); threadexits("threadmain"); } static void passer(void *x, char *msg) { USED(x); Waitmsg *w; if(strcmp(msg, "sys: usr2") == 0) _exit(0); /* daemonize */ else if(strcmp(msg, "sys: child") == 0){ w = wait(); if(w == nil) _exit(1); _exit(atoi(w->msg)); }else postnote(PNPROC, passtomainpid, msg); } int main(int argc, char **argv) { int pid; Mainarg a; Proc *p; sigset_t mask; /* * Do daemonize hack here. */ if(_callsthreaddaemonize){ passtomainpid = getpid(); switch(pid = fork()){ case -1: sysfatal("fork: %r"); case 0: /* continue executing */ _threadmainpid = getppid(); break; default: /* wait for signal USR2 */ notify(passer); for(;;) pause(); _exit(0); } } /* * Instruct QLock et al. to use our scheduling functions * so that they can operate at the thread level. */ _qlockinit(_threadsleep, _threadwakeup); /* * Install our own _threadsysfatal which takes down * the whole conglomeration of procs. */ _sysfatal = _threadsysfatal; /* * XXX Install our own jump handler. */ /* * Install our own signal handlers. */ notify(_threadnote); /* * Construct the initial proc running mainlauncher(&a). */ if(mainstacksize == 0) mainstacksize = 32*1024; a.argc = argc; a.argv = argv; p = _newproc(); _newthread(p, mainlauncher, &a, mainstacksize, "threadmain", 0); _threadscheduler(p); abort(); /* not reached */ return 0; } /* * No-op function here so that sched.o drags in main.o. */ void _threadlinkmain(void) { }