wait.c (1988B)
1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 #include <9pclient.h> 5 #include "acme.h" 6 7 extern int debug; 8 9 #define dprint if(debug>1)print 10 11 typedef struct Waitreq Waitreq; 12 struct Waitreq 13 { 14 int pid; 15 Channel *c; 16 }; 17 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; 29 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; 38 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; 64 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 } 86 87 Waitmsg* 88 twaitfor(int pid) 89 { 90 Waitreq r; 91 Waitmsg *w; 92 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 } 100 101 int 102 twait(int pid) 103 { 104 int x; 105 Waitmsg *w; 106 107 w = twaitfor(pid); 108 x = w->msg[0] != 0 ? -1 : 0; 109 free(w); 110 return x; 111 } 112 113 void 114 twaitinit(void) 115 { 116 threadwaitchan(); /* allocate it before returning */ 117 twaitchan = chancreate(sizeof(Waitreq), 10); 118 threadcreate(waitthread, nil, 128*1024); 119 }