Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include <9pclient.h>
5 #include "acme.h"
7 extern int debug;
9 #define dprint if(debug>1)print
11 typedef struct Waitreq Waitreq;
12 struct Waitreq
13 {
14 int pid;
15 Channel *c;
16 };
18 /*
19 * watch the exiting children
20 */
21 Channel *twaitchan; /* chan(Waitreq) */
22 void
23 waitthread(void *v)
24 {
25 Alt a[3];
26 Waitmsg *w, **wq;
27 Waitreq *rq, r;
28 int i, nrq, nwq;
30 threadsetname("waitthread");
31 a[0].c = threadwaitchan();
32 a[0].v = &w;
33 a[0].op = CHANRCV;
34 a[1].c = twaitchan;
35 a[1].v = &r;
36 a[1].op = CHANRCV;
37 a[2].op = CHANEND;
39 nrq = 0;
40 nwq = 0;
41 rq = nil;
42 wq = nil;
43 dprint("wait: start\n");
44 for(;;){
45 cont2:;
46 dprint("wait: alt\n");
47 switch(alt(a)){
48 case 0:
49 dprint("wait: pid %d exited\n", w->pid);
50 for(i=0; i<nrq; i++){
51 if(rq[i].pid == w->pid){
52 dprint("wait: match with rq chan %p\n", rq[i].c);
53 sendp(rq[i].c, w);
54 rq[i] = rq[--nrq];
55 goto cont2;
56 }
57 }
58 if(i == nrq){
59 dprint("wait: queueing waitmsg\n");
60 wq = erealloc(wq, (nwq+1)*sizeof(wq[0]));
61 wq[nwq++] = w;
62 }
63 break;
65 case 1:
66 dprint("wait: req for pid %d chan %p\n", r.pid, r.c);
67 for(i=0; i<nwq; i++){
68 if(w->pid == r.pid){
69 dprint("wait: match with waitmsg\n");
70 sendp(r.c, w);
71 wq[i] = wq[--nwq];
72 goto cont2;
73 }
74 }
75 if(i == nwq){
76 dprint("wait: queueing req\n");
77 rq = erealloc(rq, (nrq+1)*sizeof(rq[0]));
78 rq[nrq] = r;
79 dprint("wait: queueing req pid %d chan %p\n", rq[nrq].pid, rq[nrq].c);
80 nrq++;
81 }
82 break;
83 }
84 }
85 }
87 Waitmsg*
88 twaitfor(int pid)
89 {
90 Waitreq r;
91 Waitmsg *w;
93 r.pid = pid;
94 r.c = chancreate(sizeof(Waitmsg*), 1);
95 send(twaitchan, &r);
96 w = recvp(r.c);
97 chanfree(r.c);
98 return w;
99 }
101 int
102 twait(int pid)
104 int x;
105 Waitmsg *w;
107 w = twaitfor(pid);
108 x = w->msg[0] != 0 ? -1 : 0;
109 free(w);
110 return x;
113 void
114 twaitinit(void)
116 threadwaitchan(); /* allocate it before returning */
117 twaitchan = chancreate(sizeof(Waitreq), 10);
118 threadcreate(waitthread, nil, 128*1024);