From 68a7e6d363db8a3ef4a73a7254d2197400738a74 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 16 Oct 1996 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1996-10-16 --- port/portdat.h | 2 +- port/proc.c | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/port/portdat.h b/port/portdat.h index a3fe20af00e220358a95c265229f94a773f11844..f6d3ce9c5b073c2acc16e2f4aa3de7f12f30c981 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -555,7 +555,7 @@ struct Proc int procctl; /* Control for /proc debugging */ ulong pc; /* DEBUG only */ - Lock rlock; /* synchronization for 'r' below */ + Lock rlock; /* sync sleep/wakeup with postnote */ Rendez *r; /* rendezvous point slept on */ Rendez sleep; /* place for syssleep/debug */ int notepending; /* note issued but not acted on */ diff --git a/port/proc.c b/port/proc.c index a33d83b2ab3747093d924d4dadce6de98c32db3f..93fb87606602993229a410d3514a46dab60f3b50 100644 --- a/port/proc.c +++ b/port/proc.c @@ -383,14 +383,15 @@ sleep1(Rendez *r, int (*f)(void*), void *arg) * at interrupt time. lock is mutual exclusion */ s = splhi(); - up->r = r; /* early so postnote knows */ lock(r); + lock(&up->rlock); /* * if condition happened, never mind */ if((*f)(arg)){ up->r = 0; + unlock(&up->rlock); unlock(r); splx(s); return; @@ -406,6 +407,8 @@ sleep1(Rendez *r, int (*f)(void*), void *arg) } up->state = Wakeme; r->p = up; + up->r = r; + unlock(&up->rlock); unlock(r); } @@ -422,8 +425,10 @@ sleep(Rendez *r, int (*f)(void*), void *arg) up->notepending = 0; s = splhi(); lock(r); + lock(&up->rlock); if(r->p == up) r->p = 0; + unlock(&up->rlock); unlock(r); splx(s); error(Eintr); @@ -487,10 +492,12 @@ wakeup(Rendez *r) lock(r); p = r->p; if(p){ + lock(&p->rlock); r->p = 0; if(p->state != Wakeme) panic("wakeup: state"); p->r = 0; + unlock(&p->rlock); ready(p); } unlock(r); @@ -523,20 +530,35 @@ postnote(Proc *p, int dolock, char *n, int flag) if(dolock) qunlock(&p->debug); - r = p->r; - if(r != 0) { - for(;;) { - s = splhi(); - if(canlock(r)) - break; + for(;;){ + s = splhi(); + lock(&p->rlock); + r = p->r; + if(r == 0){ + unlock(&p->rlock); + splx(s); + break; + } + + /* the canlock deals with a different lock ordering + * twixt r and p->rlock than everywhere else. If we + * locked in the normal order we wouldn't be sure + * r was valid when we did the lock. + */ + if(!canlock(r)){ + unlock(&p->rlock); splx(s); + continue; } + /* check we won the race */ if(p->r == r && r->p == p && p->state==Wakeme) { r->p = 0; p->r = 0; ready(p); } + + unlock(&p->rlock); unlock(r); splx(s); } @@ -680,9 +702,12 @@ pexit(char *exitstr, int freemem) wq->w.msg[0] = '\0'; lock(&p->exl); - /* My parent still alive, processes are limited to 128 - * Zombies to prevent a badly written daemon lots of wait - * records + /* + * If my parent is no longer alive, or if there would be more + * than 128 zombie child processes for my parent, then don't + * leave a wait record behind. This helps prevent badly + * written daemon processes from accumulating lots of wait + * records. */ if(p->pid == up->parentpid && p->state != Broken && p->nwait < 128) { p->nchild--; @@ -692,9 +717,9 @@ pexit(char *exitstr, int freemem) wq->next = p->waitq; p->waitq = wq; p->nwait++; - unlock(&p->exl); wakeup(&p->waitr); + unlock(&p->exl); } else { unlock(&p->exl);