From 4c05d129e20a90a2aa25d2ad947d920f5e24a1ee Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Wed, 2 Nov 2011 21:39:30 +0100 Subject: [PATCH] eqlock: fix postnote/qunlock race --- sys/src/9/port/portdat.h | 1 - sys/src/9/port/proc.c | 43 +++++++++++++++++++--------------------- sys/src/9/port/qlock.c | 19 ++++-------------- 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 2fcb37b0b..5aca7fb14 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -736,7 +736,6 @@ struct Proc ulong qpc; /* pc calling last blocking qlock */ QLock *eql; /* interruptable eqlock */ - Lock eqlock; int setargs; diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 99000a6fa..f2045e840 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -948,38 +948,35 @@ postnote(Proc *p, int dolock, char *n, int flag) unlock(&p->rlock); splx(s); -Pullout: switch(p->state){ case Queueing: /* Try and pull out of a eqlock */ - lock(&p->eqlock); - if(p->state == Queueing && p->eql && p->notepending){ - Proc *d, *l; + if(p->notepending){ QLock *q; - q = p->eql; - if(!canlock(&q->use)){ - unlock(&p->eqlock); - sched(); - goto Pullout; - } + if((q = p->eql) == nil) + break; + lock(&q->use); + if(p->state == Queueing && p->eql == q && p->notepending){ + Proc *d, *l; - for(l = nil, d = q->head; d; l = d, d = d->qnext) - if(d == p){ - if(l) - l->qnext = p->qnext; - else - q->head = p->qnext; - if(p->qnext == 0) - q->tail = l; - p->qnext = 0; - p->eql = 0; - ready(p); - break; + for(l = nil, d = q->head; d; l = d, d = d->qnext){ + if(d == p){ + if(l) + l->qnext = p->qnext; + else + q->head = p->qnext; + if(p->qnext == 0) + q->tail = l; + p->qnext = 0; + p->eql = 0; /* not taken */ + ready(p); + break; + } } + } unlock(&q->use); } - unlock(&p->eqlock); break; case Rendezvous: /* Try and pull out of a rendezvous */ diff --git a/sys/src/9/port/qlock.c b/sys/src/9/port/qlock.c index d41768435..ece5488b1 100644 --- a/sys/src/9/port/qlock.c +++ b/sys/src/9/port/qlock.c @@ -42,28 +42,22 @@ eqlock(QLock *q) error(Eintr); } rwstats.qlockq++; - p = q->tail; if(p == 0) q->head = up; else p->qnext = up; q->tail = up; - + up->eql = q; up->qnext = 0; up->qpc = getcallerpc(&q); up->state = Queueing; - - lock(&up->eqlock); - up->eql = q; - unlock(&up->eqlock); - unlock(&q->use); - sched(); - if(up->notepending){ up->notepending = 0; + if(up->eql == q) + qunlock(q); error(Eintr); } } @@ -96,6 +90,7 @@ qlock(QLock *q) else p->qnext = up; q->tail = up; + up->eql = 0; up->qnext = 0; up->state = Queueing; up->qpc = getcallerpc(&q); @@ -128,12 +123,6 @@ qunlock(QLock *q) getcallerpc(&q)); p = q->head; if(p){ - if(p->eql){ - lock(&p->eqlock); - if(p->eql == q) - p->eql = 0; - unlock(&p->eqlock); - } q->head = p->qnext; if(q->head == 0) q->tail = 0;