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