aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libthread/Linux.c39
-rw-r--r--src/libthread/exec.c44
-rw-r--r--src/libthread/test/mkfile8
-rw-r--r--src/libthread/thread.c2
-rw-r--r--src/libthread/threadimpl.h6
5 files changed, 80 insertions, 19 deletions
diff --git a/src/libthread/Linux.c b/src/libthread/Linux.c
index 4be2c481..d6d31afa 100644
--- a/src/libthread/Linux.c
+++ b/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
diff --git a/src/libthread/exec.c b/src/libthread/exec.c
index f31b004a..dfdb71b6 100644
--- a/src/libthread/exec.c
+++ b/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);
diff --git a/src/libthread/test/mkfile b/src/libthread/test/mkfile
new file mode 100644
index 00000000..b3fd821c
--- /dev/null
+++ b/src/libthread/test/mkfile
@@ -0,0 +1,8 @@
+<$PLAN9/src/mkhdr
+
+SHORTLIB=thread 9
+OFILES=
+
+TARG=tprimes tspawn tspawnloop
+
+<$PLAN9/src/mkmany
diff --git a/src/libthread/thread.c b/src/libthread/thread.c
index 4116ac22..8f838b62 100644
--- a/src/libthread/thread.c
+++ b/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);
diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
index 9f0a53d5..6bc8cbfc 100644
--- a/src/libthread/threadimpl.h
+++ b/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);