Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "stdinc.h"
2
 
3
#include "9.h"
4
 
5
static struct {
6
	VtLock*	lock;
7
 
8
	Excl*	head;
9
	Excl*	tail;
10
} ebox;
11
 
12
struct Excl {
13
	Fsys*	fsys;
14
	uvlong	path;
15
	ulong	time;
16
 
17
	Excl*	next;
18
	Excl*	prev;
19
};
20
 
21
enum {
22
	LifeTime	= (5*60),
23
};
24
 
25
int
26
exclAlloc(Fid* fid)
27
{
28
	ulong t;
29
	Excl *excl;
30
 
31
	assert(fid->excl == nil);
32
 
33
	t = time(0L);
34
	vtLock(ebox.lock);
35
	for(excl = ebox.head; excl != nil; excl = excl->next){
36
		if(excl->fsys != fid->fsys || excl->path != fid->qid.path)
37
			continue;
38
		/*
39
		 * Found it.
40
		 * Now, check if it's timed out.
41
		 * If not, return error, it's locked.
42
		 * If it has timed out, zap the old
43
		 * one and continue on to allocate a
44
		 * a new one.
45
		 */
46
		if(excl->time >= t){
47
			vtUnlock(ebox.lock);
48
			vtSetError("exclusive lock");
49
			return 0;
50
		}
51
		excl->fsys = nil;
52
	}
53
 
54
	/*
55
	 * Not found or timed-out.
56
	 * Alloc a new one and initialise.
57
	 */
58
	excl = vtMemAllocZ(sizeof(Excl));
59
	excl->fsys = fid->fsys;
60
	excl->path = fid->qid.path;
61
	excl->time = t+LifeTime;
62
	if(ebox.tail != nil){
63
		excl->prev = ebox.tail;
64
		ebox.tail->next = excl;
65
	}
66
	else{
67
		ebox.head = excl;
68
		excl->prev = nil;
69
	}
70
	ebox.tail = excl;
71
	excl->next = nil;
72
	vtUnlock(ebox.lock);
73
 
74
	fid->excl = excl;
75
	return 1;
76
}
77
 
78
int
79
exclUpdate(Fid* fid)
80
{
81
	ulong t;
82
	Excl *excl;
83
 
84
	excl = fid->excl;
85
 
86
	t = time(0L);
87
	vtLock(ebox.lock);
88
	if(excl->time < t || excl->fsys != fid->fsys){
89
		vtUnlock(ebox.lock);
90
		vtSetError("exclusive lock broken");
91
		return 0;
92
	}
93
	excl->time = t+LifeTime;
94
	vtUnlock(ebox.lock);
95
 
96
	return 1;
97
}
98
 
99
void
100
exclFree(Fid* fid)
101
{
102
	Excl *excl;
103
 
104
	if((excl = fid->excl) == nil)
105
		return;
106
	fid->excl = nil;
107
 
108
	vtLock(ebox.lock);
109
	if(excl->prev != nil)
110
		excl->prev->next = excl->next;
111
	else
112
		ebox.head = excl->next;
113
	if(excl->next != nil)
114
		excl->next->prev = excl->prev;
115
	else
116
		ebox.tail = excl->prev;
117
	vtUnlock(ebox.lock);
118
 
119
	vtMemFree(excl);
120
}
121
 
122
void
123
exclInit(void)
124
{
125
	ebox.lock = vtLockAlloc();
126
}