1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 5 typedef struct Waiter Waiter; 6 7 struct { 8 QLock lk; 9 Waitmsg **msg; 10 int nmsg; 11 int muxer; 12 Waiter *head; 13 } waiting; 14 15 struct Waiter 16 { 17 Rendez r; 18 Waitmsg *msg; 19 int pid; 20 Waiter *next; 21 Waiter *prev; 22 }; 23 24 /* see src/libmux/mux.c */ 25 Waitmsg* procwait(int pid)26procwait(int pid) 27 { 28 Waiter *w; 29 Waiter me; 30 Waitmsg *msg; 31 int i; 32 33 memset(&me, 0, sizeof me); 34 me.pid = pid; 35 me.r.l = &waiting.lk; 36 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); 53 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 else 71 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 } 94