xref: /plan9-contrib/sys/src/boot/vt4/taslock.c (revision da917039c7f233c1a27d212bf012c6afa758af39)
1 #include "include.h"
2 
3 #undef LOCKCYCLES
4 
5 #ifdef LOCKCYCLES
6 uvlong maxlockcycles;
7 uvlong maxilockcycles;
8 ulong maxlockpc;
9 ulong maxilockpc;
10 #endif
11 
12 struct
13 {
14 	ulong	locks;
15 	ulong	glare;
16 	ulong	inglare;
17 } lockstats;
18 
19 static void
inccnt(Ref * r)20 inccnt(Ref *r)
21 {
22 	_xinc(&r->ref);
23 }
24 
25 static int
deccnt(Ref * r)26 deccnt(Ref *r)
27 {
28 	int x;
29 
30 	x = _xdec(&r->ref);
31 	assert(x >= 0);
32 //	if(x < 0)
33 //		panic("deccnt pc=%#p", getcallerpc(&r));
34 	return x;
35 }
36 
37 static void
dumplockmem(char * tag,Lock * l)38 dumplockmem(char *tag, Lock *l)
39 {
40 	uchar *cp;
41 	int i;
42 
43 	iprint("%s: ", tag);
44 	cp = (uchar*)l;
45 	for(i = 0; i < 64; i++)
46 		iprint("%2.2ux ", cp[i]);
47 	iprint("\n");
48 }
49 
50 void
lockloop(Lock * l,uintptr pc)51 lockloop(Lock *l, uintptr pc)
52 {
53 	print("lock %#p loop key %#ux pc %#p\n", l, l->key, pc);
54 }
55 
56 int
lock(Lock * l)57 lock(Lock *l)
58 {
59 	int i;
60 	uintptr pc;
61 
62 	pc = getcallerpc(&l);
63 
64 	lockstats.locks++;
65 	if(TAS(&l->key) == 0){
66 		l->pc = pc;
67 		l->isilock = 0;
68 #ifdef LOCKCYCLES
69 		cycles(&l->lockcycles);
70 #endif
71 		return 0;
72 	}
73 
74 	lockstats.glare++;
75 	for(;;){
76 		lockstats.inglare++;
77 		i = 0;
78 		while(l->key){
79 			if(i++ > 100000000){
80 				i = 0;
81 				lockloop(l, pc);
82 			}
83 		}
84 		if(TAS(&l->key) == 0){
85 			l->pc = pc;
86 			l->isilock = 0;
87 #ifdef LOCKCYCLES
88 			cycles(&l->lockcycles);
89 #endif
90 			return 1;
91 		}
92 	}
93 }
94 
95 void
ilock(Lock * l)96 ilock(Lock *l)
97 {
98 	ulong sr;
99 	uintptr pc;
100 
101 	pc = getcallerpc(&l);
102 	lockstats.locks++;
103 
104 	sr = splhi();
105 	if(TAS(&l->key) != 0){
106 		lockstats.glare++;
107 		/*
108 		 * Cannot also check l->pc and l->m here because
109 		 * they might just not be set yet, or the lock might
110 		 * even have been let go.
111 		 */
112 		if(!l->isilock){
113 			dumplockmem("ilock:", l);
114 			print("corrupt ilock %#p pc=%#p m=%#p isilock=%d",
115 				l, l->pc, l->m, l->isilock);
116 			assert(0);
117 		}
118 		if(l->m == MACHP(m->machno)) {
119 			print("ilock: deadlock on cpu%d pc=%#p lockpc=%#p\n",
120 				m->machno, pc, l->pc);
121 			assert(0);
122 		}
123 		for(;;){
124 			lockstats.inglare++;
125 			splx(sr);
126 			while(l->key)
127 				;
128 			sr = splhi();
129 			if(TAS(&l->key) == 0)
130 				goto acquire;
131 		}
132 	}
133 acquire:
134 //	m->ilockdepth++;
135 	l->sr = sr;
136 	l->pc = pc;
137 	l->isilock = 1;
138 	l->m = MACHP(m->machno);
139 #ifdef LOCKCYCLES
140 	cycles(&l->lockcycles);
141 #endif
142 }
143 
144 int
canlock(Lock * l)145 canlock(Lock *l)
146 {
147 	if(TAS(&l->key))
148 		return 0;
149 
150 	l->pc = getcallerpc(&l);
151 	l->m = MACHP(m->machno);
152 	l->isilock = 0;
153 #ifdef LOCKCYCLES
154 	cycles(&l->lockcycles);
155 #endif
156 	return 1;
157 }
158 
159 void
unlock(Lock * l)160 unlock(Lock *l)
161 {
162 #ifdef LOCKCYCLES
163 	uvlong x;
164 	cycles(&x);
165 	l->lockcycles = x - l->lockcycles;
166 	if(l->lockcycles > maxlockcycles){
167 		maxlockcycles = l->lockcycles;
168 		maxlockpc = l->pc;
169 	}
170 #endif
171 
172 	if(l->key == 0)
173 		print("unlock: not locked: pc %#p\n", getcallerpc(&l));
174 	if(l->isilock)
175 		print("unlock of ilock: pc %#p, held by %#p\n",
176 			getcallerpc(&l), l->pc);
177 	l->m = nil;
178 	l->key = 0;
179 	coherence();
180 }
181 
182 void
iunlock(Lock * l)183 iunlock(Lock *l)
184 {
185 	ulong sr;
186 
187 #ifdef LOCKCYCLES
188 	uvlong x;
189 	cycles(&x);
190 	l->lockcycles = x - l->lockcycles;
191 	if(l->lockcycles > maxilockcycles){
192 		maxilockcycles = l->lockcycles;
193 		maxilockpc = l->pc;
194 	}
195 #endif
196 
197 	if(l->key == 0)
198 		print("iunlock: not locked: pc %#p\n", getcallerpc(&l));
199 	if(!l->isilock)
200 		print("iunlock of lock: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
201 	if(islo())
202 		print("iunlock while lo: pc %#p, held by %#p\n", getcallerpc(&l), l->pc);
203 
204 	sr = l->sr;
205 	l->m = nil;
206 	l->key = 0;
207 	coherence();
208 //	m->ilockdepth--;
209 	splx(sr);
210 }
211