blob: 6fce280ace14311e10736d69e24380046c3868a3 [file] [log] [blame]
#include "stdinc.h"
#include "9.h"
static struct {
VtLock* 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);
vtLock(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){
vtUnlock(ebox.lock);
vtSetError("exclusive lock");
return 0;
}
excl->fsys = nil;
}
/*
* Not found or timed-out.
* Alloc a new one and initialise.
*/
excl = vtMemAllocZ(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;
vtUnlock(ebox.lock);
fid->excl = excl;
return 1;
}
int
exclUpdate(Fid* fid)
{
ulong t;
Excl *excl;
excl = fid->excl;
t = time(0L);
vtLock(ebox.lock);
if(excl->time < t || excl->fsys != fid->fsys){
vtUnlock(ebox.lock);
vtSetError("exclusive lock broken");
return 0;
}
excl->time = t+LifeTime;
vtUnlock(ebox.lock);
return 1;
}
void
exclFree(Fid* fid)
{
Excl *excl;
if((excl = fid->excl) == nil)
return;
fid->excl = nil;
vtLock(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;
vtUnlock(ebox.lock);
vtMemFree(excl);
}
void
exclInit(void)
{
ebox.lock = vtLockAlloc();
}