xref: /inferno-os/os/port/qlock.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 
7 void
qlock(QLock * q)8 qlock(QLock *q)
9 {
10 	Proc *p, *mp;
11 
12 	lock(&q->use);
13 	if(!q->locked) {
14 		q->locked = 1;
15 		unlock(&q->use);
16 		return;
17 	}
18 	p = q->tail;
19 	mp = up;
20 	if(p == 0)
21 		q->head = mp;
22 	else
23 		p->qnext = mp;
24 	q->tail = mp;
25 	mp->qnext = 0;
26 	mp->state = Queueing;
27 	up->qpc = getcallerpc(&q);
28 	unlock(&q->use);
29 	sched();
30 }
31 
32 int
canqlock(QLock * q)33 canqlock(QLock *q)
34 {
35 	if(!canlock(&q->use))
36 		return 0;
37 	if(q->locked){
38 		unlock(&q->use);
39 		return 0;
40 	}
41 	q->locked = 1;
42 	unlock(&q->use);
43 	return 1;
44 }
45 
46 void
qunlock(QLock * q)47 qunlock(QLock *q)
48 {
49 	Proc *p;
50 
51 	lock(&q->use);
52 	p = q->head;
53 	if(p) {
54 		q->head = p->qnext;
55 		if(q->head == 0)
56 			q->tail = 0;
57 		unlock(&q->use);
58 		ready(p);
59 		return;
60 	}
61 	q->locked = 0;
62 	unlock(&q->use);
63 }
64 
65 void
rlock(RWlock * l)66 rlock(RWlock *l)
67 {
68 	qlock(&l->x);		/* wait here for writers and exclusion */
69 	lock(l);
70 	l->readers++;
71 	canqlock(&l->k);	/* block writers if we are the first reader */
72 	unlock(l);
73 	qunlock(&l->x);
74 }
75 
76 /* same as rlock but punts if there are any writers waiting */
77 int
canrlock(RWlock * l)78 canrlock(RWlock *l)
79 {
80 	if (!canqlock(&l->x))
81 		return 0;
82 	lock(l);
83 	l->readers++;
84 	canqlock(&l->k);	/* block writers if we are the first reader */
85 	unlock(l);
86 	qunlock(&l->x);
87 	return 1;
88 }
89 
90 void
runlock(RWlock * l)91 runlock(RWlock *l)
92 {
93 	lock(l);
94 	if(--l->readers == 0)	/* last reader out allows writers */
95 		qunlock(&l->k);
96 	unlock(l);
97 }
98 
99 void
wlock(RWlock * l)100 wlock(RWlock *l)
101 {
102 	qlock(&l->x);		/* wait here for writers and exclusion */
103 	qlock(&l->k);		/* wait here for last reader */
104 }
105 
106 void
wunlock(RWlock * l)107 wunlock(RWlock *l)
108 {
109 	qunlock(&l->k);
110 	qunlock(&l->x);
111 }
112