commit 955a2ca78d7efc2787864e38a3d902df16fc2541 from: rsc date: Mon Dec 27 18:21:58 2004 UTC starting to work on Linux commit - e127e40bb1327662a05f5b70dd1bbca5c69b042c commit + 955a2ca78d7efc2787864e38a3d902df16fc2541 blob - 4be2c48165f5be956dec2137fcfd4ead988b90c4 blob + d6d31afae5a91f9a5780f376091a3b20de32ab60 --- src/libthread/Linux.c +++ src/libthread/Linux.c @@ -87,6 +87,7 @@ _procsleep(_Procrendez *r) * unlock the vouslock so our waker can wake us, * and then suspend. */ +again: r->asleep = 1; r->pid = getpid(); @@ -101,9 +102,13 @@ _procsleep(_Procrendez *r) /* * We're awake. Make USR1 not interrupt system calls. */ - ignusr1(1); - assert(r->asleep == 0); lock(r->l); + ignusr1(1); + if(r->asleep && r->pid == getpid()){ +print("resleep %d\n", getpid()); + /* Didn't really wake up - signal from something else */ + goto again; + } } void @@ -233,6 +238,7 @@ static char *threadexitsmsg; void sigusr2handler(int s) { + print("%d usr2 %d\n", time(0), getpid()); if(threadexitsmsg) _exits(threadexitsmsg); } @@ -260,6 +266,35 @@ threadexitsall(char *msg) } /* + * exec - need to arrange for wait proc to run + * the execs so it gets the wait messages + */ +int +_runthreadspawn(int *fd, char *cmd, char **argv) +{ + Execjob e; + int pid; + + e.fd = fd; + e.cmd = cmd; + e.argv = argv; + e.c = chancreate(sizeof(ulong), 0); +print("%d run\n", time(0)); + qlock(&_threadexeclock); + sendp(_threadexecchan, &e); +print("%d sent\n", time(0)); + while(_threadexecproc == nil) + yield(); + kill(_threadexecproc->osprocid, SIGUSR2); +print("%d killed\n", time(0)); + pid = recvul(e.c); + qunlock(&_threadexeclock); +print("%d ran\n", time(0)); + return pid; +} + + +/* * per-process data, indexed by pid * * could use modify_ldt and a segment register blob - f31b004ad2099c50b0b2840210e0a5da05f35f7e blob + dfdb71b614bf8d47b3a322ffc7611f9fc71293ea --- src/libthread/exec.c +++ src/libthread/exec.c @@ -6,26 +6,36 @@ static Lock thewaitlock; static Channel *thewaitchan; -static Channel *dowaitchan; -static Channel *execchan; +Channel *_dowaitchan; +Channel *_threadexecchan; +Proc *_threadexecproc; +QLock _threadexeclock; static void +execthread(void *v) +{ + Execjob *e; + + USED(v); + while((e = recvp(_threadexecchan)) != nil){ +print("%d doexec pid %d\n", time(0), getpid()); + sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv)); + } +} + +static void waitproc(void *v) { Channel *c; Waitmsg *w; - Execjob *e; _threadsetsysproc(); + _threadexecproc = proc(); + threadcreate(execthread, nil, 65536); for(;;){ - for(;;){ - while((e = nbrecvp(execchan)) != nil) - sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv)); - if((w = wait()) != nil) - break; + while((w = wait()) == nil) if(errno == ECHILD) - recvul(dowaitchan); - } + recvul(_dowaitchan); if((c = thewaitchan) != nil) sendp(c, w); else @@ -94,20 +104,20 @@ _threadspawn(int fd[3], char *cmd, char *argv[]) close(fd[1]); if(fd[2] != fd[1] && fd[2] != fd[0]) close(fd[2]); - channbsendul(dowaitchan, 1); + channbsendul(_dowaitchan, 1); return pid; } int threadspawn(int fd[3], char *cmd, char *argv[]) { - if(dowaitchan == nil){ + if(_dowaitchan == nil){ lock(&thewaitlock); - if(dowaitchan == nil){ - dowaitchan = chancreate(sizeof(ulong), 1); - chansetname(dowaitchan, "dowaitchan"); - execchan = chancreate(sizeof(void*), 0); - chansetname(execchan, "execchan"); + if(_dowaitchan == nil){ + _dowaitchan = chancreate(sizeof(ulong), 1); + chansetname(_dowaitchan, "dowaitchan"); + _threadexecchan = chancreate(sizeof(void*), 1); + chansetname(_threadexecchan, "execchan"); proccreate(waitproc, nil, STACK); } unlock(&thewaitlock); blob - /dev/null blob + b3fd821c010796effab35c96da3cb54dac40d5aa (mode 644) --- /dev/null +++ src/libthread/test/mkfile @@ -0,0 +1,8 @@ +<$PLAN9/src/mkhdr + +SHORTLIB=thread 9 +OFILES= + +TARG=tprimes tspawn tspawnloop + +<$PLAN9/src/mkmany blob - 4116ac22ea4f9f0bccfd02fa313b97bb9bc26174 blob + 8f838b62adbb4ec1c63ad087394fa68d530373f9 --- src/libthread/thread.c +++ src/libthread/thread.c @@ -184,7 +184,9 @@ scheduler(Proc *p) if(p->nthread == 0) goto Out; p->runrend.l = &p->lock; +print("sleep for jobs %d\n", getpid()); _procsleep(&p->runrend); +print("wake from jobs %d\n", getpid()); } delthread(&p->runqueue, t); unlock(&p->lock); blob - 9f0a53d520a34727cbd144a540bd7934a7808a23 blob + 6bc8cbfcb86489009d0654c44cdfe315142aac05 --- src/libthread/threadimpl.h +++ src/libthread/threadimpl.h @@ -5,6 +5,8 @@ typedef struct Execjob Execjob; typedef struct Proc Proc; typedef struct _Procrendez _Procrendez; + + typedef struct Jmp Jmp; struct Jmp { @@ -88,6 +90,10 @@ struct Proc extern Proc *_threadprocs; extern Lock _threadprocslock; +extern Proc *_threadexecproc; +extern Channel *_threadexecchan; +extern QLock _threadexeclock; +extern Channel *_dowaitchan; extern void _procstart(Proc*, void (*fn)(Proc*)); extern _Thread *_threadcreate(Proc*, void(*fn)(void*), void*, uint);