M carrera/clock.c => carrera/clock.c +7 -7
@@ 78,15 78,15 @@ clockinit(void)
uvlong
updatefastclock(ulong count)
{
- uvlong cyclecount;
+ vlong delta;
/* keep track of higher precision time */
- cyclecount = count;
- if(cyclecount < m->lastcyclecount)
- m->fastclock += (0x100000000LL - m->lastcyclecount) + cyclecount;
- else
- m->fastclock += cyclecount - m->lastcyclecount;
- m->lastcyclecount = cyclecount;
+ delta = count - m->lastcyclecount;
+ if(delta < 0)
+ delta += 0x100000000LL;
+ m->lastcyclecount = count;
+ m->fastclock += delta;
+
return m->fastclock;
}
M ip/devip.c => ip/devip.c +28 -24
@@ 367,7 367,14 @@ ipopen(Chan* c, int omode)
break;
case Qclone:
p = f->p[PROTO(c->qid)];
+ qlock(p);
+ if(waserror()){
+ qunlock(p);
+ nexterror();
+ }
cv = Fsprotoclone(p, commonuser());
+ qunlock(p);
+ poperror();
if(cv == nil) {
error(Enodev);
break;
@@ 380,9 387,9 @@ ipopen(Chan* c, int omode)
p = f->p[PROTO(c->qid)];
qlock(p);
cv = p->conv[CONV(c->qid)];
- lock(cv);
+ qlock(cv);
if(waserror()) {
- unlock(cv);
+ qunlock(cv);
qunlock(p);
nexterror();
}
@@ 398,7 405,7 @@ ipopen(Chan* c, int omode)
memmove(cv->owner, commonuser(), NAMELEN);
cv->perm = 0660;
}
- unlock(cv);
+ qunlock(cv);
qunlock(p);
poperror();
break;
@@ 422,14 429,14 @@ ipopen(Chan* c, int omode)
/* wait for a connect */
sleep(&cv->listenr, incoming, cv);
- lock(cv);
+ qlock(cv);
nc = cv->incall;
if(nc != nil){
cv->incall = nc->next;
c->qid = (Qid){QID(PROTO(c->qid), nc->x, Qctl), 0};
memmove(cv->owner, commonuser(), NAMELEN);
}
- unlock(cv);
+ qunlock(cv);
qunlock(&cv->listenq);
poperror();
@@ 466,10 473,10 @@ closeconv(Conv *cv)
Conv *nc;
Ipmulti *mp;
- lock(cv);
+ qlock(cv);
if(--cv->inuse > 0) {
- unlock(cv);
+ qunlock(cv);
return;
}
@@ 1005,17 1012,15 @@ Fsbuiltinproto(Fs* f, uchar proto)
return f->t2p[proto] != nil;
}
+/*
+ * called with protocol locked
+ */
Conv*
Fsprotoclone(Proto *p, char *user)
{
Conv *c, **pp, **ep;
c = nil;
- qlock(p);
- if(waserror()) {
- qunlock(p);
- nexterror();
- }
ep = &p->conv[p->nc];
for(pp = p->conv; pp < ep; pp++) {
c = *pp;
@@ 1023,7 1028,7 @@ Fsprotoclone(Proto *p, char *user)
c = malloc(sizeof(Conv));
if(c == nil)
error(Enomem);
- lock(c);
+ qlock(c);
c->p = p;
c->x = pp - p->conv;
c->ptcl = malloc(p->ptclsize);
@@ 1037,7 1042,7 @@ Fsprotoclone(Proto *p, char *user)
(*p->create)(c);
break;
}
- if(canlock(c)){
+ if(canqlock(c)){
/*
* make sure both processes and protocol
* are done with this Conv
@@ 1045,12 1050,10 @@ Fsprotoclone(Proto *p, char *user)
if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
break;
- unlock(c);
+ qunlock(c);
}
}
if(pp >= ep) {
- qunlock(p);
- poperror();
return nil;
}
@@ 1068,9 1071,7 @@ Fsprotoclone(Proto *p, char *user)
qreopen(c->wq);
qreopen(c->eq);
- unlock(c);
- qunlock(p);
- poperror();
+ qunlock(c);
return c;
}
@@ 1110,6 1111,9 @@ Fsrcvpcolx(Fs *f, uchar proto)
return f->t2p[proto];
}
+/*
+ * called with protocol locked
+ */
Conv*
Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
{
@@ 1117,19 1121,19 @@ Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
Conv **l;
int i;
- lock(c);
+ qlock(c);
i = 0;
for(l = &c->incall; *l; l = &(*l)->next)
i++;
if(i >= Maxincall) {
- unlock(c);
+ qunlock(c);
return nil;
}
/* find a free conversation */
nc = Fsprotoclone(c->p, network);
if(nc == nil) {
- unlock(c);
+ qunlock(c);
return nil;
}
ipmove(nc->raddr, raddr);
@@ 1138,7 1142,7 @@ Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport)
nc->lport = lport;
nc->next = nil;
*l = nc;
- unlock(c);
+ qunlock(c);
wakeup(&c->listenr);
M ip/ethermedium.c => ip/ethermedium.c +10 -5
@@ 265,27 265,32 @@ etherread(void *a)
Ipifc *ifc;
Block *bp;
Etherrock *er;
- int locked = 0;
ifc = a;
er = ifc->arg;
er->readp = up; /* hide identity under a rock for unbind */
if(waserror()){
- if(locked)
- runlock(ifc);
er->readp = 0;
pexit("hangup", 1);
}
for(;;){
bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxmtu, 0);
- rlock(ifc); locked = 1; USED(locked);
+ if(!canrlock(ifc)){
+ freeb(bp);
+ continue;
+ }
+ if(waserror()){
+ runlock(ifc);
+ nexterror();
+ }
ifc->in++;
bp->rp += ifc->m->hsize;
if(ifc->lifc == nil)
freeb(bp);
else
ipiput(er->f, ifc->lifc->local, bp);
- runlock(ifc); locked = 0; USED(locked);
+ runlock(ifc);
+ poperror();
}
}
M ip/gre.c => ip/gre.c +6 -1
@@ 115,7 115,7 @@ greclose(Conv *c)
c->lport = 0;
c->rport = 0;
- unlock(c);
+ qunlock(c);
}
int drop;
@@ 179,6 179,8 @@ greiput(Proto *gre, uchar*, Block *bp)
v4tov6(raddr, ghp->src);
eproto = nhgets(ghp->eproto);
+ qlock(gre);
+
/* Look for a conversation structure for this port and address */
c = nil;
for(p = gre->conv; *p; p++) {
@@ 190,10 192,13 @@ greiput(Proto *gre, uchar*, Block *bp)
}
if(*p == nil) {
+ qunlock(gre);
freeblist(bp);
return;
}
+ qunlock(gre);
+
/*
* Trim the packet down to data size
*/
M ip/icmp.c => ip/icmp.c +2 -1
@@ 140,7 140,7 @@ icmpclose(Conv *c)
ipmove(c->laddr, IPnoaddr);
ipmove(c->raddr, IPnoaddr);
c->lport = 0;
- unlock(c);
+ qunlock(c);
}
static void
@@ 328,6 328,7 @@ icmpiput(Proto *icmp, uchar*, Block *bp)
}
if(p->type <= Maxtype)
ipriv->in[p->type]++;
+
switch(p->type) {
case EchoRequest:
r = mkechoreply(bp);
M ip/il.c => ip/il.c +30 -3
@@ 274,7 274,7 @@ ilclose(Conv *c)
break;
}
ilfreeq(ic);
- unlock(c);
+ qunlock(c);
}
void
@@ 521,17 521,28 @@ iliput(Proto *il, uchar*, Block *bp)
goto raise;
}
+ qlock(il);
+
for(p = il->conv; *p; p++) {
s = *p;
if(s->lport == sp)
if(s->rport == dp)
if(ipcmp(s->raddr, raddr) == 0) {
+ qlock(s);
+ qunlock(il);
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
ilprocess(s, ih, bp);
+ qunlock(s);
+ poperror();
return;
}
}
if(ih->iltype != Ilsync){
+ qunlock(il);
if(ih->iltype < 0 || ih->iltype > Ilclose)
st = "?";
else
@@ 564,24 575,36 @@ iliput(Proto *il, uchar*, Block *bp)
else
if(gen)
s = gen;
- else
+ else {
+ qunlock(il);
goto raise;
+ }
v4tov6(laddr, ih->dst);
new = Fsnewcall(s, raddr, dp, laddr, sp);
if(new == nil){
+ qunlock(il);
netlog(il->f, Logil, "il: bad newcall %I/%ud->%ud\n", raddr, sp, dp);
ilsendctl(nil, ih, Ilclose, 0, nhgetl(ih->ilid), 0);
goto raise;
}
ic = (Ilcb*)new->ptcl;
+
ic->conv = new;
ic->state = Ilsyncee;
ilcbinit(ic);
ic->rstart = nhgetl(ih->ilid);
+ qlock(new);
+ qunlock(il);
+ if(waserror()){
+ qunlock(new);
+ nexterror();
+ }
ilprocess(new, ih, bp);
+ qunlock(new);
+ poperror();
return;
raise:
@@ 1179,20 1202,24 @@ iladvise(Proto *il, Block *bp, char *msg)
/* Look for a connection, unfortunately the destination port is missing */
+ qlock(il);
for(p = il->conv; *p; p++) {
s = *p;
if(s->lport == psource)
if(ipcmp(s->laddr, source) == 0)
if(ipcmp(s->raddr, dest) == 0){
+ qunlock(il);
ic = (Ilcb*)s->ptcl;
switch(ic->state){
case Ilsyncer:
ilhangup(s, msg);
break;
}
- break;
+ freeblist(bp);
+ return;
}
}
+ qunlock(il);
freeblist(bp);
}
M ip/ip.c => ip/ip.c +5 -4
@@ 85,7 85,7 @@ struct IP
Fragment* flisthead;
Fragment* fragfree;
- ulong id;
+ Ref id;
int iprouting; /* true if we route like a gateway */
void (*ipextprotoiput)(Block*);
};
@@ 186,11 186,12 @@ ipoput(Fs *f, Block *bp, int gating, int ttl)
eh->ttl = ttl;
}
+ if(!canrlock(ifc))
+ goto free;
if(waserror()){
runlock(ifc);
nexterror();
}
- rlock(ifc);
if(ifc->m == nil)
goto raise;
@@ 198,7 199,7 @@ ipoput(Fs *f, Block *bp, int gating, int ttl)
medialen = ifc->m->maxmtu - ifc->m->hsize;
if(len <= medialen) {
if(!gating)
- hnputs(eh->id, ip->id++);
+ hnputs(eh->id, incref(&ip->id));
hnputs(eh->length, len);
eh->frag[0] = 0;
eh->frag[1] = 0;
@@ 231,7 232,7 @@ ipoput(Fs *f, Block *bp, int gating, int ttl)
if(gating)
lid = nhgets(eh->id);
else
- lid = ip->id++;
+ lid = incref(&ip->id);
offset = IPHDR;
while(xp != nil && offset && offset >= BLEN(xp)) {
M ip/ip.h => ip/ip.h +1 -1
@@ 58,7 58,7 @@ enum
*/
struct Conv
{
- Lock;
+ QLock;
int x; /* conversation index */
Proto* p;
M ip/ipifc.c => ip/ipifc.c +5 -5
@@ 136,9 136,9 @@ ipifcbind(Conv *c, char **argv, int argc)
ifc->minmtu = ifc->m->minmtu;
ifc->maxmtu = ifc->m->maxmtu;
if(ifc->m->unbindonclose == 0){
- lock(ifc->conv);
+ qlock(ifc->conv);
ifc->conv->inuse++;
- unlock(ifc->conv);
+ qunlock(ifc->conv);
}
ifc->ifcid++;
@@ 166,9 166,9 @@ ipifcunbind(Ipifc *ifc)
/* dissociate routes */
if(ifc->m != nil && ifc->m->unbindonclose == 0){
- lock(ifc->conv);
+ qlock(ifc->conv);
ifc->conv->inuse--;
- unlock(ifc->conv);
+ qunlock(ifc->conv);
}
ifc->ifcid++;
@@ 305,7 305,7 @@ ipifcclose(Conv *c)
m = ifc->m;
if(m != nil && m->unbindonclose)
ipifcunbind(ifc);
- unlock(c);
+ qunlock(c);
}
/*
M ip/ipmux.c => ip/ipmux.c +1 -1
@@ 620,7 620,7 @@ ipmuxclose(Conv *c)
ipmuxtreefree(r->chain);
r->chain = nil;
- unlock(c);
+ qunlock(c);
}
/*
M ip/rudp.c => ip/rudp.c +6 -2
@@ 289,7 289,7 @@ rudpclose(Conv *c)
qunlock(ucb);
- unlock(c);
+ qunlock(c);
}
/*
@@ 490,6 490,8 @@ rudpiput(Proto *rudp, uchar *ia, Block *bp)
}
}
+ qlock(rudp);
+
/* Look for a conversation structure for this port */
c = nil;
for(p = rudp->conv; *p; p++) {
@@ 512,6 514,7 @@ rudpiput(Proto *rudp, uchar *ia, Block *bp)
}
if(*p == nil) {
+ qunlock(rudp);
upriv->ustats.rudpNoPorts++;
netlog(f, Logrudp, "rudp: no conv %I!%d -> %I!%d\n", raddr, rport,
laddr, lport);
@@ 525,8 528,9 @@ rudpiput(Proto *rudp, uchar *ia, Block *bp)
}
ucb = (Rudpcb*)c->ptcl;
-
qlock(ucb);
+ qunlock(rudp);
+
if(reliput(c, bp, raddr, rport) < 0){
qunlock(ucb);
freeb(bp);
M ip/tcp.c => ip/tcp.c +39 -31
@@ 133,10 133,12 @@ struct Reseq
ushort length;
};
+/*
+ * the qlock in the Conv locks this structure
+ */
typedef struct Tcpctl Tcpctl;
struct Tcpctl
{
- QLock;
uchar state; /* Connection state */
uchar type; /* Listening or active connection */
uchar code; /* Icmp code */
@@ 343,8 345,6 @@ tcpclose(Conv *c)
qhangup(c->wq, nil);
qhangup(c->eq, nil);
- unlock(c);
-
switch(tcb->state) {
case Listen:
/*
@@ 352,31 352,27 @@ tcpclose(Conv *c)
*/
Fsconnected(c, "Hangup");
- qlock(tcb);
localclose(c, nil);
break;
case Closed:
case Syn_sent:
- qlock(tcb);
localclose(c, nil);
break;
case Syn_received:
case Established:
- qlock(tcb);
tcb->sndcnt++;
tcb->snd.nxt++;
tcpsetstate(c, Finwait1);
tcpoutput(c);
break;
case Close_wait:
- qlock(tcb);
tcb->sndcnt++;
tcb->snd.nxt++;
tcpsetstate(c, Last_ack);
tcpoutput(c);
break;
}
- qunlock(tcb);
+ qunlock(c);
}
void
@@ 400,11 396,11 @@ tcpkick(Conv *s, int len)
/*
* Push data
*/
- qlock(tcb);
+ qlock(s);
tcb->sndcnt += len;
tcprcvwin(s);
tcpoutput(s);
- qunlock(tcb);
+ qunlock(s);
break;
default:
localclose(s, "Hangup");
@@ 445,11 441,11 @@ tcpacktimer(Conv *s)
tcb = (Tcpctl*)s->ptcl;
- qlock(tcb);
+ qlock(s);
tcb->flags |= FORCE;
tcprcvwin(s);
tcpoutput(s);
- qunlock(tcb);
+ qunlock(s);
}
static void
@@ 667,12 663,12 @@ tcpstart(Conv *s, int mode, ushort window)
case TCP_CONNECT:
tpriv->tstats.tcpActiveOpens++;
/* Send SYN, go into SYN_SENT state */
- qlock(tcb);
+ qlock(s);
tcb->flags |= ACTIVE;
tcpsndsyn(tcb);
tcpsetstate(s, Syn_sent);
tcpoutput(s);
- qunlock(tcb);
+ qunlock(s);
break;
}
}
@@ 893,10 889,10 @@ tcphangup(Conv *s)
tcb = (Tcpctl*)s->ptcl;
if(waserror()){
- qunlock(tcb);
+ qunlock(s);
return commonerror();
}
- qlock(tcb);
+ qlock(s);
if(s->raddr != 0) {
seg.flags = RST | ACK;
seg.ack = tcb->rcv.nxt;
@@ 911,7 907,7 @@ tcphangup(Conv *s)
}
localclose(s, nil);
poperror();
- qunlock(tcb);
+ qunlock(s);
return nil;
}
@@ 1159,6 1155,8 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
return;
}
+ /* lock protocol while searching for a conversation */
+ qlock(tcp);
/* Look for a connection. failing that look for a listener. */
for(p = tcp->conv; *p; p++) {
@@ 1175,6 1173,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
/* can't send packets to a listener */
tcb = (Tcpctl*)s->ptcl;
if(tcb->state == Listen){
+ qunlock(tcp);
freeblist(bp);
return;
}
@@ 1184,10 1183,13 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
* dump packets with bogus flags
*/
if(seg.flags & RST){
+ qunlock(tcp);
freeblist(bp);
return;
}
+
if(seg.flags & ACK) {
+ qunlock(tcp);
sndrst(tcp, source, dest, length, &seg);
freeblist(bp);
return;
@@ 1223,8 1225,9 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
s = tcpincoming(gen, &seg, source, dest);
}
if(s == nil) {
- freeblist(bp);
+ qunlock(tcp);
sndrst(tcp, source, dest, length, &seg);
+ freeblist(bp);
return;
}
@@ 1233,7 1236,8 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
* Out-of-band data is ignored - it was always a bad idea.
*/
tcb = (Tcpctl*)s->ptcl;
- qlock(tcb);
+ qlock(s);
+ qunlock(tcp);
if(tcb->kacounter > 0)
tcb->kacounter = MAXBACKOFF;
@@ 1283,7 1287,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
else
freeblist(bp);
- qunlock(tcb);
+ qunlock(s);
return;
case Syn_received:
/* doesn't matter if it's the correct ack, we're just trying to set timing */
@@ 1308,7 1312,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
tcb->flags |= FORCE;
goto output;
}
- qunlock(tcb);
+ qunlock(s);
return;
}
@@ 1449,7 1453,7 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
if(bp != nil)
freeblist(bp);
sndrst(tcp, source, dest, length, &seg);
- qunlock(tcb);
+ qunlock(s);
return;
}
}
@@ 1514,10 1518,10 @@ tcpiput(Proto *tcp, uchar*, Block *bp)
}
output:
tcpoutput(s);
- qunlock(tcb);
+ qunlock(s);
return;
raise:
- qunlock(tcb);
+ qunlock(s);
freeblist(bp);
tcpkick(s, 0);
}
@@ 1773,9 1777,9 @@ tcpkeepalive(Conv *s)
if(--(tcb->kacounter) <= 0)
localclose(s, Etimedout);
else {
- qlock(tcb);
+ qlock(s);
tcpsendka(s);
- qunlock(tcb);
+ qunlock(s);
tcpgo(s->p->priv, &tcb->katimer);
}
}
@@ 1810,7 1814,7 @@ tcprxmit(Conv *s)
tpriv = s->p->priv;
tcb = (Tcpctl*)s->ptcl;
- qlock(tcb);
+ qlock(s);
tcb->flags |= RETRAN|FORCE;
tcb->snd.ptr = tcb->snd.una;
@@ 1826,7 1830,7 @@ tcprxmit(Conv *s)
tcpoutput(s);
tpriv->tstats.tcpRetransSegs++;
- qunlock(tcb);
+ qunlock(s);
}
void
@@ 2035,6 2039,7 @@ tcpadvise(Proto *tcp, Block *bp, char *msg)
pdest = nhgets(h->tcpdport);
/* Look for a connection */
+ qlock(tcp);
for(p = tcp->conv; *p; p++) {
s = *p;
tcb = (Tcpctl*)s->ptcl;
@@ 2043,16 2048,19 @@ tcpadvise(Proto *tcp, Block *bp, char *msg)
if(tcb->state != Closed)
if(ipcmp(s->raddr, dest) == 0)
if(ipcmp(s->laddr, source) == 0){
- qlock(tcb);
+ qlock(s);
+ qunlock(tcp);
switch(tcb->state){
case Syn_sent:
localclose(s, msg);
break;
}
- qunlock(tcb);
- break;
+ qunlock(s);
+ freeblist(bp);
+ return;
}
}
+ qunlock(tcp);
freeblist(bp);
}
M ip/udp.c => ip/udp.c +23 -6
@@ 130,7 130,7 @@ udpclose(Conv *c)
ucb = (Udpcb*)c->ptcl;
ucb->headers = 0;
- unlock(c);
+ qunlock(c);
}
void
@@ 270,6 270,8 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
}
}
+ qlock(udp);
+
/* Look for a conversation structure for this port */
c = nil;
for(p = udp->conv; *p; p++) {
@@ 293,6 295,7 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
if(*p == nil) {
upriv->ustats.udpNoPorts++;
+ qunlock(udp);
netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
laddr, lport);
uh->Unused = ottl;
@@ 302,12 305,17 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
return;
}
+ ucb = (Udpcb*)c->ptcl;
+ qlock(c);
+ qunlock(udp);
+
/*
* Trim the packet down to data size
*/
len -= (UDP_HDRSIZE-UDP_PHDRSIZE);
bp = trimblock(bp, UDP_IPHDR+UDP_HDRSIZE, len);
if(bp == nil){
+ qunlock(c);
netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport,
laddr, lport);
upriv->lenerr++;
@@ 317,8 325,6 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport,
laddr, lport, len);
- ucb = (Udpcb*)c->ptcl;
-
switch(ucb->headers){
case 6:
/* pass the src address */
@@ 361,11 367,16 @@ udpiput(Proto *udp, uchar *ia, Block *bp)
bp = concatblock(bp);
if(qfull(c->rq)){
+ qunlock(c);
netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport,
laddr, lport);
freeblist(bp);
- }else
- qpass(c->rq, bp);
+ return;
+ }
+
+ qpass(c->rq, bp);
+ qunlock(c);
+
}
char*
@@ 402,17 413,23 @@ udpadvise(Proto *udp, Block *bp, char *msg)
pdest = nhgets(h->udpdport);
/* Look for a connection */
+ qlock(udp);
for(p = udp->conv; *p; p++) {
s = *p;
if(s->rport == pdest)
if(s->lport == psource)
if(ipcmp(s->raddr, dest) == 0)
if(ipcmp(s->laddr, source) == 0){
+ qlock(s);
+ qunlock(udp);
qhangup(s->rq, msg);
qhangup(s->wq, msg);
- break;
+ qunlock(s);
+ freeblist(bp);
+ return;
}
}
+ qunlock(udp);
freeblist(bp);
}
M port/devssl.c => port/devssl.c +1 -1
@@ 418,7 418,7 @@ qremove(Block **l, int n, int discard)
} else
*l = b->next;
b->next = 0;
- break;
+ return first;
} else if(i > n){
i -= n;
if(discard){
M port/portfns.h => port/portfns.h +1 -0
@@ 26,6 26,7 @@ int canlock(Lock*);
int canpage(Proc*);
int canputc(void*);
int canqlock(QLock*);
+int canrlock(RWlock*);
void chandevinit(void);
void chandevreset(void);
void chanfree(Chan*);
M port/qlock.c => port/qlock.c +16 -0
@@ 196,3 196,19 @@ wunlock(RWlock *q)
q->writer = 0;
unlock(&q->use);
}
+
+/* same as rlock but punts if there are any readers waiting */
+int
+canrlock(RWlock *q)
+{
+ lock(&q->use);
+rwstats.rlock++;
+ if(q->writer == 0 && q->head == nil){
+ /* no writer, go for it */
+ q->readers++;
+ unlock(&q->use);
+ return 1;
+ }
+ unlock(&q->use);
+ return 0;
+}