ref: 4c05d129e20a90a2aa25d2ad947d920f5e24a1ee
parent: b2ba90e7b6b0fc0941a2061ab038917861887f2d
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Wed Nov 2 17:39:30 EDT 2011
eqlock: fix postnote/qunlock race
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -736,7 +736,6 @@
ulong qpc; /* pc calling last blocking qlock */
QLock *eql; /* interruptable eqlock */
- Lock eqlock;
int setargs;
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -948,38 +948,35 @@
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 */
--- a/sys/src/9/port/qlock.c
+++ b/sys/src/9/port/qlock.c
@@ -42,7 +42,6 @@
error(Eintr);
}
rwstats.qlockq++;
-
p = q->tail;
if(p == 0)
q->head = up;
@@ -49,21 +48,16 @@
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 @@
else
p->qnext = up;
q->tail = up;
+ up->eql = 0;
up->qnext = 0;
up->state = Queueing;
up->qpc = getcallerpc(&q);
@@ -128,12 +123,6 @@
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;