#include <u.h>#include <libc.h> static struct { QLp *p; QLp x[1024];} ql = { ql.x}; enum{ Queuing, QueuingR, QueuingW,}; static ulong (*_rendezvousp)(ulong, ulong) = rendezvous; /* this gets called by the thread library ONLY to get us to use its rendezvous */void_qlockinit(ulong (*r)(ulong, ulong)){ _rendezvousp = r;} /* find a free shared memory location to queue ourselves in */static QLp*getqlp(void){ QLp *p, *op; op = ql.p; for(p = op+1; ; p++){ if(p == &ql.x[nelem(ql.x)]) p = ql.x; if(p == op) abort(); if(_tas(&(p->inuse)) == 0){ ql.p = p; p->next = nil; break; } } return p;} voidqlock(QLock *q){ QLp *p, *mp; lock(&q->lock); if(!q->locked){ q->locked = 1; unlock(&q->lock); return; } /* chain into waiting list */ mp = getqlp(); p = q->tail; if(p == nil) q->head = mp; else p->next = mp; q->tail = mp; mp->state = Queuing; unlock(&q->lock); /* wait */ while((*_rendezvousp)((ulong)mp, 1) == ~0) ; mp->inuse = 0;} voidqunlock(QLock *q){ QLp *p; lock(&q->lock); p = q->head; if(p != nil){ /* wakeup head waiting process */ q->head = p->next; if(q->head == nil) q->tail = nil; unlock(&q->lock); while((*_rendezvousp)((ulong)p, 0x12345) == ~0) ; return; } q->locked = 0; unlock(&q->lock);} intcanqlock(QLock *q){ lock(&q->lock); if(!q->locked){ q->locked = 1; unlock(&q->lock); return 1; } unlock(&q->lock); return 0;} voidrlock(RWLock *q){ QLp *p, *mp; lock(&q->lock); if(q->writer == 0 && q->head == nil){ /* no writer, go for it */ q->readers++; unlock(&q->lock); return; } mp = getqlp(); p = q->tail; if(p == 0) q->head = mp; else p->next = mp; q->tail = mp; mp->next = nil; mp->state = QueuingR; unlock(&q->lock); /* wait in kernel */ while((*_rendezvousp)((ulong)mp, 1) == ~0) ; mp->inuse = 0;} intcanrlock(RWLock *q){ lock(&q->lock); if (q->writer == 0 && q->head == nil) { /* no writer; go for it */ q->readers++; unlock(&q->lock); return 1; } unlock(&q->lock); return 0;} voidrunlock(RWLock *q){ QLp *p; lock(&q->lock); if(q->readers <= 0) abort(); p = q->head; if(--(q->readers) > 0 || p == nil){ unlock(&q->lock); return; } /* start waiting writer */ if(p->state != QueuingW) abort(); q->head = p->next; if(q->head == 0) q->tail = 0; q->writer = 1; unlock(&q->lock); /* wakeup waiter */ while((*_rendezvousp)((ulong)p, 0) == ~0) ;} voidwlock(RWLock *q){ QLp *p, *mp; lock(&q->lock); if(q->readers == 0 && q->writer == 0){ /* noone waiting, go for it */ q->writer = 1; unlock(&q->lock); return; } /* wait */ p = q->tail; mp = getqlp(); if(p == nil) q->head = mp; else p->next = mp; q->tail = mp; mp->next = nil; mp->state = QueuingW; unlock(&q->lock); /* wait in kernel */ while((*_rendezvousp)((ulong)mp, 1) == ~0) ; mp->inuse = 0;} intcanwlock(RWLock *q){ lock(&q->lock); if (q->readers == 0 && q->writer == 0) { /* no one waiting; go for it */ q->writer = 1; unlock(&q->lock); return 1; } unlock(&q->lock); return 0;} voidwunlock(RWLock *q){ QLp *p; lock(&q->lock); if(q->writer == 0) abort(); p = q->head; if(p == nil){ q->writer = 0; unlock(&q->lock); return; } if(p->state == QueuingW){ /* start waiting writer */ q->head = p->next; if(q->head == nil) q->tail = nil; unlock(&q->lock); while((*_rendezvousp)((ulong)p, 0) == ~0) ; return; } if(p->state != QueuingR) abort(); /* wake waiting readers */ while(q->head != nil && q->head->state == QueuingR){ p = q->head; q->head = p->next; q->readers++; while((*_rendezvousp)((ulong)p, 0) == ~0) ; } if(q->head == nil) q->tail = nil; q->writer = 0; unlock(&q->lock);}
#include <u.h>
#include <libc.h>
static struct {
QLp *p;
QLp x[1024];
} ql = {
ql.x
};
enum
{
Queuing,
QueuingR,
QueuingW,
};
static ulong (*_rendezvousp)(ulong, ulong) = rendezvous;
/* this gets called by the thread library ONLY to get us to use its rendezvous */
void
_qlockinit(ulong (*r)(ulong, ulong))
{
_rendezvousp = r;
}
/* find a free shared memory location to queue ourselves in */
static QLp*
getqlp(void)
{
QLp *p, *op;
op = ql.p;
for(p = op+1; ; p++){
if(p == &ql.x[nelem(ql.x)])
p = ql.x;
if(p == op)
abort();
if(_tas(&(p->inuse)) == 0){
ql.p = p;
p->next = nil;
break;
}
}
return p;
}
void
qlock(QLock *q)
{
QLp *p, *mp;
lock(&q->lock);
if(!q->locked){
q->locked = 1;
unlock(&q->lock);
return;
}
/* chain into waiting list */
mp = getqlp();
p = q->tail;
if(p == nil)
q->head = mp;
else
p->next = mp;
q->tail = mp;
mp->state = Queuing;
unlock(&q->lock);
/* wait */
while((*_rendezvousp)((ulong)mp, 1) == ~0)
;
mp->inuse = 0;
}
void
qunlock(QLock *q)
{
QLp *p;
lock(&q->lock);
p = q->head;
if(p != nil){
/* wakeup head waiting process */
q->head = p->next;
if(q->head == nil)
q->tail = nil;
unlock(&q->lock);
while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
;
return;
}
q->locked = 0;
unlock(&q->lock);
}
int
canqlock(QLock *q)
{
lock(&q->lock);
if(!q->locked){
q->locked = 1;
unlock(&q->lock);
return 1;
}
unlock(&q->lock);
return 0;
}
void
rlock(RWLock *q)
{
QLp *p, *mp;
lock(&q->lock);
if(q->writer == 0 && q->head == nil){
/* no writer, go for it */
q->readers++;
unlock(&q->lock);
return;
}
mp = getqlp();
p = q->tail;
if(p == 0)
q->head = mp;
else
p->next = mp;
q->tail = mp;
mp->next = nil;
mp->state = QueuingR;
unlock(&q->lock);
/* wait in kernel */
while((*_rendezvousp)((ulong)mp, 1) == ~0)
;
mp->inuse = 0;
}
int
canrlock(RWLock *q)
{
lock(&q->lock);
if (q->writer == 0 && q->head == nil) {
/* no writer; go for it */
q->readers++;
unlock(&q->lock);
return 1;
}
unlock(&q->lock);
return 0;
}
void
runlock(RWLock *q)
{
QLp *p;
lock(&q->lock);
if(q->readers <= 0)
abort();
p = q->head;
if(--(q->readers) > 0 || p == nil){
unlock(&q->lock);
return;
}
/* start waiting writer */
if(p->state != QueuingW)
abort();
q->head = p->next;
if(q->head == 0)
q->tail = 0;
q->writer = 1;
unlock(&q->lock);
/* wakeup waiter */
while((*_rendezvousp)((ulong)p, 0) == ~0)
;
}
void
wlock(RWLock *q)
{
QLp *p, *mp;
lock(&q->lock);
if(q->readers == 0 && q->writer == 0){
/* noone waiting, go for it */
q->writer = 1;
unlock(&q->lock);
return;
}
/* wait */
p = q->tail;
mp = getqlp();
if(p == nil)
q->head = mp;
else
p->next = mp;
q->tail = mp;
mp->next = nil;
mp->state = QueuingW;
unlock(&q->lock);
/* wait in kernel */
while((*_rendezvousp)((ulong)mp, 1) == ~0)
;
mp->inuse = 0;
}
int
canwlock(RWLock *q)
{
lock(&q->lock);
if (q->readers == 0 && q->writer == 0) {
/* no one waiting; go for it */
q->writer = 1;
unlock(&q->lock);
return 1;
}
unlock(&q->lock);
return 0;
}
void
wunlock(RWLock *q)
{
QLp *p;
lock(&q->lock);
if(q->writer == 0)
abort();
p = q->head;
if(p == nil){
q->writer = 0;
unlock(&q->lock);
return;
}
if(p->state == QueuingW){
/* start waiting writer */
q->head = p->next;
if(q->head == nil)
q->tail = nil;
unlock(&q->lock);
while((*_rendezvousp)((ulong)p, 0) == ~0)
;
return;
}
if(p->state != QueuingR)
abort();
/* wake waiting readers */
while(q->head != nil && q->head->state == QueuingR){
p = q->head;
q->head = p->next;
q->readers++;
while((*_rendezvousp)((ulong)p, 0) == ~0)
;
}
if(q->head == nil)
q->tail = nil;
q->writer = 0;
unlock(&q->lock);
}