added eqlock(), a interruptable version of qlock. addresses issue #81
This commit is contained in:
parent
5cf6f8c096
commit
70e4b8d1f9
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,12 +948,45 @@ 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;
|
||||||
|
|
||||||
|
q = p->eql;
|
||||||
|
if(!canlock(&q->use)){
|
||||||
|
unlock(&p->rlock);
|
||||||
|
sched();
|
||||||
|
goto Pullout;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
unlock(&p->rlock);
|
||||||
|
break;
|
||||||
|
case Rendezvous:
|
||||||
/* Try and pull out of a rendezvous */
|
/* Try and pull out of a rendezvous */
|
||||||
lock(p->rgrp);
|
lock(p->rgrp);
|
||||||
if(p->state == Rendezvous) {
|
if(p->state == Rendezvous) {
|
||||||
|
Proc *d, **l;
|
||||||
|
|
||||||
p->rendval = ~0;
|
p->rendval = ~0;
|
||||||
l = &REND(p->rgrp, p->rendtag);
|
l = &REND(p->rgrp, p->rendtag);
|
||||||
for(d = *l; d; d = d->rendhash) {
|
for(d = *l; d; d = d->rendhash) {
|
||||||
|
@ -966,6 +999,8 @@ postnote(Proc *p, int dolock, char *n, int flag)
|
||||||
ready(p);
|
ready(p);
|
||||||
}
|
}
|
||||||
unlock(p->rgrp);
|
unlock(p->rgrp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue