xref: /inferno-os/lib9/lock.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1 #include	"dat.h"
2 #include	"fns.h"
3 #include	"error.h"
4 
5 void
lock(Lock * l)6 lock(Lock *l)
7 {
8 	int i;
9 
10 	if(_tas(&l->val) == 0)
11 		return;
12 	for(i=0; i<100; i++){
13 		if(_tas(&l->val) == 0)
14 			return;
15 		osyield();
16 	}
17 	for(i=1;; i++){
18 		if(_tas(&l->val) == 0)
19 			return;
20 		osmillisleep(i*10);
21 		if(i > 100){
22 			osyield();
23 			i = 1;
24 		}
25 	}
26 }
27 
28 int
canlock(Lock * l)29 canlock(Lock *l)
30 {
31 	return _tas(&l->val) == 0;
32 }
33 
34 void
unlock(Lock * l)35 unlock(Lock *l)
36 {
37 	l->val = 0;
38 }
39 
40 void
qlock(QLock * q)41 qlock(QLock *q)
42 {
43 	Proc *p;
44 
45 	lock(&q->use);
46 	if(!q->locked) {
47 		q->locked = 1;
48 		unlock(&q->use);
49 		return;
50 	}
51 	p = q->tail;
52 	if(p == 0)
53 		q->head = up;
54 	else
55 		p->qnext = up;
56 	q->tail = up;
57 	up->qnext = 0;
58 	unlock(&q->use);
59 	osblock();
60 }
61 
62 int
canqlock(QLock * q)63 canqlock(QLock *q)
64 {
65 	if(!canlock(&q->use))
66 		return 0;
67 	if(q->locked){
68 		unlock(&q->use);
69 		return 0;
70 	}
71 	q->locked = 1;
72 	unlock(&q->use);
73 	return 1;
74 }
75 
76 void
qunlock(QLock * q)77 qunlock(QLock *q)
78 {
79 	Proc *p;
80 
81 	lock(&q->use);
82 	p = q->head;
83 	if(p) {
84 		q->head = p->qnext;
85 		if(q->head == 0)
86 			q->tail = 0;
87 		unlock(&q->use);
88 		osready(p);
89 		return;
90 	}
91 	q->locked = 0;
92 	unlock(&q->use);
93 }
94 
95 void
rlock(RWlock * l)96 rlock(RWlock *l)
97 {
98 	qlock(&l->x);		/* wait here for writers and exclusion */
99 	lock(&l->l);
100 	l->readers++;
101 	canqlock(&l->k);	/* block writers if we are the first reader */
102 	unlock(&l->l);
103 	qunlock(&l->x);
104 }
105 
106 /* same as rlock but punts if there are any writers waiting */
107 int
canrlock(RWlock * l)108 canrlock(RWlock *l)
109 {
110 	if (!canqlock(&l->x))
111 		return 0;
112 	lock(&l->l);
113 	l->readers++;
114 	canqlock(&l->k);	/* block writers if we are the first reader */
115 	unlock(&l->l);
116 	qunlock(&l->x);
117 	return 1;
118 }
119 
120 void
runlock(RWlock * l)121 runlock(RWlock *l)
122 {
123 	lock(&l->l);
124 	if(--l->readers == 0)	/* last reader out allows writers */
125 		qunlock(&l->k);
126 	unlock(&l->l);
127 }
128 
129 void
wlock(RWlock * l)130 wlock(RWlock *l)
131 {
132 	qlock(&l->x);		/* wait here for writers and exclusion */
133 	qlock(&l->k);		/* wait here for last reader */
134 }
135 
136 void
wunlock(RWlock * l)137 wunlock(RWlock *l)
138 {
139 	qunlock(&l->k);
140 	qunlock(&l->x);
141 }
142