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/wait.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/libthread/wait.c (limited to 'src/libthread/wait.c') 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