From 5093c3fa40717e78b0a63955640a8ac9071b5c07 Mon Sep 17 00:00:00 2001 From: rsc Date: Fri, 22 Oct 2004 18:45:08 +0000 Subject: try to implement the daemonize hack. --- src/libthread/386.c | 4 ++-- src/libthread/create.c | 48 ++++++++++++++++++++++++++++++++++++---------- src/libthread/exec-unix.c | 8 ++++---- src/libthread/fdwait.c | 2 +- src/libthread/main.c | 44 +++++++++++++++++++++++++++++++++++++++++- src/libthread/mkfile | 6 ++++-- src/libthread/note.c | 1 + src/libthread/pthread.c | 48 +++++++++++++++++++++++++++------------------- src/libthread/sched.c | 35 +++++++++++++++++++++++---------- src/libthread/texec.c | 7 ++++++- src/libthread/threadimpl.h | 13 +++++++++++++ 11 files changed, 165 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/libthread/386.c b/src/libthread/386.c index fb4c6746..313c2be5 100644 --- a/src/libthread/386.c +++ b/src/libthread/386.c @@ -1,6 +1,6 @@ +#if defined(__linux__) #include "ucontext.c" - -#ifdef OLD +#else #include "threadimpl.h" /* diff --git a/src/libthread/create.c b/src/libthread/create.c index 290c52a8..d2f4be25 100644 --- a/src/libthread/create.c +++ b/src/libthread/create.c @@ -18,6 +18,9 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, 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, uint stacksize, * 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 stacksize) { 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--; +} diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c index 73a2faf7..f69fedca 100644 --- a/src/libthread/exec-unix.c +++ b/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); } diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c index 8768e60d..a46ea456 100644 --- a/src/libthread/fdwait.c +++ b/src/libthread/fdwait.c @@ -163,7 +163,7 @@ threadfdwaitsetup(void) if(!setup){ setup = 1; - threadcreateidle(pollidle, nil, 16384); + proccreate(pollidle, nil, 16384); } } diff --git a/src/libthread/main.c b/src/libthread/main.c index 83ee177c..ec085430 100644 --- a/src/libthread/main.c +++ b/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,15 +29,53 @@ 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 diff --git a/src/libthread/mkfile b/src/libthread/mkfile index 20d08e09..e51d195f 100644 --- a/src/libthread/mkfile +++ b/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 -DUSEVALGRIND` CFLAGS=$CFLAGS $VG +Linux-clone.$O: execproc.ch exit-getpid.ch proctab.ch procstack.ch diff --git a/src/libthread/note.c b/src/libthread/note.c index 94bf236a..ed40c08f 100644 --- a/src/libthread/note.c +++ b/src/libthread/note.c @@ -1,5 +1,6 @@ #include "threadimpl.h" + int _threadnopasser; #define NFN 33 diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c index a914f433..8d661c16 100644 --- a/src/libthread/pthread.c +++ b/src/libthread/pthread.c @@ -44,6 +44,25 @@ _threadgetproc(void) return pthread_getspecific(key); } +/* + * 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. */ @@ -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; -} diff --git a/src/libthread/sched.c b/src/libthread/sched.c index 55898f08..7e430193 100644 --- a/src/libthread/sched.c +++ b/src/libthread/sched.c @@ -51,27 +51,42 @@ _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); } diff --git a/src/libthread/texec.c b/src/libthread/texec.c index bcfabee6..c9682e35 100644 --- a/src/libthread/texec.c +++ b/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"); diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index 7c9a66bb..8d7a7a75 100644 --- a/src/libthread/threadimpl.h +++ b/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); -- cgit v1.2.3