commit 5093c3fa40717e78b0a63955640a8ac9071b5c07 from: rsc date: Fri Oct 22 18:45:08 2004 UTC try to implement the daemonize hack. commit - 048610b7ea50507c6987d5b0cc0c4810cda87d53 commit + 5093c3fa40717e78b0a63955640a8ac9071b5c07 blob - fb4c674667cb33586e8ca767c7ec208a20223ea5 blob + 313c2be5fa5ee8932e6022879936268ce7cfbc9a --- src/libthread/386.c +++ src/libthread/386.c @@ -1,7 +1,7 @@ +#if defined(__linux__) #include "ucontext.c" +#else -#ifdef OLD - #include "threadimpl.h" /* * To use this you need some patches to Valgrind that blob - 290c52a8162df41d2bfd597d42fab968625dcdd8 blob + d2f4be259f5934c4d0624d72b9c6a1e0e56eede2 --- src/libthread/create.c +++ src/libthread/create.c @@ -18,6 +18,9 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, u t = _threadmalloc(sizeof(Thread), 1); t->proc = p; + t->nextproc = p; + t->homeproc = p; + t->grp = grp; t->id = id = newthreadid(); if(name) @@ -42,15 +45,7 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, u * Add thread to proc. */ lock(&p->lock); - p->nthreads++; - if(p->threads.head == nil) - p->threads.head = t; - else{ - t->prevt = p->threads.tail; - t->prevt->nextt = t; - } - p->threads.tail = t; - t->next = (Thread*)~0; + _procaddthread(p, t); /* * Mark thread as ready to run. @@ -123,7 +118,7 @@ threadcreateidle(void (*f)(void *arg), void *arg, uint { int id; - assert(_threadnprocs == 1); + assert(_threadpq.head->next == nil); /* only 1 */ id = threadcreate(f, arg, stacksize); _threaddebug(DBGSCHED, "idle is %d", id); @@ -181,3 +176,36 @@ newprocid(void) return i; } +/* + * Add thread to proc's list. + */ +void +_procaddthread(Proc *p, Thread *t) +{ + p->nthreads++; + if(p->threads.head == nil) + p->threads.head = t; + else{ + t->prevt = p->threads.tail; + t->prevt->nextt = t; + } + p->threads.tail = t; + t->next = (Thread*)~0; +} + +/* + * Remove thread from proc's list. + */ +void +_procdelthread(Proc *p, Thread *t) +{ + if(t->prevt) + t->prevt->nextt = t->nextt; + else + p->threads.head = t->nextt; + if(t->nextt) + t->nextt->prevt = t->prevt; + else + p->threads.tail = t->prevt; + p->nthreads--; +} blob - 73a2faf7467b66059d35e96c7ac55c28c7526a21 blob + f69fedcab30760353f432aeebcd39dd14cbc2745 --- src/libthread/exec-unix.c +++ src/libthread/exec-unix.c @@ -4,7 +4,7 @@ #include "threadimpl.h" static void efork(int[3], int[2], char*, char**); -static int +int _threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs) { int pfd[2]; @@ -88,14 +88,14 @@ Bad: void threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) { - if(_threadexec(pidc, fd, prog, args, 0) >= 0) + if(_callthreadexec(pidc, fd, prog, args, 0) >= 0) threadexits(nil); } int threadspawn(int fd[3], char *prog, char *args[]) { - return _threadexec(nil, fd, prog, args, 0); + return _callthreadexec(nil, fd, prog, args, 0); } /* @@ -128,7 +128,7 @@ threadexecl(Channel *pidc, int fd[3], char *f, ...) args[n] = 0; va_end(arg); - if(_threadexec(pidc, fd, f, args, 1) >= 0) + if(_callthreadexec(pidc, fd, f, args, 1) >= 0) threadexits(nil); } blob - 8768e60df715c4d78e23a552a8977bcebabf3f1b blob + a46ea4567248428d791a631ae2a6cf5b77e72451 --- src/libthread/fdwait.c +++ src/libthread/fdwait.c @@ -163,7 +163,7 @@ threadfdwaitsetup(void) if(!setup){ setup = 1; - threadcreateidle(pollidle, nil, 16384); + proccreate(pollidle, nil, 16384); } } blob - 83ee177c379149a93c5ccbd015a32c6f6b7c2289 blob + ec0854304fd33a201f8503daf168d6120ecba7cb --- src/libthread/main.c +++ src/libthread/main.c @@ -11,7 +11,11 @@ struct Mainarg char **argv; }; +int _threadmainpid; int mainstacksize; +int _callsthreaddaemonize; +static int passtomainpid; + extern void (*_sysfatal)(char*, va_list); static void @@ -25,16 +29,54 @@ mainlauncher(void *arg) 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; /* - * XXX Do daemonize hack here. + * 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. blob - 20d08e09279c21a97d009ec841bc8063d54fe7de blob + e51d195f32727b7d174beda4ab7ffb3f25358a07 --- src/libthread/mkfile +++ src/libthread/mkfile @@ -1,13 +1,15 @@ <$PLAN9/src/mkhdr LIB=libthread.a - +THREAD=`sh ./thread.sh` OFILES=\ $OBJTYPE.$O\ + $THREAD.$O\ asm-$SYSNAME-$OBJTYPE.$O\ channel.$O\ chanprint.$O\ create.$O\ + daemon.$O\ debug.$O\ exec-unix.$O\ exit.$O\ @@ -28,7 +30,6 @@ OFILES=\ memset.$O\ memsetd.$O\ note.$O\ - pthread.$O\ read9pmsg.$O\ ref.$O\ sched.$O\ @@ -69,3 +70,4 @@ VG=`test -d /home/rsc/pub/valgrind-debian && echo -DUS CFLAGS=$CFLAGS $VG +Linux-clone.$O: execproc.ch exit-getpid.ch proctab.ch procstack.ch blob - 94bf236a3374ebd8ff61c71fc5119be701276fc5 blob + ed40c08fb5d956428270200a53d4cb5cf8642dbf --- src/libthread/note.c +++ src/libthread/note.c @@ -1,5 +1,6 @@ #include "threadimpl.h" + int _threadnopasser; #define NFN 33 blob - a914f433d12dbb51efa02f75e7a318095137209f blob + 8d661c166e0ad6786f0615081cb181da7dec4668 --- src/libthread/pthread.c +++ src/libthread/pthread.c @@ -45,6 +45,25 @@ _threadgetproc(void) } /* + * Called to start a new proc. + */ +void +_threadstartproc(Proc *p) +{ + Proc *np; + pthread_t tid; + sigset_t all; + + np = p->newproc; + sigfillset(&all); + pthread_sigmask(SIG_SETMASK, &all, nil); + if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler, + np) < 0) + sysfatal("pthread_create: %r"); + np->pthreadid = tid; +} + +/* * Called to associate p with the current pthread. */ void @@ -87,9 +106,10 @@ _threadwaitkids(Proc *p) /* * Separate process to wait for child messages. + * Also runs signal handlers. */ -Channel *_threadexecchan; -void +static Channel *_threadexecchan; +static void _threadwaitproc(void *v) { Channel *c; @@ -124,6 +144,9 @@ _threadfirstexec(void) { } +/* + * Called from mainlauncher before threadmain. + */ void _threadmaininit(void) { @@ -141,27 +164,12 @@ _threadmaininit(void) unlock(&_threadpq.lock); } +/* + * Called after forking the exec child. + */ void _threadafterexec(void) { nbsendul(_threadexecchan, 1); } -/* - * Called to start a new proc. - */ -void -_threadstartproc(Proc *p) -{ - Proc *np; - pthread_t tid; - sigset_t all; - - np = p->newproc; - sigfillset(&all); - pthread_sigmask(SIG_SETMASK, &all, nil); - if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler, - np) < 0) - sysfatal("pthread_create: %r"); - np->pthreadid = tid; -} blob - 55898f08198ada2ac6a5de9e127525f4eb31638b blob + 7e430193545527a15372f10801f57097f69d82e7 --- src/libthread/sched.c +++ src/libthread/sched.c @@ -51,28 +51,43 @@ _threadscheduler(void *arg) /* * If thread needs to die, kill it. + * t->proc == p may not be true if we're + * trying to jump into the exec proc (see exec-unix.c). */ if(t->moribund){ _threaddebug(DBGSCHED, "moribund %d.%d", p->id, t->id); + if(t->moribund != 1) + print("moribund broke %p %d\n", &t->moribund, t->moribund); assert(t->moribund == 1); t->state = Dead; - if(t->prevt) - t->prevt->nextt = t->nextt; - else - p->threads.head = t->nextt; - if(t->nextt) - t->nextt->prevt = t->prevt; - else - p->threads.tail = t->prevt; + _procdelthread(p, t); unlock(&p->lock); _threadfree(t); - p->nthreads--; t = nil; continue; } + + /* + * If the thread has asked to move to another proc, + * let it go (only to be used in *very* special situations). + if(t->nextproc != p) + _procdelthread(p, t); + */ + unlock(&p->lock); /* + * If the thread has asked to move to another proc, + * add it to the new proc. + */ + if(t->nextproc != p){ + // lock(&t->nextproc->lock); + // _procaddthread(t->nextproc, t); + // unlock(&t->nextproc->lock); + t->proc = t->nextproc; + } + + /* * If there is a request to run a function on the * scheduling stack, do so. */ @@ -87,7 +102,7 @@ _threadscheduler(void *arg) * Move the thread along. */ t->state = t->nextstate; - _threaddebug(DBGSCHED, "moveon %d.%d", p->id, t->id); + _threaddebug(DBGSCHED, "moveon %d.%d", t->proc->id, t->id); if(t->state == Ready) _threadready(t); } blob - bcfabee6d8c5739f1d5d2546d308f7b312d8f798 blob + c9682e35d7d1035174554824dc570b5032cf36e6 --- src/libthread/texec.c +++ src/libthread/texec.c @@ -22,15 +22,20 @@ threadmain(int argc, char **argv) { Channel *c; Waitmsg *w; + int (*mk)(void(*)(void*), void*, uint); + mk = threadcreate; ARGBEGIN{ case 'D': _threaddebuglevel = ~0; break; + case 'p': + mk = proccreate; + break; }ARGEND c = threadwaitchan(); - proccreate(doexec, argv, 8192); + mk(doexec, argv, 8192); w = recvp(c); if(w == nil) print("exec/recvp failed: %r\n"); blob - 7c9a66bbfece1cb4785eb3e4759949089fa73f7c blob + 8d7a7a75d5dc30eb01af9111011dd01dad90bff7 --- src/libthread/threadimpl.h +++ src/libthread/threadimpl.h @@ -70,11 +70,13 @@ struct Thread int asleep; /* thread is in _threadsleep */ Label context; /* for context switches */ int grp; /* thread group */ + Proc *homeproc; /* ``home'' proc */ int id; /* thread id */ int moribund; /* thread needs to die */ char *name; /* name of thread */ Thread *next; /* next on ready queue */ Thread *nextt; /* next on list of threads in this proc */ + Proc *nextproc; /* next proc in which to run (rarely changes) */ State nextstate; /* next run state */ Proc *proc; /* proc of this thread */ Thread *prevt; /* prev on list of threads in this proc */ @@ -117,6 +119,7 @@ struct Proc Thread *thread; /* running thread */ Thread *idle; /* idle thread */ int id; + int procid; int needexec; Execargs exec; /* exec argument */ @@ -195,7 +198,9 @@ void threadstatus(void); void _threadstartproc(Proc*); void _threadexitproc(char*); void _threadexitallproc(char*); +void _threadefork(int[3], int[2], char*, char**); +extern int _threadmainpid; extern int _threadnprocs; extern int _threaddebuglevel; extern char* _threadexitsallstatus; @@ -214,3 +219,11 @@ extern void _threadmemset(void*, int, int); extern void _threaddebugmemset(void*, int, int); extern int _threadprocs; extern void _threadstacklimit(void*, void*); +extern void _procdelthread(Proc*, Thread*); +extern void _procaddthread(Proc*, Thread*); + +extern void _threadafterexec(void); +extern void _threadmaininit(void); +extern void _threadfirstexec(void); +extern int _threadexec(Channel*, int[3], char*, char*[], int); +extern int _callthreadexec(Channel*, int[3], char*, char*[], int);