shithub: riscv

Download patch

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;