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

This commit is contained in:
cinap_lenrek 2011-08-10 16:21:17 +02:00
parent 5cf6f8c096
commit 70e4b8d1f9
7 changed files with 120 additions and 22 deletions

View file

@ -204,7 +204,7 @@ audioread(Chan *c, void *a, long n, vlong off)
if(fn == nil) if(fn == nil)
error(Egreg); error(Egreg);
qlock(ac); eqlock(ac);
if(waserror()){ if(waserror()){
qunlock(ac); qunlock(ac);
nexterror(); nexterror();
@ -260,7 +260,7 @@ audiowrite(Chan *c, void *a, long n, vlong off)
if(fn == nil) if(fn == nil)
error(Egreg); error(Egreg);
qlock(ac); eqlock(ac);
if(waserror()){ if(waserror()){
qunlock(ac); qunlock(ac);
nexterror(); nexterror();

View file

@ -105,7 +105,7 @@ mntversion(Chan *c, char *version, int msize, int returnlen)
uvlong oo; uvlong oo;
char buf[128]; 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()){ if(waserror()){
qunlock(&c->umqlock); qunlock(&c->umqlock);
nexterror(); nexterror();

View file

@ -735,6 +735,7 @@ struct Proc
int trace; /* process being traced? */ int trace; /* process being traced? */
ulong qpc; /* pc calling last blocking qlock */ ulong qpc; /* pc calling last blocking qlock */
QLock *eql; /* interruptable eqlock, protected by rlock */
int setargs; int setargs;

View file

@ -98,6 +98,7 @@ int eqchan(Chan*, Chan*, int);
int eqchantdqid(Chan*, int, int, Qid, int); int eqchantdqid(Chan*, int, int, Qid, int);
int eqqid(Qid, Qid); int eqqid(Qid, Qid);
void error(char*); void error(char*);
void eqlock(QLock*);
long execregs(ulong, ulong, ulong); long execregs(ulong, ulong, ulong);
void exhausted(char*); void exhausted(char*);
void exit(int); void exit(int);

View file

@ -900,8 +900,6 @@ int
postnote(Proc *p, int dolock, char *n, int flag) postnote(Proc *p, int dolock, char *n, int flag)
{ {
int s, ret; int s, ret;
Rendez *r;
Proc *d, **l;
if(dolock) if(dolock)
qlock(&p->debug); qlock(&p->debug);
@ -921,6 +919,8 @@ postnote(Proc *p, int dolock, char *n, int flag)
/* this loop is to avoid lock ordering problems. */ /* this loop is to avoid lock ordering problems. */
for(;;){ for(;;){
Rendez *r;
s = splhi(); s = splhi();
lock(&p->rlock); lock(&p->rlock);
r = p->r; r = p->r;
@ -948,24 +948,59 @@ postnote(Proc *p, int dolock, char *n, int flag)
unlock(&p->rlock); unlock(&p->rlock);
splx(s); splx(s);
if(p->state != Rendezvous) Pullout:
return ret; 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 */ q = p->eql;
lock(p->rgrp); if(!canlock(&q->use)){
if(p->state == Rendezvous) { unlock(&p->rlock);
p->rendval = ~0; sched();
l = &REND(p->rgrp, p->rendtag); goto Pullout;
for(d = *l; d; d = d->rendhash) {
if(d == p) {
*l = p->rendhash;
break;
} }
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; return ret;
} }

View file

@ -1017,7 +1017,7 @@ qbread(Queue *q, int len)
Block *b, *nb; Block *b, *nb;
int n; int n;
qlock(&q->rlock); eqlock(&q->rlock);
if(waserror()){ if(waserror()){
qunlock(&q->rlock); qunlock(&q->rlock);
nexterror(); nexterror();
@ -1072,7 +1072,7 @@ qread(Queue *q, void *vp, int len)
Block *b, *first, **l; Block *b, *first, **l;
int m, n; int m, n;
qlock(&q->rlock); eqlock(&q->rlock);
if(waserror()){ if(waserror()){
qunlock(&q->rlock); qunlock(&q->rlock);
nexterror(); nexterror();
@ -1173,7 +1173,7 @@ qbwrite(Queue *q, Block *b)
} }
dowakeup = 0; dowakeup = 0;
qlock(&q->wlock); eqlock(&q->wlock);
if(waserror()){ if(waserror()){
if(b != nil) if(b != nil)
freeb(b); freeb(b);

View file

@ -4,6 +4,8 @@
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
#include "../port/error.h"
struct { struct {
ulong rlock; ulong rlock;
ulong rlockq; ulong rlockq;
@ -13,6 +15,59 @@ struct {
ulong qlockq; ulong qlockq;
} rwstats; } 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 void
qlock(QLock *q) qlock(QLock *q)
{ {
@ -73,6 +128,12 @@ qunlock(QLock *q)
getcallerpc(&q)); getcallerpc(&q));
p = q->head; p = q->head;
if(p){ if(p){
if(p->eql){
lock(&p->rlock);
if(p->eql == q)
p->eql = 0;
unlock(&p->rlock);
}
q->head = p->qnext; q->head = p->qnext;
if(q->head == 0) if(q->head == 0)
q->tail = 0; q->tail = 0;