aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/netfiles/wait.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-03-18 19:30:22 +0000
committerrsc <devnull@localhost>2005-03-18 19:30:22 +0000
commit7c709434eccd461a3f3c522df6224adf4e50a8da (patch)
tree07824349dbc0e919ab411b254cca583e5f6feb7d /src/cmd/netfiles/wait.c
parent72fd2f881907db5e367ffee1fcecb737c44a0090 (diff)
downloadplan9port-7c709434eccd461a3f3c522df6224adf4e50a8da.tar.gz
plan9port-7c709434eccd461a3f3c522df6224adf4e50a8da.tar.bz2
plan9port-7c709434eccd461a3f3c522df6224adf4e50a8da.zip
new files
Diffstat (limited to 'src/cmd/netfiles/wait.c')
-rw-r--r--src/cmd/netfiles/wait.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/cmd/netfiles/wait.c b/src/cmd/netfiles/wait.c
new file mode 100644
index 00000000..6f31a29b
--- /dev/null
+++ b/src/cmd/netfiles/wait.c
@@ -0,0 +1,120 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <9pclient.h>
+#include "acme.h"
+
+extern int debug;
+
+#define dprint if(debug)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);
+}
+