mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-27 11:52:03 +00:00
93 lines
1.6 KiB
C
93 lines
1.6 KiB
C
#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;
|
|
}
|