blob: 9cefe58f059481c415c47803eac919ded6066a95 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#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)
{
}
|