try to implement the daemonize hack.

This commit is contained in:
rsc 2004-10-22 18:45:08 +00:00
parent 048610b7ea
commit 5093c3fa40
11 changed files with 165 additions and 51 deletions

View file

@ -1,6 +1,6 @@
#if defined(__linux__)
#include "ucontext.c" #include "ucontext.c"
#else
#ifdef OLD
#include "threadimpl.h" #include "threadimpl.h"
/* /*

View file

@ -18,6 +18,9 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize,
t = _threadmalloc(sizeof(Thread), 1); t = _threadmalloc(sizeof(Thread), 1);
t->proc = p; t->proc = p;
t->nextproc = p;
t->homeproc = p;
t->grp = grp; t->grp = grp;
t->id = id = newthreadid(); t->id = id = newthreadid();
if(name) if(name)
@ -42,15 +45,7 @@ _newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize,
* Add thread to proc. * Add thread to proc.
*/ */
lock(&p->lock); lock(&p->lock);
p->nthreads++; _procaddthread(p, t);
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;
/* /*
* Mark thread as ready to run. * Mark thread as ready to run.
@ -123,7 +118,7 @@ threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize)
{ {
int id; int id;
assert(_threadnprocs == 1); assert(_threadpq.head->next == nil); /* only 1 */
id = threadcreate(f, arg, stacksize); id = threadcreate(f, arg, stacksize);
_threaddebug(DBGSCHED, "idle is %d", id); _threaddebug(DBGSCHED, "idle is %d", id);
@ -181,3 +176,36 @@ newprocid(void)
return i; 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--;
}

View file

@ -4,7 +4,7 @@
#include "threadimpl.h" #include "threadimpl.h"
static void efork(int[3], int[2], char*, char**); static void efork(int[3], int[2], char*, char**);
static int int
_threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs) _threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs)
{ {
int pfd[2]; int pfd[2];
@ -88,14 +88,14 @@ Bad:
void void
threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) 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); threadexits(nil);
} }
int int
threadspawn(int fd[3], char *prog, char *args[]) 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; args[n] = 0;
va_end(arg); va_end(arg);
if(_threadexec(pidc, fd, f, args, 1) >= 0) if(_callthreadexec(pidc, fd, f, args, 1) >= 0)
threadexits(nil); threadexits(nil);
} }

View file

@ -163,7 +163,7 @@ threadfdwaitsetup(void)
if(!setup){ if(!setup){
setup = 1; setup = 1;
threadcreateidle(pollidle, nil, 16384); proccreate(pollidle, nil, 16384);
} }
} }

View file

@ -11,7 +11,11 @@ struct Mainarg
char **argv; char **argv;
}; };
int _threadmainpid;
int mainstacksize; int mainstacksize;
int _callsthreaddaemonize;
static int passtomainpid;
extern void (*_sysfatal)(char*, va_list); extern void (*_sysfatal)(char*, va_list);
static void static void
@ -25,15 +29,53 @@ mainlauncher(void *arg)
threadexits("threadmain"); 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 int
main(int argc, char **argv) main(int argc, char **argv)
{ {
int pid;
Mainarg a; Mainarg a;
Proc *p; 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 * Instruct QLock et al. to use our scheduling functions

View file

@ -1,13 +1,15 @@
<$PLAN9/src/mkhdr <$PLAN9/src/mkhdr
LIB=libthread.a LIB=libthread.a
THREAD=`sh ./thread.sh`
OFILES=\ OFILES=\
$OBJTYPE.$O\ $OBJTYPE.$O\
$THREAD.$O\
asm-$SYSNAME-$OBJTYPE.$O\ asm-$SYSNAME-$OBJTYPE.$O\
channel.$O\ channel.$O\
chanprint.$O\ chanprint.$O\
create.$O\ create.$O\
daemon.$O\
debug.$O\ debug.$O\
exec-unix.$O\ exec-unix.$O\
exit.$O\ exit.$O\
@ -28,7 +30,6 @@ OFILES=\
memset.$O\ memset.$O\
memsetd.$O\ memsetd.$O\
note.$O\ note.$O\
pthread.$O\
read9pmsg.$O\ read9pmsg.$O\
ref.$O\ ref.$O\
sched.$O\ sched.$O\
@ -69,3 +70,4 @@ VG=`test -d /home/rsc/pub/valgrind-debian && echo -DUSEVALGRIND`
CFLAGS=$CFLAGS $VG CFLAGS=$CFLAGS $VG
Linux-clone.$O: execproc.ch exit-getpid.ch proctab.ch procstack.ch

View file

@ -1,5 +1,6 @@
#include "threadimpl.h" #include "threadimpl.h"
int _threadnopasser; int _threadnopasser;
#define NFN 33 #define NFN 33

View file

@ -44,6 +44,25 @@ _threadgetproc(void)
return pthread_getspecific(key); 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. * Called to associate p with the current pthread.
*/ */
@ -87,9 +106,10 @@ _threadwaitkids(Proc *p)
/* /*
* Separate process to wait for child messages. * Separate process to wait for child messages.
* Also runs signal handlers.
*/ */
Channel *_threadexecchan; static Channel *_threadexecchan;
void static void
_threadwaitproc(void *v) _threadwaitproc(void *v)
{ {
Channel *c; Channel *c;
@ -124,6 +144,9 @@ _threadfirstexec(void)
{ {
} }
/*
* Called from mainlauncher before threadmain.
*/
void void
_threadmaininit(void) _threadmaininit(void)
{ {
@ -141,27 +164,12 @@ _threadmaininit(void)
unlock(&_threadpq.lock); unlock(&_threadpq.lock);
} }
/*
* Called after forking the exec child.
*/
void void
_threadafterexec(void) _threadafterexec(void)
{ {
nbsendul(_threadexecchan, 1); 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;
}

View file

@ -51,27 +51,42 @@ _threadscheduler(void *arg)
/* /*
* If thread needs to die, kill it. * 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){ if(t->moribund){
_threaddebug(DBGSCHED, "moribund %d.%d", p->id, t->id); _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); assert(t->moribund == 1);
t->state = Dead; t->state = Dead;
if(t->prevt) _procdelthread(p, t);
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;
unlock(&p->lock); unlock(&p->lock);
_threadfree(t); _threadfree(t);
p->nthreads--;
t = nil; t = nil;
continue; 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); 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 * If there is a request to run a function on the
* scheduling stack, do so. * scheduling stack, do so.
@ -87,7 +102,7 @@ _threadscheduler(void *arg)
* Move the thread along. * Move the thread along.
*/ */
t->state = t->nextstate; 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) if(t->state == Ready)
_threadready(t); _threadready(t);
} }

View file

@ -22,15 +22,20 @@ threadmain(int argc, char **argv)
{ {
Channel *c; Channel *c;
Waitmsg *w; Waitmsg *w;
int (*mk)(void(*)(void*), void*, uint);
mk = threadcreate;
ARGBEGIN{ ARGBEGIN{
case 'D': case 'D':
_threaddebuglevel = ~0; _threaddebuglevel = ~0;
break; break;
case 'p':
mk = proccreate;
break;
}ARGEND }ARGEND
c = threadwaitchan(); c = threadwaitchan();
proccreate(doexec, argv, 8192); mk(doexec, argv, 8192);
w = recvp(c); w = recvp(c);
if(w == nil) if(w == nil)
print("exec/recvp failed: %r\n"); print("exec/recvp failed: %r\n");

View file

@ -70,11 +70,13 @@ struct Thread
int asleep; /* thread is in _threadsleep */ int asleep; /* thread is in _threadsleep */
Label context; /* for context switches */ Label context; /* for context switches */
int grp; /* thread group */ int grp; /* thread group */
Proc *homeproc; /* ``home'' proc */
int id; /* thread id */ int id; /* thread id */
int moribund; /* thread needs to die */ int moribund; /* thread needs to die */
char *name; /* name of thread */ char *name; /* name of thread */
Thread *next; /* next on ready queue */ Thread *next; /* next on ready queue */
Thread *nextt; /* next on list of threads in this proc */ 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 */ State nextstate; /* next run state */
Proc *proc; /* proc of this thread */ Proc *proc; /* proc of this thread */
Thread *prevt; /* prev on list of threads in this proc */ Thread *prevt; /* prev on list of threads in this proc */
@ -117,6 +119,7 @@ struct Proc
Thread *thread; /* running thread */ Thread *thread; /* running thread */
Thread *idle; /* idle thread */ Thread *idle; /* idle thread */
int id; int id;
int procid;
int needexec; int needexec;
Execargs exec; /* exec argument */ Execargs exec; /* exec argument */
@ -195,7 +198,9 @@ void threadstatus(void);
void _threadstartproc(Proc*); void _threadstartproc(Proc*);
void _threadexitproc(char*); void _threadexitproc(char*);
void _threadexitallproc(char*); void _threadexitallproc(char*);
void _threadefork(int[3], int[2], char*, char**);
extern int _threadmainpid;
extern int _threadnprocs; extern int _threadnprocs;
extern int _threaddebuglevel; extern int _threaddebuglevel;
extern char* _threadexitsallstatus; extern char* _threadexitsallstatus;
@ -214,3 +219,11 @@ extern void _threadmemset(void*, int, int);
extern void _threaddebugmemset(void*, int, int); extern void _threaddebugmemset(void*, int, int);
extern int _threadprocs; extern int _threadprocs;
extern void _threadstacklimit(void*, void*); 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);