| #include <u.h> |
| #include <libc.h> |
| #include <thread.h> |
| #include <9pclient.h> |
| #include "acme.h" |
| |
| extern int debug; |
| |
| #define dprint if(debug>1)print |
| |
| typedef struct Waitreq Waitreq; |
| struct Waitreq |
| { |
| int pid; |
| Channel *c; |
| }; |
| |
| /* |
| * watch the exiting children |
| */ |
| Channel *twaitchan; /* chan(Waitreq) */ |
| void |
| waitthread(void *v) |
| { |
| Alt a[3]; |
| Waitmsg *w, **wq; |
| Waitreq *rq, r; |
| int i, nrq, nwq; |
| |
| threadsetname("waitthread"); |
| a[0].c = threadwaitchan(); |
| a[0].v = &w; |
| a[0].op = CHANRCV; |
| a[1].c = twaitchan; |
| a[1].v = &r; |
| a[1].op = CHANRCV; |
| a[2].op = CHANEND; |
| |
| nrq = 0; |
| nwq = 0; |
| rq = nil; |
| wq = nil; |
| dprint("wait: start\n"); |
| for(;;){ |
| cont2:; |
| dprint("wait: alt\n"); |
| switch(alt(a)){ |
| case 0: |
| dprint("wait: pid %d exited\n", w->pid); |
| for(i=0; i<nrq; i++){ |
| if(rq[i].pid == w->pid){ |
| dprint("wait: match with rq chan %p\n", rq[i].c); |
| sendp(rq[i].c, w); |
| rq[i] = rq[--nrq]; |
| goto cont2; |
| } |
| } |
| if(i == nrq){ |
| dprint("wait: queueing waitmsg\n"); |
| wq = erealloc(wq, (nwq+1)*sizeof(wq[0])); |
| wq[nwq++] = w; |
| } |
| break; |
| |
| case 1: |
| dprint("wait: req for pid %d chan %p\n", r.pid, r.c); |
| for(i=0; i<nwq; i++){ |
| if(w->pid == r.pid){ |
| dprint("wait: match with waitmsg\n"); |
| sendp(r.c, w); |
| wq[i] = wq[--nwq]; |
| goto cont2; |
| } |
| } |
| if(i == nwq){ |
| dprint("wait: queueing req\n"); |
| rq = erealloc(rq, (nrq+1)*sizeof(rq[0])); |
| rq[nrq] = r; |
| dprint("wait: queueing req pid %d chan %p\n", rq[nrq].pid, rq[nrq].c); |
| nrq++; |
| } |
| break; |
| } |
| } |
| } |
| |
| Waitmsg* |
| twaitfor(int pid) |
| { |
| Waitreq r; |
| Waitmsg *w; |
| |
| r.pid = pid; |
| r.c = chancreate(sizeof(Waitmsg*), 1); |
| send(twaitchan, &r); |
| w = recvp(r.c); |
| chanfree(r.c); |
| return w; |
| } |
| |
| int |
| twait(int pid) |
| { |
| int x; |
| Waitmsg *w; |
| |
| w = twaitfor(pid); |
| x = w->msg[0] != 0 ? -1 : 0; |
| free(w); |
| return x; |
| } |
| |
| void |
| twaitinit(void) |
| { |
| threadwaitchan(); /* allocate it before returning */ |
| twaitchan = chancreate(sizeof(Waitreq), 10); |
| threadcreate(waitthread, nil, 128*1024); |
| } |
| |