libtask/qlock.c

143 lines
1.9 KiB
C

#include "taskimpl.h"
/*
* locking
*/
static int
_qlock(QLock *l, int block)
{
if(l->owner == nil){
l->owner = taskrunning;
return 1;
}
if(!block)
return 0;
addtask(&l->waiting, taskrunning);
taskstate("qlock");
taskswitch();
if(l->owner != taskrunning){
fprint(2, "qlock: owner=%p self=%p oops\n", l->owner, taskrunning);
abort();
}
return 1;
}
void
qlock(QLock *l)
{
_qlock(l, 1);
}
int
canqlock(QLock *l)
{
return _qlock(l, 0);
}
void
qunlock(QLock *l)
{
Task *ready;
if(l->owner == 0){
fprint(2, "qunlock: owner=0\n");
abort();
}
if((l->owner = ready = l->waiting.head) != nil){
deltask(&l->waiting, ready);
taskready(ready);
}
}
static int
_rlock(RWLock *l, int block)
{
if(l->writer == nil && l->wwaiting.head == nil){
l->readers++;
return 1;
}
if(!block)
return 0;
addtask(&l->rwaiting, taskrunning);
taskstate("rlock");
taskswitch();
return 1;
}
void
rlock(RWLock *l)
{
_rlock(l, 1);
}
int
canrlock(RWLock *l)
{
return _rlock(l, 0);
}
static int
_wlock(RWLock *l, int block)
{
if(l->writer == nil && l->readers == 0){
l->writer = taskrunning;
return 1;
}
if(!block)
return 0;
addtask(&l->wwaiting, taskrunning);
taskstate("wlock");
taskswitch();
return 1;
}
void
wlock(RWLock *l)
{
_wlock(l, 1);
}
int
canwlock(RWLock *l)
{
return _wlock(l, 0);
}
void
runlock(RWLock *l)
{
Task *t;
if(--l->readers == 0 && (t = l->wwaiting.head) != nil){
deltask(&l->wwaiting, t);
l->writer = t;
taskready(t);
}
}
void
wunlock(RWLock *l)
{
Task *t;
if(l->writer == nil){
fprint(2, "wunlock: not locked\n");
abort();
}
l->writer = nil;
if(l->readers != 0){
fprint(2, "wunlock: readers\n");
abort();
}
while((t = l->rwaiting.head) != nil){
deltask(&l->rwaiting, t);
l->readers++;
taskready(t);
}
if(l->readers == 0 && (t = l->wwaiting.head) != nil){
deltask(&l->wwaiting, t);
l->writer = t;
taskready(t);
}
}