plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }