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)print11 typedef struct Waitreq Waitreq;12 struct Waitreq13 {14 int pid;15 Channel *c;16 };18 /*19 * watch the exiting children20 */21 Channel *twaitchan; /* chan(Waitreq) */22 void23 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 int102 twait(int pid)103 {104 int x;105 Waitmsg *w;107 w = twaitfor(pid);108 x = w->msg[0] != 0 ? -1 : 0;109 free(w);110 return x;111 }113 void114 twaitinit(void)115 {116 threadwaitchan(); /* allocate it before returning */117 twaitchan = chancreate(sizeof(Waitreq), 10);118 threadcreate(waitthread, nil, 128*1024);119 }