From 4940b55216d170189ddc4c3ba9fe8b2b0fb507a0 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 12 Feb 2006 16:48:50 +0000 Subject: add wait --- src/libthread/COPYRIGHT | 2 +- src/libthread/exec.c | 3 +- src/libthread/mkfile | 1 + src/libthread/wait.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/libthread/wait.c (limited to 'src') diff --git a/src/libthread/COPYRIGHT b/src/libthread/COPYRIGHT index 960a9a77..f4ee354e 100644 --- a/src/libthread/COPYRIGHT +++ b/src/libthread/COPYRIGHT @@ -45,7 +45,7 @@ Contains parts of an earlier library that has: === -The above notice does *NOT* apply to Linux-sparc64-context.S +The above notices do *NOT* apply to Linux-sparc64-context.S or to Linux-sparc64-swapcontext.c. Those are functions from the GNU C library and are provided for systems that use the GNU C library but somehow are missing those functions. They are diff --git a/src/libthread/exec.c b/src/libthread/exec.c index bfd4f718..d7452488 100644 --- a/src/libthread/exec.c +++ b/src/libthread/exec.c @@ -75,7 +75,8 @@ _threadspawn(int fd[3], char *cmd, char *argv[]) close(p[1]); return -1; case 0: - rfork(RFNOTEG); + /* can't RFNOTEG - will lose tty */ + /* rfork(RFNOTEG); */ dup2(fd[0], 0); dup2(fd[1], 1); dup2(fd[2], 2); diff --git a/src/libthread/mkfile b/src/libthread/mkfile index 0b620565..d552d079 100644 --- a/src/libthread/mkfile +++ b/src/libthread/mkfile @@ -11,6 +11,7 @@ OFILES=\ iorw.$O\ ref.$O\ thread.$O\ + wait.$O\ <$PLAN9/src/mksyslib diff --git a/src/libthread/wait.c b/src/libthread/wait.c new file mode 100644 index 00000000..24538e58 --- /dev/null +++ b/src/libthread/wait.c @@ -0,0 +1,93 @@ +#include +#include +#include + +typedef struct Waiter Waiter; + +struct { + QLock lk; + Waitmsg **msg; + int nmsg; + int muxer; + Waiter *head; +} waiting; + +struct Waiter +{ + Rendez r; + Waitmsg *msg; + int pid; + Waiter *next; + Waiter *prev; +}; + +/* see src/libmux/mux.c */ +Waitmsg* +procwait(int pid) +{ + Waiter *w; + Waiter me; + Waitmsg *msg; + int i; + + memset(&me, 0, sizeof me); + me.pid = pid; + me.r.l = &waiting.lk; + + qlock(&waiting.lk); + for(i=0; ipid == pid){ + msg = waiting.msg[i]; + waiting.msg[i] = waiting.msg[--waiting.nmsg]; + qunlock(&waiting.lk); + return msg; + } + } + me.next = waiting.head; + me.prev = nil; + if(me.next) + me.next->prev = &me; + waiting.head = &me; + while(waiting.muxer && me.msg==nil) + rsleep(&me.r); + + if(!me.msg){ + if(waiting.muxer) + abort(); + waiting.muxer = 1; + while(!me.msg){ + qunlock(&waiting.lk); + msg = recvp(threadwaitchan()); + qlock(&waiting.lk); + if(msg == nil) /* shouldn't happen */ + break; + for(w=waiting.head; w; w=w->next) + if(w->pid == msg->pid) + break; + if(w){ + if(w->prev) + w->prev->next = w->next; + else + waiting.head = w->next; + if(w->next) + w->next->prev = w->prev; + me.msg = msg; + rwakeup(&w->r); + }else{ + waiting.msg = realloc(waiting.msg, (waiting.nmsg+1)*sizeof waiting.msg[0]); + if(waiting.msg == nil) + sysfatal("out of memory"); + waiting.msg[waiting.nmsg++] = msg; + } + } + waiting.muxer = 0; + if(waiting.head) + rwakeup(&waiting.head->r); + } + qunlock(&waiting.lk); + if (me.msg->pid < 0) { + free(me.msg); + me.msg = 0; + } + return me.msg; +} -- cgit v1.2.3