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 "u.h"
2
#include "../port/lib.h"
3
#include "mem.h"
4
#include "dat.h"
5
#include "fns.h"
6
 
7
struct {
8
	ulong rlock;
9
	ulong rlockq;
10
	ulong wlock;
11
	ulong wlockq;
12
	ulong qlock;
13
	ulong qlockq;
14
} rwstats;
15
 
16
void
17
qlock(QLock *q)
18
{
19
	Proc *p;
20
 
21
	if(m->ilockdepth != 0)
22
		print("qlock: %#p: ilockdepth %d\n", getcallerpc(&q), m->ilockdepth);
23
	if(up != nil && up->nlocks.ref)
24
		print("qlock: %#p: nlocks %lud\n", getcallerpc(&q), up->nlocks.ref);
25
 
26
	if(q->use.key == 0x55555555)
27
		panic("qlock: q %#p, key 5*\n", q);
28
	lock(&q->use);
29
	rwstats.qlock++;
30
	if(!q->locked) {
31
		q->locked = 1;
32
		q->qpc = getcallerpc(&q);
33
		unlock(&q->use);
34
		return;
35
	}
36
	if(up == 0)
37
		panic("qlock");
38
	rwstats.qlockq++;
39
	p = q->tail;
40
	if(p == 0)
41
		q->head = up;
42
	else
43
		p->qnext = up;
44
	q->tail = up;
45
	up->qnext = 0;
46
	up->state = Queueing;
47
	up->qpc = getcallerpc(&q);
48
	unlock(&q->use);
49
	sched();
50
	q->qpc = getcallerpc(&q);
51
}
52
 
53
int
54
canqlock(QLock *q)
55
{
56
	if(!canlock(&q->use))
57
		return 0;
58
	if(q->locked){
59
		unlock(&q->use);
60
		return 0;
61
	}
62
	q->locked = 1;
63
	q->qpc = getcallerpc(&q);
64
	unlock(&q->use);
65
	return 1;
66
}
67
 
68
void
69
qunlock(QLock *q)
70
{
71
	Proc *p;
72
 
73
	lock(&q->use);
74
	if (q->locked == 0)
75
		print("qunlock called with qlock not held, from %#p\n",
76
			getcallerpc(&q));
77
	p = q->head;
78
	if(p){
79
		q->head = p->qnext;
80
		if(q->head == 0)
81
			q->tail = 0;
82
		unlock(&q->use);
83
		ready(p);
84
		return;
85
	}
86
	q->locked = 0;
87
	q->qpc = 0;
88
	unlock(&q->use);
89
}
90
 
91
void
92
rlock(RWlock *q)
93
{
94
	Proc *p;
95
 
96
	lock(&q->use);
97
	rwstats.rlock++;
98
	if(q->writer == 0 && q->head == nil){
99
		/* no writer, go for it */
100
		q->readers++;
101
		unlock(&q->use);
102
		return;
103
	}
104
 
105
	rwstats.rlockq++;
106
	p = q->tail;
107
	if(up == nil)
108
		panic("rlock");
109
	if(p == 0)
110
		q->head = up;
111
	else
112
		p->qnext = up;
113
	q->tail = up;
114
	up->qnext = 0;
115
	up->state = QueueingR;
116
	unlock(&q->use);
117
	sched();
118
}
119
 
120
void
121
runlock(RWlock *q)
122
{
123
	Proc *p;
124
 
125
	lock(&q->use);
126
	p = q->head;
127
	if(--(q->readers) > 0 || p == nil){
128
		unlock(&q->use);
129
		return;
130
	}
131
 
132
	/* start waiting writer */
133
	if(p->state != QueueingW)
134
		panic("runlock");
135
	q->head = p->qnext;
136
	if(q->head == 0)
137
		q->tail = 0;
138
	q->writer = 1;
139
	unlock(&q->use);
140
	ready(p);
141
}
142
 
143
void
144
wlock(RWlock *q)
145
{
146
	Proc *p;
147
 
148
	lock(&q->use);
149
	rwstats.wlock++;
150
	if(q->readers == 0 && q->writer == 0){
151
		/* noone waiting, go for it */
152
		q->wpc = getcallerpc(&q);
153
		q->wproc = up;
154
		q->writer = 1;
155
		unlock(&q->use);
156
		return;
157
	}
158
 
159
	/* wait */
160
	rwstats.wlockq++;
161
	p = q->tail;
162
	if(up == nil)
163
		panic("wlock");
164
	if(p == nil)
165
		q->head = up;
166
	else
167
		p->qnext = up;
168
	q->tail = up;
169
	up->qnext = 0;
170
	up->state = QueueingW;
171
	unlock(&q->use);
172
	sched();
173
}
174
 
175
void
176
wunlock(RWlock *q)
177
{
178
	Proc *p;
179
 
180
	lock(&q->use);
181
	p = q->head;
182
	if(p == nil){
183
		q->writer = 0;
184
		unlock(&q->use);
185
		return;
186
	}
187
	if(p->state == QueueingW){
188
		/* start waiting writer */
189
		q->head = p->qnext;
190
		if(q->head == nil)
191
			q->tail = nil;
192
		unlock(&q->use);
193
		ready(p);
194
		return;
195
	}
196
 
197
	if(p->state != QueueingR)
198
		panic("wunlock");
199
 
200
	/* waken waiting readers */
201
	while(q->head != nil && q->head->state == QueueingR){
202
		p = q->head;
203
		q->head = p->qnext;
204
		q->readers++;
205
		ready(p);
206
	}
207
	if(q->head == nil)
208
		q->tail = nil;
209
	q->writer = 0;
210
	unlock(&q->use);
211
}
212
 
213
/* same as rlock but punts if there are any writers waiting */
214
int
215
canrlock(RWlock *q)
216
{
217
	lock(&q->use);
218
	rwstats.rlock++;
219
	if(q->writer == 0 && q->head == nil){
220
		/* no writer, go for it */
221
		q->readers++;
222
		unlock(&q->use);
223
		return 1;
224
	}
225
	unlock(&q->use);
226
	return 0;
227
}