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;
--
⑨