126 lines
1.8 KiB
C
126 lines
1.8 KiB
C
#include "stdinc.h"
|
|
|
|
#include "9.h"
|
|
|
|
static struct {
|
|
QLock lock;
|
|
|
|
Excl* head;
|
|
Excl* tail;
|
|
} ebox;
|
|
|
|
struct Excl {
|
|
Fsys* fsys;
|
|
uvlong path;
|
|
ulong time;
|
|
|
|
Excl* next;
|
|
Excl* prev;
|
|
};
|
|
|
|
enum {
|
|
LifeTime = (5*60),
|
|
};
|
|
|
|
int
|
|
exclAlloc(Fid* fid)
|
|
{
|
|
ulong t;
|
|
Excl *excl;
|
|
|
|
assert(fid->excl == nil);
|
|
|
|
t = time(0L);
|
|
qlock(&ebox.lock);
|
|
for(excl = ebox.head; excl != nil; excl = excl->next){
|
|
if(excl->fsys != fid->fsys || excl->path != fid->qid.path)
|
|
continue;
|
|
/*
|
|
* Found it.
|
|
* Now, check if it's timed out.
|
|
* If not, return error, it's locked.
|
|
* If it has timed out, zap the old
|
|
* one and continue on to allocate a
|
|
* a new one.
|
|
*/
|
|
if(excl->time >= t){
|
|
qunlock(&ebox.lock);
|
|
werrstr("exclusive lock");
|
|
return 0;
|
|
}
|
|
excl->fsys = nil;
|
|
}
|
|
|
|
/*
|
|
* Not found or timed-out.
|
|
* Alloc a new one and initialise.
|
|
*/
|
|
excl = vtmallocz(sizeof(Excl));
|
|
excl->fsys = fid->fsys;
|
|
excl->path = fid->qid.path;
|
|
excl->time = t+LifeTime;
|
|
if(ebox.tail != nil){
|
|
excl->prev = ebox.tail;
|
|
ebox.tail->next = excl;
|
|
}
|
|
else{
|
|
ebox.head = excl;
|
|
excl->prev = nil;
|
|
}
|
|
ebox.tail = excl;
|
|
excl->next = nil;
|
|
qunlock(&ebox.lock);
|
|
|
|
fid->excl = excl;
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
exclUpdate(Fid* fid)
|
|
{
|
|
ulong t;
|
|
Excl *excl;
|
|
|
|
excl = fid->excl;
|
|
|
|
t = time(0L);
|
|
qlock(&ebox.lock);
|
|
if(excl->time < t || excl->fsys != fid->fsys){
|
|
qunlock(&ebox.lock);
|
|
werrstr("exclusive lock broken");
|
|
return 0;
|
|
}
|
|
excl->time = t+LifeTime;
|
|
qunlock(&ebox.lock);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
exclFree(Fid* fid)
|
|
{
|
|
Excl *excl;
|
|
|
|
if((excl = fid->excl) == nil)
|
|
return;
|
|
fid->excl = nil;
|
|
|
|
qlock(&ebox.lock);
|
|
if(excl->prev != nil)
|
|
excl->prev->next = excl->next;
|
|
else
|
|
ebox.head = excl->next;
|
|
if(excl->next != nil)
|
|
excl->next->prev = excl->prev;
|
|
else
|
|
ebox.tail = excl->prev;
|
|
qunlock(&ebox.lock);
|
|
|
|
vtfree(excl);
|
|
}
|
|
|
|
void
|
|
exclInit(void)
|
|
{
|
|
}
|