add wait
This commit is contained in:
parent
3fd66761f7
commit
4940b55216
4 changed files with 97 additions and 2 deletions
93
src/libthread/wait.c
Normal file
93
src/libthread/wait.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue