rscadd waitdc9eb8a20 years agoHistory
93 lines · 1.6 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h> typedef struct Waiter Waiter; struct {	QLock lk;	Waitmsg **msg;	int nmsg;	int muxer;	Waiter *head;} waiting; struct Waiter{	Rendez r;	Waitmsg *msg;	int pid;	Waiter *next;	Waiter *prev;}; /* see src/libmux/mux.c */Waitmsg*procwait(int pid){	Waiter *w;	Waiter me;	Waitmsg *msg;	int i;		memset(&me, 0, sizeof me);	me.pid = pid;	me.r.l = &waiting.lk;		qlock(&waiting.lk);	for(i=0; i<waiting.nmsg; i++){		if(waiting.msg[i]->pid == pid){			msg = waiting.msg[i];			waiting.msg[i] = waiting.msg[--waiting.nmsg];			qunlock(&waiting.lk);			return msg;		}	}	me.next = waiting.head;	me.prev = nil;	if(me.next)		me.next->prev = &me;	waiting.head = &me;	while(waiting.muxer && me.msg==nil)		rsleep(&me.r); 	if(!me.msg){		if(waiting.muxer)			abort();		waiting.muxer = 1;		while(!me.msg){			qunlock(&waiting.lk);			msg = recvp(threadwaitchan());			qlock(&waiting.lk);			if(msg == nil)	/* shouldn't happen */				break;			for(w=waiting.head; w; w=w->next)				if(w->pid == msg->pid)					break;			if(w){				if(w->prev)					w->prev->next = w->next;				else					waiting.head = w->next;				if(w->next)					w->next->prev = w->prev;				me.msg = msg;				rwakeup(&w->r);			}else{				waiting.msg = realloc(waiting.msg, (waiting.nmsg+1)*sizeof waiting.msg[0]);				if(waiting.msg == nil)					sysfatal("out of memory");				waiting.msg[waiting.nmsg++] = msg;			}		}		waiting.muxer = 0;		if(waiting.head)			rwakeup(&waiting.head->r);	}	qunlock(&waiting.lk);	if (me.msg->pid < 0) {		free(me.msg);		me.msg = 0;	}	return me.msg;}