Blob
1 #include <u.h>2 #include <libc.h>3 #include <thread.h>5 typedef struct Waiter Waiter;7 struct {8 QLock lk;9 Waitmsg **msg;10 int nmsg;11 int muxer;12 Waiter *head;13 } waiting;15 struct Waiter16 {17 Rendez r;18 Waitmsg *msg;19 int pid;20 Waiter *next;21 Waiter *prev;22 };24 /* see src/libmux/mux.c */25 Waitmsg*26 procwait(int pid)27 {28 Waiter *w;29 Waiter me;30 Waitmsg *msg;31 int i;33 memset(&me, 0, sizeof me);34 me.pid = pid;35 me.r.l = &waiting.lk;37 qlock(&waiting.lk);38 for(i=0; i<waiting.nmsg; i++){39 if(waiting.msg[i]->pid == pid){40 msg = waiting.msg[i];41 waiting.msg[i] = waiting.msg[--waiting.nmsg];42 qunlock(&waiting.lk);43 return msg;44 }45 }46 me.next = waiting.head;47 me.prev = nil;48 if(me.next)49 me.next->prev = &me;50 waiting.head = &me;51 while(waiting.muxer && me.msg==nil)52 rsleep(&me.r);54 if(!me.msg){55 if(waiting.muxer)56 abort();57 waiting.muxer = 1;58 while(!me.msg){59 qunlock(&waiting.lk);60 msg = recvp(threadwaitchan());61 qlock(&waiting.lk);62 if(msg == nil) /* shouldn't happen */63 break;64 for(w=waiting.head; w; w=w->next)65 if(w->pid == msg->pid)66 break;67 if(w){68 if(w->prev)69 w->prev->next = w->next;70 else71 waiting.head = w->next;72 if(w->next)73 w->next->prev = w->prev;74 me.msg = msg;75 rwakeup(&w->r);76 }else{77 waiting.msg = realloc(waiting.msg, (waiting.nmsg+1)*sizeof waiting.msg[0]);78 if(waiting.msg == nil)79 sysfatal("out of memory");80 waiting.msg[waiting.nmsg++] = msg;81 }82 }83 waiting.muxer = 0;84 if(waiting.head)85 rwakeup(&waiting.head->r);86 }87 qunlock(&waiting.lk);88 if (me.msg->pid < 0) {89 free(me.msg);90 me.msg = 0;91 }92 return me.msg;93 }