git: 9front

Download patch

ref: a4ac136dc23986738b0461bcbcfda2266dd79bc6
parent: b51900de4e32f4c306951bcd1c044777b29d48be
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Wed Aug 10 12:21:17 EDT 2011

added eqlock(), a interruptable version of qlock. addresses issue #81

--- a/sys/src/9/port/devaudio.c
+++ b/sys/src/9/port/devaudio.c
@@ -204,7 +204,7 @@
 	if(fn == nil)
 		error(Egreg);
 
-	qlock(ac);
+	eqlock(ac);
 	if(waserror()){
 		qunlock(ac);
 		nexterror();
@@ -260,7 +260,7 @@
 	if(fn == nil)
 		error(Egreg);
 
-	qlock(ac);
+	eqlock(ac);
 	if(waserror()){
 		qunlock(ac);
 		nexterror();
--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -105,7 +105,7 @@
 	uvlong oo;
 	char buf[128];
 
-	qlock(&c->umqlock);	/* make sure no one else does this until we've established ourselves */
+	eqlock(&c->umqlock);	/* make sure no one else does this until we've established ourselves */
 	if(waserror()){
 		qunlock(&c->umqlock);
 		nexterror();
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -735,6 +735,7 @@
 	int	trace;		/* process being traced? */
 
 	ulong	qpc;		/* pc calling last blocking qlock */
+	QLock	*eql;		/* interruptable eqlock, protected by rlock */
 
 	int	setargs;
 
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -98,6 +98,7 @@
 int		eqchantdqid(Chan*, int, int, Qid, int);
 int		eqqid(Qid, Qid);
 void		error(char*);
+void		eqlock(QLock*);
 long		execregs(ulong, ulong, ulong);
 void		exhausted(char*);
 void		exit(int);
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -900,8 +900,6 @@
 postnote(Proc *p, int dolock, char *n, int flag)
 {
 	int s, ret;
-	Rendez *r;
-	Proc *d, **l;
 
 	if(dolock)
 		qlock(&p->debug);
@@ -921,6 +919,8 @@
 
 	/* this loop is to avoid lock ordering problems. */
 	for(;;){
+		Rendez *r;
+
 		s = splhi();
 		lock(&p->rlock);
 		r = p->r;
@@ -948,24 +948,59 @@
 	unlock(&p->rlock);
 	splx(s);
 
-	if(p->state != Rendezvous)
-		return ret;
+Pullout:
+	switch(p->state){
+	case Queueing:
+		/* Try and pull out of a eqlock */
+		lock(&p->rlock);
+		if(p->state == Queueing && p->eql && p->notepending){
+			Proc *d, *l;
+			QLock *q;
 
-	/* Try and pull out of a rendezvous */
-	lock(p->rgrp);
-	if(p->state == Rendezvous) {
-		p->rendval = ~0;
-		l = &REND(p->rgrp, p->rendtag);
-		for(d = *l; d; d = d->rendhash) {
-			if(d == p) {
-				*l = p->rendhash;
-				break;
+			q = p->eql;
+			if(!canlock(&q->use)){
+				unlock(&p->rlock);
+				sched();
+				goto Pullout;
 			}
-			l = &d->rendhash;
+			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;
+				}
+			unlock(&q->use);
+			break;
 		}
-		ready(p);
+		unlock(&p->rlock);
+		break;
+	case Rendezvous:
+		/* Try and pull out of a rendezvous */
+		lock(p->rgrp);
+		if(p->state == Rendezvous) {
+			Proc *d, **l;
+
+			p->rendval = ~0;
+			l = &REND(p->rgrp, p->rendtag);
+			for(d = *l; d; d = d->rendhash) {
+				if(d == p) {
+					*l = p->rendhash;
+					break;
+				}
+				l = &d->rendhash;
+			}
+			ready(p);
+		}
+		unlock(p->rgrp);
+		break;
 	}
-	unlock(p->rgrp);
 	return ret;
 }
 
--- a/sys/src/9/port/qio.c
+++ b/sys/src/9/port/qio.c
@@ -1017,7 +1017,7 @@
 	Block *b, *nb;
 	int n;
 
-	qlock(&q->rlock);
+	eqlock(&q->rlock);
 	if(waserror()){
 		qunlock(&q->rlock);
 		nexterror();
@@ -1072,7 +1072,7 @@
 	Block *b, *first, **l;
 	int m, n;
 
-	qlock(&q->rlock);
+	eqlock(&q->rlock);
 	if(waserror()){
 		qunlock(&q->rlock);
 		nexterror();
@@ -1173,7 +1173,7 @@
 	}
 
 	dowakeup = 0;
-	qlock(&q->wlock);
+	eqlock(&q->wlock);
 	if(waserror()){
 		if(b != nil)
 			freeb(b);
--- a/sys/src/9/port/qlock.c
+++ b/sys/src/9/port/qlock.c
@@ -4,6 +4,8 @@
 #include "dat.h"
 #include "fns.h"
 
+#include	"../port/error.h"
+
 struct {
 	ulong rlock;
 	ulong rlockq;
@@ -14,6 +16,59 @@
 } rwstats;
 
 void
+eqlock(QLock *q)
+{
+	Proc *p;
+
+	if(m->ilockdepth != 0)
+		print("eqlock: %#p: ilockdepth %d\n", getcallerpc(&q), m->ilockdepth);
+	if(up != nil && up->nlocks.ref)
+		print("eqlock: %#p: nlocks %lud\n", getcallerpc(&q), up->nlocks.ref);
+
+	if(q->use.key == 0x55555555)
+		panic("eqlock: q %#p, key 5*\n", q);
+
+	lock(&q->use);
+	rwstats.qlock++;
+	if(!q->locked) {
+		q->locked = 1;
+		unlock(&q->use);
+		return;
+	}
+	if(up == 0)
+		panic("eqlock");
+	if(up->notepending){
+		unlock(&q->use);
+		error(Eintr);
+	}
+	rwstats.qlockq++;
+
+	p = q->tail;
+	if(p == 0)
+		q->head = up;
+	else
+		p->qnext = up;
+	q->tail = up;
+
+	up->qnext = 0;
+	up->qpc = getcallerpc(&q);
+	up->state = Queueing;
+
+	lock(&up->rlock);
+	up->eql = q;
+	unlock(&up->rlock);
+
+	unlock(&q->use);
+
+	sched();
+
+	if(up->notepending){
+		up->notepending = 0;
+		error(Eintr);
+	}
+}
+
+void
 qlock(QLock *q)
 {
 	Proc *p;
@@ -73,6 +128,12 @@
 			getcallerpc(&q));
 	p = q->head;
 	if(p){
+		if(p->eql){
+			lock(&p->rlock);
+			if(p->eql == q)
+				p->eql = 0;
+			unlock(&p->rlock);
+		}
 		q->head = p->qnext;
 		if(q->head == 0)
 			q->tail = 0;
--