Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_fixcpp/sys/src/ape/lib/ap/plan9/qlock.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#define _LOCK_EXTENSION
2
#define _QLOCK_EXTENSION
3
#define _RESEARCH_SOURCE
4
#include <u.h>
5
#include <lock.h>
6
#include <qlock.h>
7
#include <stdlib.h>
8
#include "sys9.h"
9
 
10
#define rendezvous _RENDEZVOUS
11
#define _rendezvousp rendezvous
12
#define _tas tas
13
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
14
 
15
static struct {
16
	QLp	*p;
17
	QLp	x[1024];
18
} ql = {
19
	ql.x
20
};
21
 
22
enum
23
{
24
	Queuing,
25
	QueuingR,
26
	QueuingW,
27
	Sleeping,
28
};
29
 
30
/* find a free shared memory location to queue ourselves in */
31
static QLp*
32
getqlp(void)
33
{
34
	QLp *p, *op;
35
 
36
	op = ql.p;
37
	for(p = op+1; ; p++){
38
		if(p == &ql.x[nelem(ql.x)])
39
			p = ql.x;
40
		if(p == op)
41
			abort();
42
		if(_tas(&(p->inuse)) == 0){
43
			ql.p = p;
44
			p->next = nil;
45
			break;
46
		}
47
	}
48
	return p;
49
}
50
 
51
void
52
qlock(QLock *q)
53
{
54
	QLp *p, *mp;
55
 
56
	lock(&q->lock);
57
	if(!q->locked){
58
		q->locked = 1;
59
		unlock(&q->lock);
60
		return;
61
	}
62
 
63
 
64
	/* chain into waiting list */
65
	mp = getqlp();
66
	p = q->tail;
67
	if(p == nil)
68
		q->head = mp;
69
	else
70
		p->next = mp;
71
	q->tail = mp;
72
	mp->state = Queuing;
73
	unlock(&q->lock);
74
 
75
	/* wait */
76
	while((*_rendezvousp)((ulong)mp, 1) == ~0)
77
		;
78
	mp->inuse = 0;
79
}
80
 
81
void
82
qunlock(QLock *q)
83
{
84
	QLp *p;
85
 
86
	lock(&q->lock);
87
	p = q->head;
88
	if(p != nil){
89
		/* wakeup head waiting process */
90
		q->head = p->next;
91
		if(q->head == nil)
92
			q->tail = nil;
93
		unlock(&q->lock);
94
		while((*_rendezvousp)((ulong)p, 0x12345) == ~0)
95
			;
96
		return;
97
	}
98
	q->locked = 0;
99
	unlock(&q->lock);
100
}
101
 
102
int
103
canqlock(QLock *q)
104
{
105
	if(!canlock(&q->lock))
106
		return 0;
107
	if(!q->locked){
108
		q->locked = 1;
109
		unlock(&q->lock);
110
		return 1;
111
	}
112
	unlock(&q->lock);
113
	return 0;
114
}
115
 
116
#if 0
117
 
118
void
119
rlock(RWLock *q)
120
{
121
	QLp *p, *mp;
122
 
123
	lock(&q->lock);
124
	if(q->writer == 0 && q->head == nil){
125
		/* no writer, go for it */
126
		q->readers++;
127
		unlock(&q->lock);
128
		return;
129
	}
130
 
131
	mp = getqlp();
132
	p = q->tail;
133
	if(p == 0)
134
		q->head = mp;
135
	else
136
		p->next = mp;
137
	q->tail = mp;
138
	mp->next = nil;
139
	mp->state = QueuingR;
140
	unlock(&q->lock);
141
 
142
	/* wait in kernel */
143
	while((*_rendezvousp)((ulong)mp, 1) == ~0)
144
		;
145
	mp->inuse = 0;
146
}
147
 
148
int
149
canrlock(RWLock *q)
150
{
151
	lock(&q->lock);
152
	if (q->writer == 0 && q->head == nil) {
153
		/* no writer; go for it */
154
		q->readers++;
155
		unlock(&q->lock);
156
		return 1;
157
	}
158
	unlock(&q->lock);
159
	return 0;
160
}
161
 
162
void
163
runlock(RWLock *q)
164
{
165
	QLp *p;
166
 
167
	lock(&q->lock);
168
	if(q->readers <= 0)
169
		abort();
170
	p = q->head;
171
	if(--(q->readers) > 0 || p == nil){
172
		unlock(&q->lock);
173
		return;
174
	}
175
 
176
	/* start waiting writer */
177
	if(p->state != QueuingW)
178
		abort();
179
	q->head = p->next;
180
	if(q->head == 0)
181
		q->tail = 0;
182
	q->writer = 1;
183
	unlock(&q->lock);
184
 
185
	/* wakeup waiter */
186
	while((*_rendezvousp)((ulong)p, 0) == ~0)
187
		;
188
}
189
 
190
void
191
wlock(RWLock *q)
192
{
193
	QLp *p, *mp;
194
 
195
	lock(&q->lock);
196
	if(q->readers == 0 && q->writer == 0){
197
		/* noone waiting, go for it */
198
		q->writer = 1;
199
		unlock(&q->lock);
200
		return;
201
	}
202
 
203
	/* wait */
204
	p = q->tail;
205
	mp = getqlp();
206
	if(p == nil)
207
		q->head = mp;
208
	else
209
		p->next = mp;
210
	q->tail = mp;
211
	mp->next = nil;
212
	mp->state = QueuingW;
213
	unlock(&q->lock);
214
 
215
	/* wait in kernel */
216
	while((*_rendezvousp)((ulong)mp, 1) == ~0)
217
		;
218
	mp->inuse = 0;
219
}
220
 
221
int
222
canwlock(RWLock *q)
223
{
224
	lock(&q->lock);
225
	if (q->readers == 0 && q->writer == 0) {
226
		/* no one waiting; go for it */
227
		q->writer = 1;
228
		unlock(&q->lock);
229
		return 1;
230
	}
231
	unlock(&q->lock);
232
	return 0;
233
}
234
 
235
void
236
wunlock(RWLock *q)
237
{
238
	QLp *p;
239
 
240
	lock(&q->lock);
241
	if(q->writer == 0)
242
		abort();
243
	p = q->head;
244
	if(p == nil){
245
		q->writer = 0;
246
		unlock(&q->lock);
247
		return;
248
	}
249
	if(p->state == QueuingW){
250
		/* start waiting writer */
251
		q->head = p->next;
252
		if(q->head == nil)
253
			q->tail = nil;
254
		unlock(&q->lock);
255
		while((*_rendezvousp)((ulong)p, 0) == ~0)
256
			;
257
		return;
258
	}
259
 
260
	if(p->state != QueuingR)
261
		abort();
262
 
263
	/* wake waiting readers */
264
	while(q->head != nil && q->head->state == QueuingR){
265
		p = q->head;
266
		q->head = p->next;
267
		q->readers++;
268
		while((*_rendezvousp)((ulong)p, 0) == ~0)
269
			;
270
	}
271
	if(q->head == nil)
272
		q->tail = nil;
273
	q->writer = 0;
274
	unlock(&q->lock);
275
}
276
 
277
void
278
rsleep(Rendez *r)
279
{
280
	QLp *t, *me;
281
 
282
	if(!r->l)
283
		abort();
284
	lock(&r->l->lock);
285
	/* we should hold the qlock */
286
	if(!r->l->locked)
287
		abort();
288
 
289
	/* add ourselves to the wait list */
290
	me = getqlp();
291
	me->state = Sleeping;
292
	if(r->head == nil)
293
		r->head = me;
294
	else
295
		r->tail->next = me;
296
	me->next = nil;
297
	r->tail = me;
298
 
299
	/* pass the qlock to the next guy */
300
	t = r->l->head;
301
	if(t){
302
		r->l->head = t->next;
303
		if(r->l->head == nil)
304
			r->l->tail = nil;
305
		unlock(&r->l->lock);
306
		while((*_rendezvousp)((ulong)t, 0x12345) == ~0)
307
			;
308
	}else{
309
		r->l->locked = 0;
310
		unlock(&r->l->lock);
311
	}
312
 
313
	/* wait for a wakeup */
314
	while((*_rendezvousp)((ulong)me, 1) == ~0)
315
		;
316
	me->inuse = 0;
317
}
318
 
319
int
320
rwakeup(Rendez *r)
321
{
322
	QLp *t;
323
 
324
	/*
325
	 * take off wait and put on front of queue
326
	 * put on front so guys that have been waiting will not get starved
327
	 */
328
 
329
	if(!r->l)
330
		abort();
331
	lock(&r->l->lock);
332
	if(!r->l->locked)
333
		abort();
334
 
335
	t = r->head;
336
	if(t == nil){
337
		unlock(&r->l->lock);
338
		return 0;
339
	}
340
 
341
	r->head = t->next;
342
	if(r->head == nil)
343
		r->tail = nil;
344
 
345
	t->next = r->l->head;
346
	r->l->head = t;
347
	if(r->l->tail == nil)
348
		r->l->tail = t;
349
 
350
	t->state = Queuing;
351
	unlock(&r->l->lock);
352
	return 1;
353
}
354
 
355
int
356
rwakeupall(Rendez *r)
357
{
358
	int i;
359
 
360
	for(i=0; rwakeup(r); i++)
361
		;
362
	return i;
363
}
364
 
365
#endif