URI: 
       tadd wait - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 4940b55216d170189ddc4c3ba9fe8b2b0fb507a0
   DIR parent 3fd66761f7d3b1b93e9d2f819b7edbdb13152c75
  HTML Author: rsc <devnull@localhost>
       Date:   Sun, 12 Feb 2006 16:48:50 +0000
       
       add wait
       
       Diffstat:
         M src/libthread/COPYRIGHT             |       2 +-
         M src/libthread/exec.c                |       3 ++-
         M src/libthread/mkfile                |       1 +
         A src/libthread/wait.c                |      93 +++++++++++++++++++++++++++++++
       
       4 files changed, 97 insertions(+), 2 deletions(-)
       ---
   DIR diff --git a/src/libthread/COPYRIGHT b/src/libthread/COPYRIGHT
       t@@ -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 
   DIR diff --git a/src/libthread/exec.c b/src/libthread/exec.c
       t@@ -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);
   DIR diff --git a/src/libthread/mkfile b/src/libthread/mkfile
       t@@ -11,6 +11,7 @@ OFILES=\
                iorw.$O\
                ref.$O\
                thread.$O\
       +        wait.$O\
        
        <$PLAN9/src/mksyslib
        
   DIR diff --git a/src/libthread/wait.c b/src/libthread/wait.c
       t@@ -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;
       +}