|  | #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; | 
|  | } |