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 Waiter
16 {
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 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 }