#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;}
#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;
}