commit - e127e40bb1327662a05f5b70dd1bbca5c69b042c
commit + 955a2ca78d7efc2787864e38a3d902df16fc2541
blob - 4be2c48165f5be956dec2137fcfd4ead988b90c4
blob + d6d31afae5a91f9a5780f376091a3b20de32ab60
--- src/libthread/Linux.c
+++ src/libthread/Linux.c
* unlock the vouslock so our waker can wake us,
* and then suspend.
*/
+again:
r->asleep = 1;
r->pid = getpid();
/*
* 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
void
sigusr2handler(int s)
{
+ print("%d usr2 %d\n", time(0), getpid());
if(threadexitsmsg)
_exits(threadexitsmsg);
}
}
/*
+ * 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
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
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
+<$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
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
typedef struct Proc Proc;
typedef struct _Procrendez _Procrendez;
+
+
typedef struct Jmp Jmp;
struct Jmp
{
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);