diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/sparc64/lib/debuglocks.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/sparc64/lib/debuglocks.c')
-rw-r--r-- | arch/sparc64/lib/debuglocks.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c new file mode 100644 index 000000000000..c421e0c65325 --- /dev/null +++ b/arch/sparc64/lib/debuglocks.c | |||
@@ -0,0 +1,376 @@ | |||
1 | /* $Id: debuglocks.c,v 1.9 2001/11/17 00:10:48 davem Exp $ | ||
2 | * debuglocks.c: Debugging versions of SMP locking primitives. | ||
3 | * | ||
4 | * Copyright (C) 1998 David S. Miller (davem@redhat.com) | ||
5 | */ | ||
6 | |||
7 | #include <linux/config.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/sched.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <asm/system.h> | ||
12 | |||
13 | #ifdef CONFIG_SMP | ||
14 | |||
15 | #define GET_CALLER(PC) __asm__ __volatile__("mov %%i7, %0" : "=r" (PC)) | ||
16 | |||
17 | static inline void show (char *str, spinlock_t *lock, unsigned long caller) | ||
18 | { | ||
19 | int cpu = smp_processor_id(); | ||
20 | |||
21 | printk("%s(%p) CPU#%d stuck at %08x, owner PC(%08x):CPU(%x)\n", | ||
22 | str, lock, cpu, (unsigned int) caller, | ||
23 | lock->owner_pc, lock->owner_cpu); | ||
24 | } | ||
25 | |||
26 | static inline void show_read (char *str, rwlock_t *lock, unsigned long caller) | ||
27 | { | ||
28 | int cpu = smp_processor_id(); | ||
29 | |||
30 | printk("%s(%p) CPU#%d stuck at %08x, writer PC(%08x):CPU(%x)\n", | ||
31 | str, lock, cpu, (unsigned int) caller, | ||
32 | lock->writer_pc, lock->writer_cpu); | ||
33 | } | ||
34 | |||
35 | static inline void show_write (char *str, rwlock_t *lock, unsigned long caller) | ||
36 | { | ||
37 | int cpu = smp_processor_id(); | ||
38 | int i; | ||
39 | |||
40 | printk("%s(%p) CPU#%d stuck at %08x\n", | ||
41 | str, lock, cpu, (unsigned int) caller); | ||
42 | printk("Writer: PC(%08x):CPU(%x)\n", | ||
43 | lock->writer_pc, lock->writer_cpu); | ||
44 | printk("Readers:"); | ||
45 | for (i = 0; i < NR_CPUS; i++) | ||
46 | if (lock->reader_pc[i]) | ||
47 | printk(" %d[%08x]", i, lock->reader_pc[i]); | ||
48 | printk("\n"); | ||
49 | } | ||
50 | |||
51 | #undef INIT_STUCK | ||
52 | #define INIT_STUCK 100000000 | ||
53 | |||
54 | void _do_spin_lock(spinlock_t *lock, char *str) | ||
55 | { | ||
56 | unsigned long caller, val; | ||
57 | int stuck = INIT_STUCK; | ||
58 | int cpu = get_cpu(); | ||
59 | int shown = 0; | ||
60 | |||
61 | GET_CALLER(caller); | ||
62 | again: | ||
63 | __asm__ __volatile__("ldstub [%1], %0" | ||
64 | : "=r" (val) | ||
65 | : "r" (&(lock->lock)) | ||
66 | : "memory"); | ||
67 | membar("#StoreLoad | #StoreStore"); | ||
68 | if (val) { | ||
69 | while (lock->lock) { | ||
70 | if (!--stuck) { | ||
71 | if (shown++ <= 2) | ||
72 | show(str, lock, caller); | ||
73 | stuck = INIT_STUCK; | ||
74 | } | ||
75 | membar("#LoadLoad"); | ||
76 | } | ||
77 | goto again; | ||
78 | } | ||
79 | lock->owner_pc = ((unsigned int)caller); | ||
80 | lock->owner_cpu = cpu; | ||
81 | current->thread.smp_lock_count++; | ||
82 | current->thread.smp_lock_pc = ((unsigned int)caller); | ||
83 | |||
84 | put_cpu(); | ||
85 | } | ||
86 | |||
87 | int _do_spin_trylock(spinlock_t *lock) | ||
88 | { | ||
89 | unsigned long val, caller; | ||
90 | int cpu = get_cpu(); | ||
91 | |||
92 | GET_CALLER(caller); | ||
93 | __asm__ __volatile__("ldstub [%1], %0" | ||
94 | : "=r" (val) | ||
95 | : "r" (&(lock->lock)) | ||
96 | : "memory"); | ||
97 | membar("#StoreLoad | #StoreStore"); | ||
98 | if (!val) { | ||
99 | lock->owner_pc = ((unsigned int)caller); | ||
100 | lock->owner_cpu = cpu; | ||
101 | current->thread.smp_lock_count++; | ||
102 | current->thread.smp_lock_pc = ((unsigned int)caller); | ||
103 | } | ||
104 | |||
105 | put_cpu(); | ||
106 | |||
107 | return val == 0; | ||
108 | } | ||
109 | |||
110 | void _do_spin_unlock(spinlock_t *lock) | ||
111 | { | ||
112 | lock->owner_pc = 0; | ||
113 | lock->owner_cpu = NO_PROC_ID; | ||
114 | membar("#StoreStore | #LoadStore"); | ||
115 | lock->lock = 0; | ||
116 | current->thread.smp_lock_count--; | ||
117 | } | ||
118 | |||
119 | /* Keep INIT_STUCK the same... */ | ||
120 | |||
121 | void _do_read_lock (rwlock_t *rw, char *str) | ||
122 | { | ||
123 | unsigned long caller, val; | ||
124 | int stuck = INIT_STUCK; | ||
125 | int cpu = get_cpu(); | ||
126 | int shown = 0; | ||
127 | |||
128 | GET_CALLER(caller); | ||
129 | wlock_again: | ||
130 | /* Wait for any writer to go away. */ | ||
131 | while (((long)(rw->lock)) < 0) { | ||
132 | if (!--stuck) { | ||
133 | if (shown++ <= 2) | ||
134 | show_read(str, rw, caller); | ||
135 | stuck = INIT_STUCK; | ||
136 | } | ||
137 | membar("#LoadLoad"); | ||
138 | } | ||
139 | /* Try once to increment the counter. */ | ||
140 | __asm__ __volatile__( | ||
141 | " ldx [%0], %%g1\n" | ||
142 | " brlz,a,pn %%g1, 2f\n" | ||
143 | " mov 1, %0\n" | ||
144 | " add %%g1, 1, %%g7\n" | ||
145 | " casx [%0], %%g1, %%g7\n" | ||
146 | " sub %%g1, %%g7, %0\n" | ||
147 | "2:" : "=r" (val) | ||
148 | : "0" (&(rw->lock)) | ||
149 | : "g1", "g7", "memory"); | ||
150 | membar("#StoreLoad | #StoreStore"); | ||
151 | if (val) | ||
152 | goto wlock_again; | ||
153 | rw->reader_pc[cpu] = ((unsigned int)caller); | ||
154 | current->thread.smp_lock_count++; | ||
155 | current->thread.smp_lock_pc = ((unsigned int)caller); | ||
156 | |||
157 | put_cpu(); | ||
158 | } | ||
159 | |||
160 | void _do_read_unlock (rwlock_t *rw, char *str) | ||
161 | { | ||
162 | unsigned long caller, val; | ||
163 | int stuck = INIT_STUCK; | ||
164 | int cpu = get_cpu(); | ||
165 | int shown = 0; | ||
166 | |||
167 | GET_CALLER(caller); | ||
168 | |||
169 | /* Drop our identity _first_. */ | ||
170 | rw->reader_pc[cpu] = 0; | ||
171 | current->thread.smp_lock_count--; | ||
172 | runlock_again: | ||
173 | /* Spin trying to decrement the counter using casx. */ | ||
174 | __asm__ __volatile__( | ||
175 | " membar #StoreLoad | #LoadLoad\n" | ||
176 | " ldx [%0], %%g1\n" | ||
177 | " sub %%g1, 1, %%g7\n" | ||
178 | " casx [%0], %%g1, %%g7\n" | ||
179 | " membar #StoreLoad | #StoreStore\n" | ||
180 | " sub %%g1, %%g7, %0\n" | ||
181 | : "=r" (val) | ||
182 | : "0" (&(rw->lock)) | ||
183 | : "g1", "g7", "memory"); | ||
184 | if (val) { | ||
185 | if (!--stuck) { | ||
186 | if (shown++ <= 2) | ||
187 | show_read(str, rw, caller); | ||
188 | stuck = INIT_STUCK; | ||
189 | } | ||
190 | goto runlock_again; | ||
191 | } | ||
192 | |||
193 | put_cpu(); | ||
194 | } | ||
195 | |||
196 | void _do_write_lock (rwlock_t *rw, char *str) | ||
197 | { | ||
198 | unsigned long caller, val; | ||
199 | int stuck = INIT_STUCK; | ||
200 | int cpu = get_cpu(); | ||
201 | int shown = 0; | ||
202 | |||
203 | GET_CALLER(caller); | ||
204 | wlock_again: | ||
205 | /* Spin while there is another writer. */ | ||
206 | while (((long)rw->lock) < 0) { | ||
207 | if (!--stuck) { | ||
208 | if (shown++ <= 2) | ||
209 | show_write(str, rw, caller); | ||
210 | stuck = INIT_STUCK; | ||
211 | } | ||
212 | membar("#LoadLoad"); | ||
213 | } | ||
214 | |||
215 | /* Try to acuire the write bit. */ | ||
216 | __asm__ __volatile__( | ||
217 | " mov 1, %%g3\n" | ||
218 | " sllx %%g3, 63, %%g3\n" | ||
219 | " ldx [%0], %%g1\n" | ||
220 | " brlz,pn %%g1, 1f\n" | ||
221 | " or %%g1, %%g3, %%g7\n" | ||
222 | " casx [%0], %%g1, %%g7\n" | ||
223 | " membar #StoreLoad | #StoreStore\n" | ||
224 | " ba,pt %%xcc, 2f\n" | ||
225 | " sub %%g1, %%g7, %0\n" | ||
226 | "1: mov 1, %0\n" | ||
227 | "2:" : "=r" (val) | ||
228 | : "0" (&(rw->lock)) | ||
229 | : "g3", "g1", "g7", "memory"); | ||
230 | if (val) { | ||
231 | /* We couldn't get the write bit. */ | ||
232 | if (!--stuck) { | ||
233 | if (shown++ <= 2) | ||
234 | show_write(str, rw, caller); | ||
235 | stuck = INIT_STUCK; | ||
236 | } | ||
237 | goto wlock_again; | ||
238 | } | ||
239 | if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) { | ||
240 | /* Readers still around, drop the write | ||
241 | * lock, spin, and try again. | ||
242 | */ | ||
243 | if (!--stuck) { | ||
244 | if (shown++ <= 2) | ||
245 | show_write(str, rw, caller); | ||
246 | stuck = INIT_STUCK; | ||
247 | } | ||
248 | __asm__ __volatile__( | ||
249 | " mov 1, %%g3\n" | ||
250 | " sllx %%g3, 63, %%g3\n" | ||
251 | "1: ldx [%0], %%g1\n" | ||
252 | " andn %%g1, %%g3, %%g7\n" | ||
253 | " casx [%0], %%g1, %%g7\n" | ||
254 | " cmp %%g1, %%g7\n" | ||
255 | " bne,pn %%xcc, 1b\n" | ||
256 | " membar #StoreLoad | #StoreStore" | ||
257 | : /* no outputs */ | ||
258 | : "r" (&(rw->lock)) | ||
259 | : "g3", "g1", "g7", "cc", "memory"); | ||
260 | while(rw->lock != 0) { | ||
261 | if (!--stuck) { | ||
262 | if (shown++ <= 2) | ||
263 | show_write(str, rw, caller); | ||
264 | stuck = INIT_STUCK; | ||
265 | } | ||
266 | membar("#LoadLoad"); | ||
267 | } | ||
268 | goto wlock_again; | ||
269 | } | ||
270 | |||
271 | /* We have it, say who we are. */ | ||
272 | rw->writer_pc = ((unsigned int)caller); | ||
273 | rw->writer_cpu = cpu; | ||
274 | current->thread.smp_lock_count++; | ||
275 | current->thread.smp_lock_pc = ((unsigned int)caller); | ||
276 | |||
277 | put_cpu(); | ||
278 | } | ||
279 | |||
280 | void _do_write_unlock(rwlock_t *rw) | ||
281 | { | ||
282 | unsigned long caller, val; | ||
283 | int stuck = INIT_STUCK; | ||
284 | int shown = 0; | ||
285 | |||
286 | GET_CALLER(caller); | ||
287 | |||
288 | /* Drop our identity _first_ */ | ||
289 | rw->writer_pc = 0; | ||
290 | rw->writer_cpu = NO_PROC_ID; | ||
291 | current->thread.smp_lock_count--; | ||
292 | wlock_again: | ||
293 | __asm__ __volatile__( | ||
294 | " membar #StoreLoad | #LoadLoad\n" | ||
295 | " mov 1, %%g3\n" | ||
296 | " sllx %%g3, 63, %%g3\n" | ||
297 | " ldx [%0], %%g1\n" | ||
298 | " andn %%g1, %%g3, %%g7\n" | ||
299 | " casx [%0], %%g1, %%g7\n" | ||
300 | " membar #StoreLoad | #StoreStore\n" | ||
301 | " sub %%g1, %%g7, %0\n" | ||
302 | : "=r" (val) | ||
303 | : "0" (&(rw->lock)) | ||
304 | : "g3", "g1", "g7", "memory"); | ||
305 | if (val) { | ||
306 | if (!--stuck) { | ||
307 | if (shown++ <= 2) | ||
308 | show_write("write_unlock", rw, caller); | ||
309 | stuck = INIT_STUCK; | ||
310 | } | ||
311 | goto wlock_again; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | int _do_write_trylock (rwlock_t *rw, char *str) | ||
316 | { | ||
317 | unsigned long caller, val; | ||
318 | int cpu = get_cpu(); | ||
319 | |||
320 | GET_CALLER(caller); | ||
321 | |||
322 | /* Try to acuire the write bit. */ | ||
323 | __asm__ __volatile__( | ||
324 | " mov 1, %%g3\n" | ||
325 | " sllx %%g3, 63, %%g3\n" | ||
326 | " ldx [%0], %%g1\n" | ||
327 | " brlz,pn %%g1, 1f\n" | ||
328 | " or %%g1, %%g3, %%g7\n" | ||
329 | " casx [%0], %%g1, %%g7\n" | ||
330 | " membar #StoreLoad | #StoreStore\n" | ||
331 | " ba,pt %%xcc, 2f\n" | ||
332 | " sub %%g1, %%g7, %0\n" | ||
333 | "1: mov 1, %0\n" | ||
334 | "2:" : "=r" (val) | ||
335 | : "0" (&(rw->lock)) | ||
336 | : "g3", "g1", "g7", "memory"); | ||
337 | |||
338 | if (val) { | ||
339 | put_cpu(); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | if ((rw->lock & ((1UL<<63)-1UL)) != 0UL) { | ||
344 | /* Readers still around, drop the write | ||
345 | * lock, return failure. | ||
346 | */ | ||
347 | __asm__ __volatile__( | ||
348 | " mov 1, %%g3\n" | ||
349 | " sllx %%g3, 63, %%g3\n" | ||
350 | "1: ldx [%0], %%g1\n" | ||
351 | " andn %%g1, %%g3, %%g7\n" | ||
352 | " casx [%0], %%g1, %%g7\n" | ||
353 | " cmp %%g1, %%g7\n" | ||
354 | " bne,pn %%xcc, 1b\n" | ||
355 | " membar #StoreLoad | #StoreStore" | ||
356 | : /* no outputs */ | ||
357 | : "r" (&(rw->lock)) | ||
358 | : "g3", "g1", "g7", "cc", "memory"); | ||
359 | |||
360 | put_cpu(); | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /* We have it, say who we are. */ | ||
366 | rw->writer_pc = ((unsigned int)caller); | ||
367 | rw->writer_cpu = cpu; | ||
368 | current->thread.smp_lock_count++; | ||
369 | current->thread.smp_lock_pc = ((unsigned int)caller); | ||
370 | |||
371 | put_cpu(); | ||
372 | |||
373 | return 1; | ||
374 | } | ||
375 | |||
376 | #endif /* CONFIG_SMP */ | ||