URI: 
       tvarious bug fixes and paranoia - 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 6c7460701e7896446d0fb14bf9b24f258c61b6a6
   DIR parent a09e80f9c414ffc815641d49836be3a2a6a07800
  HTML Author: rsc <devnull@localhost>
       Date:   Sun, 23 May 2004 00:59:33 +0000
       
       various bug fixes and paranoia
       
       Diffstat:
         M src/lib9/notify.c                   |       1 +
         M src/lib9/qlock.c                    |      10 ++++++++++
         M src/lib9/rendez-signal.c            |     146 ++++++++++++++++---------------
       
       3 files changed, 87 insertions(+), 70 deletions(-)
       ---
   DIR diff --git a/src/lib9/notify.c b/src/lib9/notify.c
       t@@ -35,6 +35,7 @@ static struct {
                SIGVTALRM, 0,
                SIGUSR1, 0,
                SIGUSR2, 0,
       +        SIGWINCH, 1,
        #ifdef SIGINFO
                SIGINFO, 0,
        #endif
   DIR diff --git a/src/lib9/qlock.c b/src/lib9/qlock.c
       t@@ -13,6 +13,7 @@ enum
                QueuingR,
                QueuingW,
                Sleeping,
       +        Waking,
        };
        
        static ulong        (*_rendezvousp)(ulong, ulong) = rendezvous;
       t@@ -74,6 +75,7 @@ qlock(QLock *q)
                /* wait */
                while((*_rendezvousp)((ulong)mp, 1) == ~0)
                        ;
       +        assert(mp->state == Waking);
                mp->inuse = 0;
        }
        
       t@@ -90,6 +92,7 @@ qunlock(QLock *q)
                        if(q->head == nil)
                                q->tail = nil;
                        unlock(&q->lock);
       +                p->state = Waking;
                        while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
                                ;
                        return;
       t@@ -139,6 +142,7 @@ rlock(RWLock *q)
                /* wait in kernel */
                while((*_rendezvousp)((ulong)mp, 1) == ~0)
                        ;
       +        assert(mp->state == Waking);
                mp->inuse = 0;
        }
        
       t@@ -180,6 +184,7 @@ runlock(RWLock *q)
                unlock(&q->lock);
        
                /* wakeup waiter */
       +        p->state = Waking;
                while((*_rendezvousp)((ulong)p, 0) == ~0)
                        ;
        }
       t@@ -212,6 +217,7 @@ wlock(RWLock *q)
                /* wait in kernel */
                while((*_rendezvousp)((ulong)mp, 1) == ~0)
                        ;
       +        assert(mp->state == Waking);
                mp->inuse = 0;
        }
        
       t@@ -251,6 +257,7 @@ wunlock(RWLock *q)
                        if(q->head == nil)
                                q->tail = nil;
                        unlock(&q->lock);
       +                p->state = Waking;
                        while((*_rendezvousp)((ulong)p, 0) == ~0)
                                ;
                        return;
       t@@ -266,6 +273,7 @@ wunlock(RWLock *q)
                        p = q->head;
                        q->head = p->next;
                        q->readers++;
       +                p->state = Waking;
                        while((*_rendezvousp)((ulong)p, 0) == ~0)
                                ;
                }
       t@@ -308,6 +316,7 @@ rsleep(Rendez *r)
                        if(r->l->head == nil)
                                r->l->tail = nil;
                        unlock(&r->l->lock);
       +                t->state = Waking;
                        while((*_rendezvousp)((ulong)t, 0x12345) == ~0)
                                ;
                }else{
       t@@ -318,6 +327,7 @@ rsleep(Rendez *r)
                /* wait for a wakeup */
                while((*_rendezvousp)((ulong)me, 0x23456) == ~0)
                        ;
       +        assert(me->state == Waking);
                me->inuse = 0;
                if(!r->l->locked){
                        fprint(2, "rsleep: not locked after wakeup\n");
   DIR diff --git a/src/lib9/rendez-signal.c b/src/lib9/rendez-signal.c
       t@@ -28,11 +28,14 @@
                  If a rendezvous is interrupted the return value is ~0, so
                  that value should not be used in normal communication.
        
       - * This simulates rendezvous with shared memory, pause, and SIGUSR1.
       + * This simulates rendezvous with shared memory, sigsuspend, and SIGUSR1.
         */
        
       +#include <u.h>
        #include <signal.h>
       -#include <lib9.h>
       +#include <libc.h>
       +
       +#define DBG 0
        
        enum
        {
       t@@ -43,11 +46,11 @@ typedef struct Vous Vous;
        struct Vous
        {
                Vous *link;
       -        Lock lk;
                int pid;
       -        int wakeup;
       -        ulong val;
       +        int wokeup;
                ulong tag;
       +        ulong val1;                /* value for the sleeper */
       +        ulong val2;                /* value for the waker */
        };
        
        static void
       t@@ -57,9 +60,17 @@ ign(int x)
        }
        
        void /*__attribute__((constructor))*/
       -ignusr1(void)
       +ignusr1(int restart)
        {
       -        signal(SIGUSR1, ign);
       +        struct sigaction sa;
       +
       +        memset(&sa, 0, sizeof sa);
       +        sa.sa_handler = ign;
       +        sigemptyset(&sa.sa_mask);
       +        sigaddset(&sa.sa_mask, SIGUSR1);
       +        if(restart)
       +                sa.sa_flags = SA_RESTART;
       +        sigaction(SIGUSR1, &sa, nil);
        }
        
        static Vous vouspool[2048];
       t@@ -78,117 +89,112 @@ getvous(void)
                        vousfree = v->link;
                }else if(nvousused < nelem(vouspool))
                        v = &vouspool[nvousused++];
       -        else
       +        else{
       +                fprint(2, "rendezvous: out of vous!\n");
                        abort();
       +        }
                return v;
        }
        
        static void
        putvous(Vous *v)
        {
       -        lock(&vouslock);
                v->link = vousfree;
                vousfree = v;
       -        unlock(&vouslock);
        }
        
        static Vous*
       -findvous(ulong tag, ulong val, int pid)
       +findvous(ulong tag)
        {
                int h;
                Vous *v, **l;
        
       -        lock(&vouslock);
                h = tag%VOUSHASH;
                for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
                        if(v->tag == tag){
                                *l = v->link;
       -                        unlock(&vouslock);
       +                        v->link = nil;
                                return v;
                        }
                }
       +        return nil;
       +}
       +
       +static Vous*
       +mkvous(ulong tag)
       +{
       +        Vous *v;
       +        int h;
       +
       +        h = tag%VOUSHASH;
                v = getvous();
       -        v->pid = pid;
                v->link = voushash[h];
       -        v->val = val;
                v->tag = tag;
       -        lock(&v->lk);
                voushash[h] = v;
       -        unlock(&vouslock);
                return v;
        }
        
       -#define DBG 0
        ulong
        rendezvous(ulong tag, ulong val)
        {
       -        int me, vpid;
       +        int vpid, pid;
                ulong rval;
                Vous *v;
                sigset_t mask;
        
       -        me = getpid();
       -        v = findvous(tag, val, me);
       -        if(v->pid == me){
       -                if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
       +        pid = getpid();
       +        lock(&vouslock);
       +        if((v = findvous(tag)) == nil){
                        /*
       -                 * No rendezvous partner was found; the next guy
       -                 * through will find v and wake us, so we must go
       -                 * to sleep.
       +                 * Go to sleep.
                         *
       -                 * To go to sleep:
       -                 *        1. disable USR1 signals.
       -                 *        2. unlock v->lk (tells waker okay to signal us).
       -                 *        3. atomically suspend and enable USR1 signals.
       -                 *
       -                 * The call to ignusr1() could be done once at 
       -                 * process creation instead of every time through rendezvous.
       +                 * Block USR1, set the handler to interrupt system calls,
       +                 * unlock the vouslock so our waker can wake us,
       +                 * and then suspend.
                         */
       -                v->val = val;
       -                ignusr1();
       -                sigprocmask(SIG_SETMASK, NULL, &mask);
       +                v = mkvous(tag);
       +                v->pid = pid;
       +                v->val2 = val;
       +                v->wokeup = 0;
       +                sigprocmask(SIG_SETMASK, nil, &mask);
                        sigaddset(&mask, SIGUSR1);
       -                sigprocmask(SIG_SETMASK, &mask, NULL);
       +                sigprocmask(SIG_SETMASK, &mask, nil);
       +                ignusr1(0);
       +                if(DBG) fprint(2, "%d rv(%lux, %lux) -> s\n", pid, tag, val);
       +                unlock(&vouslock);
                        sigdelset(&mask, SIGUSR1);
       -                v->wakeup = 0;
       -                unlock(&v->lk);
       -                for(;;){
       -                        /*
       -                         * There may well be random signals flying around,
       -                         * so we can't be sure why we woke up.  If we weren't
       -                         * properly awakened, we need to go back to sleep.
       -                         */
       -                        sigsuspend(&mask);
       -                        lock(&v->lk);        /* do some memory synchronization */
       -                        unlock(&v->lk);
       -                        if(v->wakeup == 1)
       -                                break;
       +                sigsuspend(&mask);
       +
       +                /*
       +                 * We're awake.  Make USR1 not interrupt system calls.
       +                 * Were we awakened or interrupted?
       +                 */
       +                ignusr1(1);
       +                lock(&vouslock);
       +                if(v->wokeup){
       +                        rval = v->val1;
       +                        if(DBG) fprint(2, "%d rv(%lux, %lux) -> g %lux\n", pid, tag, val, rval);
       +                }else{
       +                        if(findvous(tag) != v){
       +                                fprint(2, "rendezvous: interrupted but not found in hash table\n");
       +                                abort();
       +                        }
       +                        rval = ~(ulong)0;
       +                        if(DBG) fprint(2, "%d rv(%lux, %lux) -> g i\n", pid, tag, val);
                        }
       -                rval = v->val;
       -                if(DBG)fprint(2, "pid is %d, awake\n", me);
                        putvous(v);
       +                unlock(&vouslock);
                }else{
                        /*
       -                 * Found someone to meet.  Wake him:
       -                 *
       -                 *        A. lock v->lk (waits for him to get to his step 2)
       -                 *        B. send a USR1
       -                 *
       -                 * He won't get the USR1 until he suspends, which
       -                 * means it must wake him up (it can't get delivered
       -                 * before he sleeps).
       +                 * Wake up sleeper.
                         */
       +                rval = v->val2;
       +                v->val1 = val;
                        vpid = v->pid;
       -                lock(&v->lk);
       -                rval = v->val;
       -                v->val = val;
       -                v->wakeup = 1;
       -                unlock(&v->lk);
       -                if(kill(vpid, SIGUSR1) < 0){
       -                        if(DBG)fprint(2, "pid is %d, kill %d failed: %r\n", me, vpid);
       -                        abort();
       -                }
       +                v->wokeup = 1;
       +                if(DBG) fprint(2, "%d rv(%lux, %lux) -> g %lux, w %d\n", pid, tag, val, rval, vpid);
       +                unlock(&vouslock);
       +                kill(vpid, SIGUSR1);
                }
                return rval;
        }
       -