plan9port

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

wait.c (1630B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <thread.h>
      4 
      5 typedef struct Waiter Waiter;
      6 
      7 struct {
      8 	QLock lk;
      9 	Waitmsg **msg;
     10 	int nmsg;
     11 	int muxer;
     12 	Waiter *head;
     13 } waiting;
     14 
     15 struct Waiter
     16 {
     17 	Rendez r;
     18 	Waitmsg *msg;
     19 	int pid;
     20 	Waiter *next;
     21 	Waiter *prev;
     22 };
     23 
     24 /* see src/libmux/mux.c */
     25 Waitmsg*
     26 procwait(int pid)
     27 {
     28 	Waiter *w;
     29 	Waiter me;
     30 	Waitmsg *msg;
     31 	int i;
     32 
     33 	memset(&me, 0, sizeof me);
     34 	me.pid = pid;
     35 	me.r.l = &waiting.lk;
     36 
     37 	qlock(&waiting.lk);
     38 	for(i=0; i<waiting.nmsg; i++){
     39 		if(waiting.msg[i]->pid == pid){
     40 			msg = waiting.msg[i];
     41 			waiting.msg[i] = waiting.msg[--waiting.nmsg];
     42 			qunlock(&waiting.lk);
     43 			return msg;
     44 		}
     45 	}
     46 	me.next = waiting.head;
     47 	me.prev = nil;
     48 	if(me.next)
     49 		me.next->prev = &me;
     50 	waiting.head = &me;
     51 	while(waiting.muxer && me.msg==nil)
     52 		rsleep(&me.r);
     53 
     54 	if(!me.msg){
     55 		if(waiting.muxer)
     56 			abort();
     57 		waiting.muxer = 1;
     58 		while(!me.msg){
     59 			qunlock(&waiting.lk);
     60 			msg = recvp(threadwaitchan());
     61 			qlock(&waiting.lk);
     62 			if(msg == nil)	/* shouldn't happen */
     63 				break;
     64 			for(w=waiting.head; w; w=w->next)
     65 				if(w->pid == msg->pid)
     66 					break;
     67 			if(w){
     68 				if(w->prev)
     69 					w->prev->next = w->next;
     70 				else
     71 					waiting.head = w->next;
     72 				if(w->next)
     73 					w->next->prev = w->prev;
     74 				me.msg = msg;
     75 				rwakeup(&w->r);
     76 			}else{
     77 				waiting.msg = realloc(waiting.msg, (waiting.nmsg+1)*sizeof waiting.msg[0]);
     78 				if(waiting.msg == nil)
     79 					sysfatal("out of memory");
     80 				waiting.msg[waiting.nmsg++] = msg;
     81 			}
     82 		}
     83 		waiting.muxer = 0;
     84 		if(waiting.head)
     85 			rwakeup(&waiting.head->r);
     86 	}
     87 	qunlock(&waiting.lk);
     88 	if (me.msg->pid < 0) {
     89 		free(me.msg);
     90 		me.msg = 0;
     91 	}
     92 	return me.msg;
     93 }