add wait
This commit is contained in:
parent
3fd66761f7
commit
4940b55216
4 changed files with 97 additions and 2 deletions
|
|
@ -45,7 +45,7 @@ Contains parts of an earlier library that has:
|
|||
|
||||
===
|
||||
|
||||
The above notice does *NOT* apply to Linux-sparc64-context.S
|
||||
The above notices do *NOT* apply to Linux-sparc64-context.S
|
||||
or to Linux-sparc64-swapcontext.c. Those are functions from
|
||||
the GNU C library and are provided for systems that use the GNU C
|
||||
library but somehow are missing those functions. They are
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ _threadspawn(int fd[3], char *cmd, char *argv[])
|
|||
close(p[1]);
|
||||
return -1;
|
||||
case 0:
|
||||
rfork(RFNOTEG);
|
||||
/* can't RFNOTEG - will lose tty */
|
||||
/* rfork(RFNOTEG); */
|
||||
dup2(fd[0], 0);
|
||||
dup2(fd[1], 1);
|
||||
dup2(fd[2], 2);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ OFILES=\
|
|||
iorw.$O\
|
||||
ref.$O\
|
||||
thread.$O\
|
||||
wait.$O\
|
||||
|
||||
<$PLAN9/src/mksyslib
|
||||
|
||||
|
|
|
|||
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