aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/wait.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2006-02-12 16:48:50 +0000
committerrsc <devnull@localhost>2006-02-12 16:48:50 +0000
commit4940b55216d170189ddc4c3ba9fe8b2b0fb507a0 (patch)
treeff0e92d3cd4d12cb4eeccdcad07b5992880f39e8 /src/libthread/wait.c
parent3fd66761f7d3b1b93e9d2f819b7edbdb13152c75 (diff)
downloadplan9port-4940b55216d170189ddc4c3ba9fe8b2b0fb507a0.tar.gz
plan9port-4940b55216d170189ddc4c3ba9fe8b2b0fb507a0.tar.bz2
plan9port-4940b55216d170189ddc4c3ba9fe8b2b0fb507a0.zip
add wait
Diffstat (limited to 'src/libthread/wait.c')
-rw-r--r--src/libthread/wait.c93
1 files changed, 93 insertions, 0 deletions
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 <u.h>
+#include <libc.h>
+#include <thread.h>
+
+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; i<waiting.nmsg; i++){
+ if(waiting.msg[i]->pid == 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;
+}