tstarting to work on Linux - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 955a2ca78d7efc2787864e38a3d902df16fc2541 | |
parent e127e40bb1327662a05f5b70dd1bbca5c69b042c | |
Author: rsc <devnull@localhost> | |
Date: Mon, 27 Dec 2004 18:21:58 +0000 | |
starting to work on Linux | |
Diffstat: | |
M src/libthread/Linux.c | 39 +++++++++++++++++++++++++++++… | |
M src/libthread/exec.c | 44 +++++++++++++++++++----------… | |
A src/libthread/test/mkfile | 8 ++++++++ | |
M src/libthread/thread.c | 2 ++ | |
M src/libthread/threadimpl.h | 6 ++++++ | |
5 files changed, 80 insertions(+), 19 deletions(-) | |
--- | |
diff --git a/src/libthread/Linux.c b/src/libthread/Linux.c | |
t@@ -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(); | |
t@@ -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 | |
t@@ -233,6 +238,7 @@ static char *threadexitsmsg; | |
void | |
sigusr2handler(int s) | |
{ | |
+ print("%d usr2 %d\n", time(0), getpid()); | |
if(threadexitsmsg) | |
_exits(threadexitsmsg); | |
} | |
t@@ -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 | |
t@@ -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->ar… | |
- if((w = wait()) != nil) | |
- break; | |
+ while((w = wait()) == nil) | |
if(errno == ECHILD) | |
- recvul(dowaitchan); | |
- } | |
+ recvul(_dowaitchan); | |
if((c = thewaitchan) != nil) | |
sendp(c, w); | |
else | |
t@@ -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 | |
t@@ -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 | |
t@@ -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 | |
t@@ -5,6 +5,8 @@ typedef struct Execjob Execjob; | |
typedef struct Proc Proc; | |
typedef struct _Procrendez _Procrendez; | |
+ | |
+ | |
typedef struct Jmp Jmp; | |
struct Jmp | |
{ | |
t@@ -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); |