mirror of
https://github.com/0intro/libtask
synced 2024-12-22 19:16:55 +03:00
143 lines
1.9 KiB
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);
|
|
}
|
|
}
|