summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@centraldogma>2011-08-10 16:21:17 +0200
committercinap_lenrek <cinap_lenrek@centraldogma>2011-08-10 16:21:17 +0200
commit70e4b8d1f957b900f784d9f7205ab2a96d7e440a (patch)
tree7dbc0769915b534c42ca5263e784a37c61719fff
parent5cf6f8c096cb4ac35684530024255aa68781794a (diff)
downloadplan9front-70e4b8d1f957b900f784d9f7205ab2a96d7e440a.tar.xz
added eqlock(), a interruptable version of qlock. addresses issue #81
-rw-r--r--sys/src/9/port/devaudio.c4
-rw-r--r--sys/src/9/port/devmnt.c2
-rw-r--r--sys/src/9/port/portdat.h1
-rw-r--r--sys/src/9/port/portfns.h1
-rw-r--r--sys/src/9/port/proc.c69
-rw-r--r--sys/src/9/port/qio.c6
-rw-r--r--sys/src/9/port/qlock.c61
7 files changed, 121 insertions, 23 deletions
diff --git a/sys/src/9/port/devaudio.c b/sys/src/9/port/devaudio.c
index 5dd1065d0..c9fbcad30 100644
--- a/sys/src/9/port/devaudio.c
+++ b/sys/src/9/port/devaudio.c
@@ -204,7 +204,7 @@ audioread(Chan *c, void *a, long n, vlong off)
if(fn == nil)
error(Egreg);
- qlock(ac);
+ eqlock(ac);
if(waserror()){
qunlock(ac);
nexterror();
@@ -260,7 +260,7 @@ audiowrite(Chan *c, void *a, long n, vlong off)
if(fn == nil)
error(Egreg);
- qlock(ac);
+ eqlock(ac);
if(waserror()){
qunlock(ac);
nexterror();
diff --git a/sys/src/9/port/devmnt.c b/sys/src/9/port/devmnt.c
index 129d06e2a..6f06e0d55 100644
--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -105,7 +105,7 @@ mntversion(Chan *c, char *version, int msize, int returnlen)
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();
diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h
index bef56c086..633ce28d0 100644
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -735,6 +735,7 @@ struct Proc
int trace; /* process being traced? */
ulong qpc; /* pc calling last blocking qlock */
+ QLock *eql; /* interruptable eqlock, protected by rlock */
int setargs;
diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h
index 6e6653901..a62e24040 100644
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -98,6 +98,7 @@ int eqchan(Chan*, Chan*, int);
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);
diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c
index de08fe72d..2cfa6faec 100644
--- a/sys/src/9/port/proc.c
+++ b/sys/src/9/port/proc.c
@@ -900,8 +900,6 @@ int
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 @@ postnote(Proc *p, int dolock, char *n, int flag)
/* this loop is to avoid lock ordering problems. */
for(;;){
+ Rendez *r;
+
s = splhi();
lock(&p->rlock);
r = p->r;
@@ -948,24 +948,59 @@ postnote(Proc *p, int dolock, char *n, int flag)
unlock(&p->rlock);
splx(s);
- if(p->state != Rendezvous)
- return ret;
-
- /* 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;
+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;
+
+ 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;
}
diff --git a/sys/src/9/port/qio.c b/sys/src/9/port/qio.c
index aa4de59f3..c91cad04c 100644
--- a/sys/src/9/port/qio.c
+++ b/sys/src/9/port/qio.c
@@ -1017,7 +1017,7 @@ qbread(Queue *q, int len)
Block *b, *nb;
int n;
- qlock(&q->rlock);
+ eqlock(&q->rlock);
if(waserror()){
qunlock(&q->rlock);
nexterror();
@@ -1072,7 +1072,7 @@ qread(Queue *q, void *vp, int len)
Block *b, *first, **l;
int m, n;
- qlock(&q->rlock);
+ eqlock(&q->rlock);
if(waserror()){
qunlock(&q->rlock);
nexterror();
@@ -1173,7 +1173,7 @@ qbwrite(Queue *q, Block *b)
}
dowakeup = 0;
- qlock(&q->wlock);
+ eqlock(&q->wlock);
if(waserror()){
if(b != nil)
freeb(b);
diff --git a/sys/src/9/port/qlock.c b/sys/src/9/port/qlock.c
index 3d666516d..9c0059044 100644
--- 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 @@ struct {
} 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 @@ qunlock(QLock *q)
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;