eqlock: fix postnote/qunlock race
This commit is contained in:
parent
b2ba90e7b6
commit
4c05d129e2
3 changed files with 24 additions and 39 deletions
|
@ -736,7 +736,6 @@ struct Proc
|
||||||
|
|
||||||
ulong qpc; /* pc calling last blocking qlock */
|
ulong qpc; /* pc calling last blocking qlock */
|
||||||
QLock *eql; /* interruptable eqlock */
|
QLock *eql; /* interruptable eqlock */
|
||||||
Lock eqlock;
|
|
||||||
|
|
||||||
int setargs;
|
int setargs;
|
||||||
|
|
||||||
|
|
|
@ -948,23 +948,19 @@ postnote(Proc *p, int dolock, char *n, int flag)
|
||||||
unlock(&p->rlock);
|
unlock(&p->rlock);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
Pullout:
|
|
||||||
switch(p->state){
|
switch(p->state){
|
||||||
case Queueing:
|
case Queueing:
|
||||||
/* Try and pull out of a eqlock */
|
/* Try and pull out of a eqlock */
|
||||||
lock(&p->eqlock);
|
if(p->notepending){
|
||||||
if(p->state == Queueing && p->eql && p->notepending){
|
|
||||||
Proc *d, *l;
|
|
||||||
QLock *q;
|
QLock *q;
|
||||||
|
|
||||||
q = p->eql;
|
if((q = p->eql) == nil)
|
||||||
if(!canlock(&q->use)){
|
break;
|
||||||
unlock(&p->eqlock);
|
lock(&q->use);
|
||||||
sched();
|
if(p->state == Queueing && p->eql == q && p->notepending){
|
||||||
goto Pullout;
|
Proc *d, *l;
|
||||||
}
|
|
||||||
|
|
||||||
for(l = nil, d = q->head; d; l = d, d = d->qnext)
|
for(l = nil, d = q->head; d; l = d, d = d->qnext){
|
||||||
if(d == p){
|
if(d == p){
|
||||||
if(l)
|
if(l)
|
||||||
l->qnext = p->qnext;
|
l->qnext = p->qnext;
|
||||||
|
@ -973,13 +969,14 @@ Pullout:
|
||||||
if(p->qnext == 0)
|
if(p->qnext == 0)
|
||||||
q->tail = l;
|
q->tail = l;
|
||||||
p->qnext = 0;
|
p->qnext = 0;
|
||||||
p->eql = 0;
|
p->eql = 0; /* not taken */
|
||||||
ready(p);
|
ready(p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
unlock(&q->use);
|
unlock(&q->use);
|
||||||
}
|
}
|
||||||
unlock(&p->eqlock);
|
|
||||||
break;
|
break;
|
||||||
case Rendezvous:
|
case Rendezvous:
|
||||||
/* Try and pull out of a rendezvous */
|
/* Try and pull out of a rendezvous */
|
||||||
|
|
|
@ -42,28 +42,22 @@ eqlock(QLock *q)
|
||||||
error(Eintr);
|
error(Eintr);
|
||||||
}
|
}
|
||||||
rwstats.qlockq++;
|
rwstats.qlockq++;
|
||||||
|
|
||||||
p = q->tail;
|
p = q->tail;
|
||||||
if(p == 0)
|
if(p == 0)
|
||||||
q->head = up;
|
q->head = up;
|
||||||
else
|
else
|
||||||
p->qnext = up;
|
p->qnext = up;
|
||||||
q->tail = up;
|
q->tail = up;
|
||||||
|
up->eql = q;
|
||||||
up->qnext = 0;
|
up->qnext = 0;
|
||||||
up->qpc = getcallerpc(&q);
|
up->qpc = getcallerpc(&q);
|
||||||
up->state = Queueing;
|
up->state = Queueing;
|
||||||
|
|
||||||
lock(&up->eqlock);
|
|
||||||
up->eql = q;
|
|
||||||
unlock(&up->eqlock);
|
|
||||||
|
|
||||||
unlock(&q->use);
|
unlock(&q->use);
|
||||||
|
|
||||||
sched();
|
sched();
|
||||||
|
|
||||||
if(up->notepending){
|
if(up->notepending){
|
||||||
up->notepending = 0;
|
up->notepending = 0;
|
||||||
|
if(up->eql == q)
|
||||||
|
qunlock(q);
|
||||||
error(Eintr);
|
error(Eintr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +90,7 @@ qlock(QLock *q)
|
||||||
else
|
else
|
||||||
p->qnext = up;
|
p->qnext = up;
|
||||||
q->tail = up;
|
q->tail = up;
|
||||||
|
up->eql = 0;
|
||||||
up->qnext = 0;
|
up->qnext = 0;
|
||||||
up->state = Queueing;
|
up->state = Queueing;
|
||||||
up->qpc = getcallerpc(&q);
|
up->qpc = getcallerpc(&q);
|
||||||
|
@ -128,12 +123,6 @@ qunlock(QLock *q)
|
||||||
getcallerpc(&q));
|
getcallerpc(&q));
|
||||||
p = q->head;
|
p = q->head;
|
||||||
if(p){
|
if(p){
|
||||||
if(p->eql){
|
|
||||||
lock(&p->eqlock);
|
|
||||||
if(p->eql == q)
|
|
||||||
p->eql = 0;
|
|
||||||
unlock(&p->eqlock);
|
|
||||||
}
|
|
||||||
q->head = p->qnext;
|
q->head = p->qnext;
|
||||||
if(q->head == 0)
|
if(q->head == 0)
|
||||||
q->tail = 0;
|
q->tail = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue