URI:
       twait.c - 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
       ---
       twait.c (1630B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <thread.h>
            4 
            5 typedef struct Waiter Waiter;
            6 
            7 struct {
            8         QLock lk;
            9         Waitmsg **msg;
           10         int nmsg;
           11         int muxer;
           12         Waiter *head;
           13 } waiting;
           14 
           15 struct Waiter
           16 {
           17         Rendez r;
           18         Waitmsg *msg;
           19         int pid;
           20         Waiter *next;
           21         Waiter *prev;
           22 };
           23 
           24 /* see src/libmux/mux.c */
           25 Waitmsg*
           26 procwait(int pid)
           27 {
           28         Waiter *w;
           29         Waiter me;
           30         Waitmsg *msg;
           31         int i;
           32 
           33         memset(&me, 0, sizeof me);
           34         me.pid = pid;
           35         me.r.l = &waiting.lk;
           36 
           37         qlock(&waiting.lk);
           38         for(i=0; i<waiting.nmsg; i++){
           39                 if(waiting.msg[i]->pid == pid){
           40                         msg = waiting.msg[i];
           41                         waiting.msg[i] = waiting.msg[--waiting.nmsg];
           42                         qunlock(&waiting.lk);
           43                         return msg;
           44                 }
           45         }
           46         me.next = waiting.head;
           47         me.prev = nil;
           48         if(me.next)
           49                 me.next->prev = &me;
           50         waiting.head = &me;
           51         while(waiting.muxer && me.msg==nil)
           52                 rsleep(&me.r);
           53 
           54         if(!me.msg){
           55                 if(waiting.muxer)
           56                         abort();
           57                 waiting.muxer = 1;
           58                 while(!me.msg){
           59                         qunlock(&waiting.lk);
           60                         msg = recvp(threadwaitchan());
           61                         qlock(&waiting.lk);
           62                         if(msg == nil)        /* shouldn't happen */
           63                                 break;
           64                         for(w=waiting.head; w; w=w->next)
           65                                 if(w->pid == msg->pid)
           66                                         break;
           67                         if(w){
           68                                 if(w->prev)
           69                                         w->prev->next = w->next;
           70                                 else
           71                                         waiting.head = w->next;
           72                                 if(w->next)
           73                                         w->next->prev = w->prev;
           74                                 me.msg = msg;
           75                                 rwakeup(&w->r);
           76                         }else{
           77                                 waiting.msg = realloc(waiting.msg, (waiting.nmsg+1)*sizeof waiting.msg[0]);
           78                                 if(waiting.msg == nil)
           79                                         sysfatal("out of memory");
           80                                 waiting.msg[waiting.nmsg++] = msg;
           81                         }
           82                 }
           83                 waiting.muxer = 0;
           84                 if(waiting.head)
           85                         rwakeup(&waiting.head->r);
           86         }
           87         qunlock(&waiting.lk);
           88         if (me.msg->pid < 0) {
           89                 free(me.msg);
           90                 me.msg = 0;
           91         }
           92         return me.msg;
           93 }