Commit 60fc28746a7b61775ae28950ddf7a4ac15955639
Committed by
Ingo Molnar
1 parent
8eddac3f10
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
locking: Move the spinlock code to kernel/locking/
Suggested-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/n/tip-b81ol0z3mon45m51o131yc9j@git.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Showing 7 changed files with 705 additions and 705 deletions Side-by-side Diff
kernel/Makefile
... | ... | @@ -43,9 +43,6 @@ |
43 | 43 | ifneq ($(CONFIG_SMP),y) |
44 | 44 | obj-y += up.o |
45 | 45 | endif |
46 | -obj-$(CONFIG_SMP) += spinlock.o | |
47 | -obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o | |
48 | -obj-$(CONFIG_PROVE_LOCKING) += spinlock.o | |
49 | 46 | obj-$(CONFIG_UID16) += uid16.o |
50 | 47 | obj-$(CONFIG_MODULES) += module.o |
51 | 48 | obj-$(CONFIG_MODULE_SIG) += module_signing.o modsign_pubkey.o modsign_certificate.o |
kernel/locking/Makefile
kernel/locking/spinlock.c
1 | +/* | |
2 | + * Copyright (2004) Linus Torvalds | |
3 | + * | |
4 | + * Author: Zwane Mwaikambo <zwane@fsmlabs.com> | |
5 | + * | |
6 | + * Copyright (2004, 2005) Ingo Molnar | |
7 | + * | |
8 | + * This file contains the spinlock/rwlock implementations for the | |
9 | + * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them) | |
10 | + * | |
11 | + * Note that some architectures have special knowledge about the | |
12 | + * stack frames of these functions in their profile_pc. If you | |
13 | + * change anything significant here that could change the stack | |
14 | + * frame contact the architecture maintainers. | |
15 | + */ | |
16 | + | |
17 | +#include <linux/linkage.h> | |
18 | +#include <linux/preempt.h> | |
19 | +#include <linux/spinlock.h> | |
20 | +#include <linux/interrupt.h> | |
21 | +#include <linux/debug_locks.h> | |
22 | +#include <linux/export.h> | |
23 | + | |
24 | +/* | |
25 | + * If lockdep is enabled then we use the non-preemption spin-ops | |
26 | + * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are | |
27 | + * not re-enabled during lock-acquire (which the preempt-spin-ops do): | |
28 | + */ | |
29 | +#if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) | |
30 | +/* | |
31 | + * The __lock_function inlines are taken from | |
32 | + * include/linux/spinlock_api_smp.h | |
33 | + */ | |
34 | +#else | |
35 | +#define raw_read_can_lock(l) read_can_lock(l) | |
36 | +#define raw_write_can_lock(l) write_can_lock(l) | |
37 | + | |
38 | +/* | |
39 | + * Some architectures can relax in favour of the CPU owning the lock. | |
40 | + */ | |
41 | +#ifndef arch_read_relax | |
42 | +# define arch_read_relax(l) cpu_relax() | |
43 | +#endif | |
44 | +#ifndef arch_write_relax | |
45 | +# define arch_write_relax(l) cpu_relax() | |
46 | +#endif | |
47 | +#ifndef arch_spin_relax | |
48 | +# define arch_spin_relax(l) cpu_relax() | |
49 | +#endif | |
50 | + | |
51 | +/* | |
52 | + * We build the __lock_function inlines here. They are too large for | |
53 | + * inlining all over the place, but here is only one user per function | |
54 | + * which embedds them into the calling _lock_function below. | |
55 | + * | |
56 | + * This could be a long-held lock. We both prepare to spin for a long | |
57 | + * time (making _this_ CPU preemptable if possible), and we also signal | |
58 | + * towards that other CPU that it should break the lock ASAP. | |
59 | + */ | |
60 | +#define BUILD_LOCK_OPS(op, locktype) \ | |
61 | +void __lockfunc __raw_##op##_lock(locktype##_t *lock) \ | |
62 | +{ \ | |
63 | + for (;;) { \ | |
64 | + preempt_disable(); \ | |
65 | + if (likely(do_raw_##op##_trylock(lock))) \ | |
66 | + break; \ | |
67 | + preempt_enable(); \ | |
68 | + \ | |
69 | + if (!(lock)->break_lock) \ | |
70 | + (lock)->break_lock = 1; \ | |
71 | + while (!raw_##op##_can_lock(lock) && (lock)->break_lock)\ | |
72 | + arch_##op##_relax(&lock->raw_lock); \ | |
73 | + } \ | |
74 | + (lock)->break_lock = 0; \ | |
75 | +} \ | |
76 | + \ | |
77 | +unsigned long __lockfunc __raw_##op##_lock_irqsave(locktype##_t *lock) \ | |
78 | +{ \ | |
79 | + unsigned long flags; \ | |
80 | + \ | |
81 | + for (;;) { \ | |
82 | + preempt_disable(); \ | |
83 | + local_irq_save(flags); \ | |
84 | + if (likely(do_raw_##op##_trylock(lock))) \ | |
85 | + break; \ | |
86 | + local_irq_restore(flags); \ | |
87 | + preempt_enable(); \ | |
88 | + \ | |
89 | + if (!(lock)->break_lock) \ | |
90 | + (lock)->break_lock = 1; \ | |
91 | + while (!raw_##op##_can_lock(lock) && (lock)->break_lock)\ | |
92 | + arch_##op##_relax(&lock->raw_lock); \ | |
93 | + } \ | |
94 | + (lock)->break_lock = 0; \ | |
95 | + return flags; \ | |
96 | +} \ | |
97 | + \ | |
98 | +void __lockfunc __raw_##op##_lock_irq(locktype##_t *lock) \ | |
99 | +{ \ | |
100 | + _raw_##op##_lock_irqsave(lock); \ | |
101 | +} \ | |
102 | + \ | |
103 | +void __lockfunc __raw_##op##_lock_bh(locktype##_t *lock) \ | |
104 | +{ \ | |
105 | + unsigned long flags; \ | |
106 | + \ | |
107 | + /* */ \ | |
108 | + /* Careful: we must exclude softirqs too, hence the */ \ | |
109 | + /* irq-disabling. We use the generic preemption-aware */ \ | |
110 | + /* function: */ \ | |
111 | + /**/ \ | |
112 | + flags = _raw_##op##_lock_irqsave(lock); \ | |
113 | + local_bh_disable(); \ | |
114 | + local_irq_restore(flags); \ | |
115 | +} \ | |
116 | + | |
117 | +/* | |
118 | + * Build preemption-friendly versions of the following | |
119 | + * lock-spinning functions: | |
120 | + * | |
121 | + * __[spin|read|write]_lock() | |
122 | + * __[spin|read|write]_lock_irq() | |
123 | + * __[spin|read|write]_lock_irqsave() | |
124 | + * __[spin|read|write]_lock_bh() | |
125 | + */ | |
126 | +BUILD_LOCK_OPS(spin, raw_spinlock); | |
127 | +BUILD_LOCK_OPS(read, rwlock); | |
128 | +BUILD_LOCK_OPS(write, rwlock); | |
129 | + | |
130 | +#endif | |
131 | + | |
132 | +#ifndef CONFIG_INLINE_SPIN_TRYLOCK | |
133 | +int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) | |
134 | +{ | |
135 | + return __raw_spin_trylock(lock); | |
136 | +} | |
137 | +EXPORT_SYMBOL(_raw_spin_trylock); | |
138 | +#endif | |
139 | + | |
140 | +#ifndef CONFIG_INLINE_SPIN_TRYLOCK_BH | |
141 | +int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) | |
142 | +{ | |
143 | + return __raw_spin_trylock_bh(lock); | |
144 | +} | |
145 | +EXPORT_SYMBOL(_raw_spin_trylock_bh); | |
146 | +#endif | |
147 | + | |
148 | +#ifndef CONFIG_INLINE_SPIN_LOCK | |
149 | +void __lockfunc _raw_spin_lock(raw_spinlock_t *lock) | |
150 | +{ | |
151 | + __raw_spin_lock(lock); | |
152 | +} | |
153 | +EXPORT_SYMBOL(_raw_spin_lock); | |
154 | +#endif | |
155 | + | |
156 | +#ifndef CONFIG_INLINE_SPIN_LOCK_IRQSAVE | |
157 | +unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock) | |
158 | +{ | |
159 | + return __raw_spin_lock_irqsave(lock); | |
160 | +} | |
161 | +EXPORT_SYMBOL(_raw_spin_lock_irqsave); | |
162 | +#endif | |
163 | + | |
164 | +#ifndef CONFIG_INLINE_SPIN_LOCK_IRQ | |
165 | +void __lockfunc _raw_spin_lock_irq(raw_spinlock_t *lock) | |
166 | +{ | |
167 | + __raw_spin_lock_irq(lock); | |
168 | +} | |
169 | +EXPORT_SYMBOL(_raw_spin_lock_irq); | |
170 | +#endif | |
171 | + | |
172 | +#ifndef CONFIG_INLINE_SPIN_LOCK_BH | |
173 | +void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock) | |
174 | +{ | |
175 | + __raw_spin_lock_bh(lock); | |
176 | +} | |
177 | +EXPORT_SYMBOL(_raw_spin_lock_bh); | |
178 | +#endif | |
179 | + | |
180 | +#ifdef CONFIG_UNINLINE_SPIN_UNLOCK | |
181 | +void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock) | |
182 | +{ | |
183 | + __raw_spin_unlock(lock); | |
184 | +} | |
185 | +EXPORT_SYMBOL(_raw_spin_unlock); | |
186 | +#endif | |
187 | + | |
188 | +#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE | |
189 | +void __lockfunc _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags) | |
190 | +{ | |
191 | + __raw_spin_unlock_irqrestore(lock, flags); | |
192 | +} | |
193 | +EXPORT_SYMBOL(_raw_spin_unlock_irqrestore); | |
194 | +#endif | |
195 | + | |
196 | +#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQ | |
197 | +void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock) | |
198 | +{ | |
199 | + __raw_spin_unlock_irq(lock); | |
200 | +} | |
201 | +EXPORT_SYMBOL(_raw_spin_unlock_irq); | |
202 | +#endif | |
203 | + | |
204 | +#ifndef CONFIG_INLINE_SPIN_UNLOCK_BH | |
205 | +void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) | |
206 | +{ | |
207 | + __raw_spin_unlock_bh(lock); | |
208 | +} | |
209 | +EXPORT_SYMBOL(_raw_spin_unlock_bh); | |
210 | +#endif | |
211 | + | |
212 | +#ifndef CONFIG_INLINE_READ_TRYLOCK | |
213 | +int __lockfunc _raw_read_trylock(rwlock_t *lock) | |
214 | +{ | |
215 | + return __raw_read_trylock(lock); | |
216 | +} | |
217 | +EXPORT_SYMBOL(_raw_read_trylock); | |
218 | +#endif | |
219 | + | |
220 | +#ifndef CONFIG_INLINE_READ_LOCK | |
221 | +void __lockfunc _raw_read_lock(rwlock_t *lock) | |
222 | +{ | |
223 | + __raw_read_lock(lock); | |
224 | +} | |
225 | +EXPORT_SYMBOL(_raw_read_lock); | |
226 | +#endif | |
227 | + | |
228 | +#ifndef CONFIG_INLINE_READ_LOCK_IRQSAVE | |
229 | +unsigned long __lockfunc _raw_read_lock_irqsave(rwlock_t *lock) | |
230 | +{ | |
231 | + return __raw_read_lock_irqsave(lock); | |
232 | +} | |
233 | +EXPORT_SYMBOL(_raw_read_lock_irqsave); | |
234 | +#endif | |
235 | + | |
236 | +#ifndef CONFIG_INLINE_READ_LOCK_IRQ | |
237 | +void __lockfunc _raw_read_lock_irq(rwlock_t *lock) | |
238 | +{ | |
239 | + __raw_read_lock_irq(lock); | |
240 | +} | |
241 | +EXPORT_SYMBOL(_raw_read_lock_irq); | |
242 | +#endif | |
243 | + | |
244 | +#ifndef CONFIG_INLINE_READ_LOCK_BH | |
245 | +void __lockfunc _raw_read_lock_bh(rwlock_t *lock) | |
246 | +{ | |
247 | + __raw_read_lock_bh(lock); | |
248 | +} | |
249 | +EXPORT_SYMBOL(_raw_read_lock_bh); | |
250 | +#endif | |
251 | + | |
252 | +#ifndef CONFIG_INLINE_READ_UNLOCK | |
253 | +void __lockfunc _raw_read_unlock(rwlock_t *lock) | |
254 | +{ | |
255 | + __raw_read_unlock(lock); | |
256 | +} | |
257 | +EXPORT_SYMBOL(_raw_read_unlock); | |
258 | +#endif | |
259 | + | |
260 | +#ifndef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE | |
261 | +void __lockfunc _raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) | |
262 | +{ | |
263 | + __raw_read_unlock_irqrestore(lock, flags); | |
264 | +} | |
265 | +EXPORT_SYMBOL(_raw_read_unlock_irqrestore); | |
266 | +#endif | |
267 | + | |
268 | +#ifndef CONFIG_INLINE_READ_UNLOCK_IRQ | |
269 | +void __lockfunc _raw_read_unlock_irq(rwlock_t *lock) | |
270 | +{ | |
271 | + __raw_read_unlock_irq(lock); | |
272 | +} | |
273 | +EXPORT_SYMBOL(_raw_read_unlock_irq); | |
274 | +#endif | |
275 | + | |
276 | +#ifndef CONFIG_INLINE_READ_UNLOCK_BH | |
277 | +void __lockfunc _raw_read_unlock_bh(rwlock_t *lock) | |
278 | +{ | |
279 | + __raw_read_unlock_bh(lock); | |
280 | +} | |
281 | +EXPORT_SYMBOL(_raw_read_unlock_bh); | |
282 | +#endif | |
283 | + | |
284 | +#ifndef CONFIG_INLINE_WRITE_TRYLOCK | |
285 | +int __lockfunc _raw_write_trylock(rwlock_t *lock) | |
286 | +{ | |
287 | + return __raw_write_trylock(lock); | |
288 | +} | |
289 | +EXPORT_SYMBOL(_raw_write_trylock); | |
290 | +#endif | |
291 | + | |
292 | +#ifndef CONFIG_INLINE_WRITE_LOCK | |
293 | +void __lockfunc _raw_write_lock(rwlock_t *lock) | |
294 | +{ | |
295 | + __raw_write_lock(lock); | |
296 | +} | |
297 | +EXPORT_SYMBOL(_raw_write_lock); | |
298 | +#endif | |
299 | + | |
300 | +#ifndef CONFIG_INLINE_WRITE_LOCK_IRQSAVE | |
301 | +unsigned long __lockfunc _raw_write_lock_irqsave(rwlock_t *lock) | |
302 | +{ | |
303 | + return __raw_write_lock_irqsave(lock); | |
304 | +} | |
305 | +EXPORT_SYMBOL(_raw_write_lock_irqsave); | |
306 | +#endif | |
307 | + | |
308 | +#ifndef CONFIG_INLINE_WRITE_LOCK_IRQ | |
309 | +void __lockfunc _raw_write_lock_irq(rwlock_t *lock) | |
310 | +{ | |
311 | + __raw_write_lock_irq(lock); | |
312 | +} | |
313 | +EXPORT_SYMBOL(_raw_write_lock_irq); | |
314 | +#endif | |
315 | + | |
316 | +#ifndef CONFIG_INLINE_WRITE_LOCK_BH | |
317 | +void __lockfunc _raw_write_lock_bh(rwlock_t *lock) | |
318 | +{ | |
319 | + __raw_write_lock_bh(lock); | |
320 | +} | |
321 | +EXPORT_SYMBOL(_raw_write_lock_bh); | |
322 | +#endif | |
323 | + | |
324 | +#ifndef CONFIG_INLINE_WRITE_UNLOCK | |
325 | +void __lockfunc _raw_write_unlock(rwlock_t *lock) | |
326 | +{ | |
327 | + __raw_write_unlock(lock); | |
328 | +} | |
329 | +EXPORT_SYMBOL(_raw_write_unlock); | |
330 | +#endif | |
331 | + | |
332 | +#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE | |
333 | +void __lockfunc _raw_write_unlock_irqrestore(rwlock_t *lock, unsigned long flags) | |
334 | +{ | |
335 | + __raw_write_unlock_irqrestore(lock, flags); | |
336 | +} | |
337 | +EXPORT_SYMBOL(_raw_write_unlock_irqrestore); | |
338 | +#endif | |
339 | + | |
340 | +#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQ | |
341 | +void __lockfunc _raw_write_unlock_irq(rwlock_t *lock) | |
342 | +{ | |
343 | + __raw_write_unlock_irq(lock); | |
344 | +} | |
345 | +EXPORT_SYMBOL(_raw_write_unlock_irq); | |
346 | +#endif | |
347 | + | |
348 | +#ifndef CONFIG_INLINE_WRITE_UNLOCK_BH | |
349 | +void __lockfunc _raw_write_unlock_bh(rwlock_t *lock) | |
350 | +{ | |
351 | + __raw_write_unlock_bh(lock); | |
352 | +} | |
353 | +EXPORT_SYMBOL(_raw_write_unlock_bh); | |
354 | +#endif | |
355 | + | |
356 | +#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
357 | + | |
358 | +void __lockfunc _raw_spin_lock_nested(raw_spinlock_t *lock, int subclass) | |
359 | +{ | |
360 | + preempt_disable(); | |
361 | + spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | |
362 | + LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); | |
363 | +} | |
364 | +EXPORT_SYMBOL(_raw_spin_lock_nested); | |
365 | + | |
366 | +unsigned long __lockfunc _raw_spin_lock_irqsave_nested(raw_spinlock_t *lock, | |
367 | + int subclass) | |
368 | +{ | |
369 | + unsigned long flags; | |
370 | + | |
371 | + local_irq_save(flags); | |
372 | + preempt_disable(); | |
373 | + spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | |
374 | + LOCK_CONTENDED_FLAGS(lock, do_raw_spin_trylock, do_raw_spin_lock, | |
375 | + do_raw_spin_lock_flags, &flags); | |
376 | + return flags; | |
377 | +} | |
378 | +EXPORT_SYMBOL(_raw_spin_lock_irqsave_nested); | |
379 | + | |
380 | +void __lockfunc _raw_spin_lock_nest_lock(raw_spinlock_t *lock, | |
381 | + struct lockdep_map *nest_lock) | |
382 | +{ | |
383 | + preempt_disable(); | |
384 | + spin_acquire_nest(&lock->dep_map, 0, 0, nest_lock, _RET_IP_); | |
385 | + LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); | |
386 | +} | |
387 | +EXPORT_SYMBOL(_raw_spin_lock_nest_lock); | |
388 | + | |
389 | +#endif | |
390 | + | |
391 | +notrace int in_lock_functions(unsigned long addr) | |
392 | +{ | |
393 | + /* Linker adds these: start and end of __lockfunc functions */ | |
394 | + extern char __lock_text_start[], __lock_text_end[]; | |
395 | + | |
396 | + return addr >= (unsigned long)__lock_text_start | |
397 | + && addr < (unsigned long)__lock_text_end; | |
398 | +} | |
399 | +EXPORT_SYMBOL(in_lock_functions); |
kernel/locking/spinlock_debug.c
1 | +/* | |
2 | + * Copyright 2005, Red Hat, Inc., Ingo Molnar | |
3 | + * Released under the General Public License (GPL). | |
4 | + * | |
5 | + * This file contains the spinlock/rwlock implementations for | |
6 | + * DEBUG_SPINLOCK. | |
7 | + */ | |
8 | + | |
9 | +#include <linux/spinlock.h> | |
10 | +#include <linux/nmi.h> | |
11 | +#include <linux/interrupt.h> | |
12 | +#include <linux/debug_locks.h> | |
13 | +#include <linux/delay.h> | |
14 | +#include <linux/export.h> | |
15 | + | |
16 | +void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, | |
17 | + struct lock_class_key *key) | |
18 | +{ | |
19 | +#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
20 | + /* | |
21 | + * Make sure we are not reinitializing a held lock: | |
22 | + */ | |
23 | + debug_check_no_locks_freed((void *)lock, sizeof(*lock)); | |
24 | + lockdep_init_map(&lock->dep_map, name, key, 0); | |
25 | +#endif | |
26 | + lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; | |
27 | + lock->magic = SPINLOCK_MAGIC; | |
28 | + lock->owner = SPINLOCK_OWNER_INIT; | |
29 | + lock->owner_cpu = -1; | |
30 | +} | |
31 | + | |
32 | +EXPORT_SYMBOL(__raw_spin_lock_init); | |
33 | + | |
34 | +void __rwlock_init(rwlock_t *lock, const char *name, | |
35 | + struct lock_class_key *key) | |
36 | +{ | |
37 | +#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
38 | + /* | |
39 | + * Make sure we are not reinitializing a held lock: | |
40 | + */ | |
41 | + debug_check_no_locks_freed((void *)lock, sizeof(*lock)); | |
42 | + lockdep_init_map(&lock->dep_map, name, key, 0); | |
43 | +#endif | |
44 | + lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED; | |
45 | + lock->magic = RWLOCK_MAGIC; | |
46 | + lock->owner = SPINLOCK_OWNER_INIT; | |
47 | + lock->owner_cpu = -1; | |
48 | +} | |
49 | + | |
50 | +EXPORT_SYMBOL(__rwlock_init); | |
51 | + | |
52 | +static void spin_dump(raw_spinlock_t *lock, const char *msg) | |
53 | +{ | |
54 | + struct task_struct *owner = NULL; | |
55 | + | |
56 | + if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) | |
57 | + owner = lock->owner; | |
58 | + printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n", | |
59 | + msg, raw_smp_processor_id(), | |
60 | + current->comm, task_pid_nr(current)); | |
61 | + printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, " | |
62 | + ".owner_cpu: %d\n", | |
63 | + lock, lock->magic, | |
64 | + owner ? owner->comm : "<none>", | |
65 | + owner ? task_pid_nr(owner) : -1, | |
66 | + lock->owner_cpu); | |
67 | + dump_stack(); | |
68 | +} | |
69 | + | |
70 | +static void spin_bug(raw_spinlock_t *lock, const char *msg) | |
71 | +{ | |
72 | + if (!debug_locks_off()) | |
73 | + return; | |
74 | + | |
75 | + spin_dump(lock, msg); | |
76 | +} | |
77 | + | |
78 | +#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) | |
79 | + | |
80 | +static inline void | |
81 | +debug_spin_lock_before(raw_spinlock_t *lock) | |
82 | +{ | |
83 | + SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | |
84 | + SPIN_BUG_ON(lock->owner == current, lock, "recursion"); | |
85 | + SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | |
86 | + lock, "cpu recursion"); | |
87 | +} | |
88 | + | |
89 | +static inline void debug_spin_lock_after(raw_spinlock_t *lock) | |
90 | +{ | |
91 | + lock->owner_cpu = raw_smp_processor_id(); | |
92 | + lock->owner = current; | |
93 | +} | |
94 | + | |
95 | +static inline void debug_spin_unlock(raw_spinlock_t *lock) | |
96 | +{ | |
97 | + SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | |
98 | + SPIN_BUG_ON(!raw_spin_is_locked(lock), lock, "already unlocked"); | |
99 | + SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); | |
100 | + SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | |
101 | + lock, "wrong CPU"); | |
102 | + lock->owner = SPINLOCK_OWNER_INIT; | |
103 | + lock->owner_cpu = -1; | |
104 | +} | |
105 | + | |
106 | +static void __spin_lock_debug(raw_spinlock_t *lock) | |
107 | +{ | |
108 | + u64 i; | |
109 | + u64 loops = loops_per_jiffy * HZ; | |
110 | + | |
111 | + for (i = 0; i < loops; i++) { | |
112 | + if (arch_spin_trylock(&lock->raw_lock)) | |
113 | + return; | |
114 | + __delay(1); | |
115 | + } | |
116 | + /* lockup suspected: */ | |
117 | + spin_dump(lock, "lockup suspected"); | |
118 | +#ifdef CONFIG_SMP | |
119 | + trigger_all_cpu_backtrace(); | |
120 | +#endif | |
121 | + | |
122 | + /* | |
123 | + * The trylock above was causing a livelock. Give the lower level arch | |
124 | + * specific lock code a chance to acquire the lock. We have already | |
125 | + * printed a warning/backtrace at this point. The non-debug arch | |
126 | + * specific code might actually succeed in acquiring the lock. If it is | |
127 | + * not successful, the end-result is the same - there is no forward | |
128 | + * progress. | |
129 | + */ | |
130 | + arch_spin_lock(&lock->raw_lock); | |
131 | +} | |
132 | + | |
133 | +void do_raw_spin_lock(raw_spinlock_t *lock) | |
134 | +{ | |
135 | + debug_spin_lock_before(lock); | |
136 | + if (unlikely(!arch_spin_trylock(&lock->raw_lock))) | |
137 | + __spin_lock_debug(lock); | |
138 | + debug_spin_lock_after(lock); | |
139 | +} | |
140 | + | |
141 | +int do_raw_spin_trylock(raw_spinlock_t *lock) | |
142 | +{ | |
143 | + int ret = arch_spin_trylock(&lock->raw_lock); | |
144 | + | |
145 | + if (ret) | |
146 | + debug_spin_lock_after(lock); | |
147 | +#ifndef CONFIG_SMP | |
148 | + /* | |
149 | + * Must not happen on UP: | |
150 | + */ | |
151 | + SPIN_BUG_ON(!ret, lock, "trylock failure on UP"); | |
152 | +#endif | |
153 | + return ret; | |
154 | +} | |
155 | + | |
156 | +void do_raw_spin_unlock(raw_spinlock_t *lock) | |
157 | +{ | |
158 | + debug_spin_unlock(lock); | |
159 | + arch_spin_unlock(&lock->raw_lock); | |
160 | +} | |
161 | + | |
162 | +static void rwlock_bug(rwlock_t *lock, const char *msg) | |
163 | +{ | |
164 | + if (!debug_locks_off()) | |
165 | + return; | |
166 | + | |
167 | + printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n", | |
168 | + msg, raw_smp_processor_id(), current->comm, | |
169 | + task_pid_nr(current), lock); | |
170 | + dump_stack(); | |
171 | +} | |
172 | + | |
173 | +#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) | |
174 | + | |
175 | +#if 0 /* __write_lock_debug() can lock up - maybe this can too? */ | |
176 | +static void __read_lock_debug(rwlock_t *lock) | |
177 | +{ | |
178 | + u64 i; | |
179 | + u64 loops = loops_per_jiffy * HZ; | |
180 | + int print_once = 1; | |
181 | + | |
182 | + for (;;) { | |
183 | + for (i = 0; i < loops; i++) { | |
184 | + if (arch_read_trylock(&lock->raw_lock)) | |
185 | + return; | |
186 | + __delay(1); | |
187 | + } | |
188 | + /* lockup suspected: */ | |
189 | + if (print_once) { | |
190 | + print_once = 0; | |
191 | + printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, " | |
192 | + "%s/%d, %p\n", | |
193 | + raw_smp_processor_id(), current->comm, | |
194 | + current->pid, lock); | |
195 | + dump_stack(); | |
196 | + } | |
197 | + } | |
198 | +} | |
199 | +#endif | |
200 | + | |
201 | +void do_raw_read_lock(rwlock_t *lock) | |
202 | +{ | |
203 | + RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
204 | + arch_read_lock(&lock->raw_lock); | |
205 | +} | |
206 | + | |
207 | +int do_raw_read_trylock(rwlock_t *lock) | |
208 | +{ | |
209 | + int ret = arch_read_trylock(&lock->raw_lock); | |
210 | + | |
211 | +#ifndef CONFIG_SMP | |
212 | + /* | |
213 | + * Must not happen on UP: | |
214 | + */ | |
215 | + RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | |
216 | +#endif | |
217 | + return ret; | |
218 | +} | |
219 | + | |
220 | +void do_raw_read_unlock(rwlock_t *lock) | |
221 | +{ | |
222 | + RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
223 | + arch_read_unlock(&lock->raw_lock); | |
224 | +} | |
225 | + | |
226 | +static inline void debug_write_lock_before(rwlock_t *lock) | |
227 | +{ | |
228 | + RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
229 | + RWLOCK_BUG_ON(lock->owner == current, lock, "recursion"); | |
230 | + RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | |
231 | + lock, "cpu recursion"); | |
232 | +} | |
233 | + | |
234 | +static inline void debug_write_lock_after(rwlock_t *lock) | |
235 | +{ | |
236 | + lock->owner_cpu = raw_smp_processor_id(); | |
237 | + lock->owner = current; | |
238 | +} | |
239 | + | |
240 | +static inline void debug_write_unlock(rwlock_t *lock) | |
241 | +{ | |
242 | + RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
243 | + RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); | |
244 | + RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | |
245 | + lock, "wrong CPU"); | |
246 | + lock->owner = SPINLOCK_OWNER_INIT; | |
247 | + lock->owner_cpu = -1; | |
248 | +} | |
249 | + | |
250 | +#if 0 /* This can cause lockups */ | |
251 | +static void __write_lock_debug(rwlock_t *lock) | |
252 | +{ | |
253 | + u64 i; | |
254 | + u64 loops = loops_per_jiffy * HZ; | |
255 | + int print_once = 1; | |
256 | + | |
257 | + for (;;) { | |
258 | + for (i = 0; i < loops; i++) { | |
259 | + if (arch_write_trylock(&lock->raw_lock)) | |
260 | + return; | |
261 | + __delay(1); | |
262 | + } | |
263 | + /* lockup suspected: */ | |
264 | + if (print_once) { | |
265 | + print_once = 0; | |
266 | + printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, " | |
267 | + "%s/%d, %p\n", | |
268 | + raw_smp_processor_id(), current->comm, | |
269 | + current->pid, lock); | |
270 | + dump_stack(); | |
271 | + } | |
272 | + } | |
273 | +} | |
274 | +#endif | |
275 | + | |
276 | +void do_raw_write_lock(rwlock_t *lock) | |
277 | +{ | |
278 | + debug_write_lock_before(lock); | |
279 | + arch_write_lock(&lock->raw_lock); | |
280 | + debug_write_lock_after(lock); | |
281 | +} | |
282 | + | |
283 | +int do_raw_write_trylock(rwlock_t *lock) | |
284 | +{ | |
285 | + int ret = arch_write_trylock(&lock->raw_lock); | |
286 | + | |
287 | + if (ret) | |
288 | + debug_write_lock_after(lock); | |
289 | +#ifndef CONFIG_SMP | |
290 | + /* | |
291 | + * Must not happen on UP: | |
292 | + */ | |
293 | + RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | |
294 | +#endif | |
295 | + return ret; | |
296 | +} | |
297 | + | |
298 | +void do_raw_write_unlock(rwlock_t *lock) | |
299 | +{ | |
300 | + debug_write_unlock(lock); | |
301 | + arch_write_unlock(&lock->raw_lock); | |
302 | +} |
kernel/spinlock.c
1 | -/* | |
2 | - * Copyright (2004) Linus Torvalds | |
3 | - * | |
4 | - * Author: Zwane Mwaikambo <zwane@fsmlabs.com> | |
5 | - * | |
6 | - * Copyright (2004, 2005) Ingo Molnar | |
7 | - * | |
8 | - * This file contains the spinlock/rwlock implementations for the | |
9 | - * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them) | |
10 | - * | |
11 | - * Note that some architectures have special knowledge about the | |
12 | - * stack frames of these functions in their profile_pc. If you | |
13 | - * change anything significant here that could change the stack | |
14 | - * frame contact the architecture maintainers. | |
15 | - */ | |
16 | - | |
17 | -#include <linux/linkage.h> | |
18 | -#include <linux/preempt.h> | |
19 | -#include <linux/spinlock.h> | |
20 | -#include <linux/interrupt.h> | |
21 | -#include <linux/debug_locks.h> | |
22 | -#include <linux/export.h> | |
23 | - | |
24 | -/* | |
25 | - * If lockdep is enabled then we use the non-preemption spin-ops | |
26 | - * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are | |
27 | - * not re-enabled during lock-acquire (which the preempt-spin-ops do): | |
28 | - */ | |
29 | -#if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) | |
30 | -/* | |
31 | - * The __lock_function inlines are taken from | |
32 | - * include/linux/spinlock_api_smp.h | |
33 | - */ | |
34 | -#else | |
35 | -#define raw_read_can_lock(l) read_can_lock(l) | |
36 | -#define raw_write_can_lock(l) write_can_lock(l) | |
37 | - | |
38 | -/* | |
39 | - * Some architectures can relax in favour of the CPU owning the lock. | |
40 | - */ | |
41 | -#ifndef arch_read_relax | |
42 | -# define arch_read_relax(l) cpu_relax() | |
43 | -#endif | |
44 | -#ifndef arch_write_relax | |
45 | -# define arch_write_relax(l) cpu_relax() | |
46 | -#endif | |
47 | -#ifndef arch_spin_relax | |
48 | -# define arch_spin_relax(l) cpu_relax() | |
49 | -#endif | |
50 | - | |
51 | -/* | |
52 | - * We build the __lock_function inlines here. They are too large for | |
53 | - * inlining all over the place, but here is only one user per function | |
54 | - * which embedds them into the calling _lock_function below. | |
55 | - * | |
56 | - * This could be a long-held lock. We both prepare to spin for a long | |
57 | - * time (making _this_ CPU preemptable if possible), and we also signal | |
58 | - * towards that other CPU that it should break the lock ASAP. | |
59 | - */ | |
60 | -#define BUILD_LOCK_OPS(op, locktype) \ | |
61 | -void __lockfunc __raw_##op##_lock(locktype##_t *lock) \ | |
62 | -{ \ | |
63 | - for (;;) { \ | |
64 | - preempt_disable(); \ | |
65 | - if (likely(do_raw_##op##_trylock(lock))) \ | |
66 | - break; \ | |
67 | - preempt_enable(); \ | |
68 | - \ | |
69 | - if (!(lock)->break_lock) \ | |
70 | - (lock)->break_lock = 1; \ | |
71 | - while (!raw_##op##_can_lock(lock) && (lock)->break_lock)\ | |
72 | - arch_##op##_relax(&lock->raw_lock); \ | |
73 | - } \ | |
74 | - (lock)->break_lock = 0; \ | |
75 | -} \ | |
76 | - \ | |
77 | -unsigned long __lockfunc __raw_##op##_lock_irqsave(locktype##_t *lock) \ | |
78 | -{ \ | |
79 | - unsigned long flags; \ | |
80 | - \ | |
81 | - for (;;) { \ | |
82 | - preempt_disable(); \ | |
83 | - local_irq_save(flags); \ | |
84 | - if (likely(do_raw_##op##_trylock(lock))) \ | |
85 | - break; \ | |
86 | - local_irq_restore(flags); \ | |
87 | - preempt_enable(); \ | |
88 | - \ | |
89 | - if (!(lock)->break_lock) \ | |
90 | - (lock)->break_lock = 1; \ | |
91 | - while (!raw_##op##_can_lock(lock) && (lock)->break_lock)\ | |
92 | - arch_##op##_relax(&lock->raw_lock); \ | |
93 | - } \ | |
94 | - (lock)->break_lock = 0; \ | |
95 | - return flags; \ | |
96 | -} \ | |
97 | - \ | |
98 | -void __lockfunc __raw_##op##_lock_irq(locktype##_t *lock) \ | |
99 | -{ \ | |
100 | - _raw_##op##_lock_irqsave(lock); \ | |
101 | -} \ | |
102 | - \ | |
103 | -void __lockfunc __raw_##op##_lock_bh(locktype##_t *lock) \ | |
104 | -{ \ | |
105 | - unsigned long flags; \ | |
106 | - \ | |
107 | - /* */ \ | |
108 | - /* Careful: we must exclude softirqs too, hence the */ \ | |
109 | - /* irq-disabling. We use the generic preemption-aware */ \ | |
110 | - /* function: */ \ | |
111 | - /**/ \ | |
112 | - flags = _raw_##op##_lock_irqsave(lock); \ | |
113 | - local_bh_disable(); \ | |
114 | - local_irq_restore(flags); \ | |
115 | -} \ | |
116 | - | |
117 | -/* | |
118 | - * Build preemption-friendly versions of the following | |
119 | - * lock-spinning functions: | |
120 | - * | |
121 | - * __[spin|read|write]_lock() | |
122 | - * __[spin|read|write]_lock_irq() | |
123 | - * __[spin|read|write]_lock_irqsave() | |
124 | - * __[spin|read|write]_lock_bh() | |
125 | - */ | |
126 | -BUILD_LOCK_OPS(spin, raw_spinlock); | |
127 | -BUILD_LOCK_OPS(read, rwlock); | |
128 | -BUILD_LOCK_OPS(write, rwlock); | |
129 | - | |
130 | -#endif | |
131 | - | |
132 | -#ifndef CONFIG_INLINE_SPIN_TRYLOCK | |
133 | -int __lockfunc _raw_spin_trylock(raw_spinlock_t *lock) | |
134 | -{ | |
135 | - return __raw_spin_trylock(lock); | |
136 | -} | |
137 | -EXPORT_SYMBOL(_raw_spin_trylock); | |
138 | -#endif | |
139 | - | |
140 | -#ifndef CONFIG_INLINE_SPIN_TRYLOCK_BH | |
141 | -int __lockfunc _raw_spin_trylock_bh(raw_spinlock_t *lock) | |
142 | -{ | |
143 | - return __raw_spin_trylock_bh(lock); | |
144 | -} | |
145 | -EXPORT_SYMBOL(_raw_spin_trylock_bh); | |
146 | -#endif | |
147 | - | |
148 | -#ifndef CONFIG_INLINE_SPIN_LOCK | |
149 | -void __lockfunc _raw_spin_lock(raw_spinlock_t *lock) | |
150 | -{ | |
151 | - __raw_spin_lock(lock); | |
152 | -} | |
153 | -EXPORT_SYMBOL(_raw_spin_lock); | |
154 | -#endif | |
155 | - | |
156 | -#ifndef CONFIG_INLINE_SPIN_LOCK_IRQSAVE | |
157 | -unsigned long __lockfunc _raw_spin_lock_irqsave(raw_spinlock_t *lock) | |
158 | -{ | |
159 | - return __raw_spin_lock_irqsave(lock); | |
160 | -} | |
161 | -EXPORT_SYMBOL(_raw_spin_lock_irqsave); | |
162 | -#endif | |
163 | - | |
164 | -#ifndef CONFIG_INLINE_SPIN_LOCK_IRQ | |
165 | -void __lockfunc _raw_spin_lock_irq(raw_spinlock_t *lock) | |
166 | -{ | |
167 | - __raw_spin_lock_irq(lock); | |
168 | -} | |
169 | -EXPORT_SYMBOL(_raw_spin_lock_irq); | |
170 | -#endif | |
171 | - | |
172 | -#ifndef CONFIG_INLINE_SPIN_LOCK_BH | |
173 | -void __lockfunc _raw_spin_lock_bh(raw_spinlock_t *lock) | |
174 | -{ | |
175 | - __raw_spin_lock_bh(lock); | |
176 | -} | |
177 | -EXPORT_SYMBOL(_raw_spin_lock_bh); | |
178 | -#endif | |
179 | - | |
180 | -#ifdef CONFIG_UNINLINE_SPIN_UNLOCK | |
181 | -void __lockfunc _raw_spin_unlock(raw_spinlock_t *lock) | |
182 | -{ | |
183 | - __raw_spin_unlock(lock); | |
184 | -} | |
185 | -EXPORT_SYMBOL(_raw_spin_unlock); | |
186 | -#endif | |
187 | - | |
188 | -#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE | |
189 | -void __lockfunc _raw_spin_unlock_irqrestore(raw_spinlock_t *lock, unsigned long flags) | |
190 | -{ | |
191 | - __raw_spin_unlock_irqrestore(lock, flags); | |
192 | -} | |
193 | -EXPORT_SYMBOL(_raw_spin_unlock_irqrestore); | |
194 | -#endif | |
195 | - | |
196 | -#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQ | |
197 | -void __lockfunc _raw_spin_unlock_irq(raw_spinlock_t *lock) | |
198 | -{ | |
199 | - __raw_spin_unlock_irq(lock); | |
200 | -} | |
201 | -EXPORT_SYMBOL(_raw_spin_unlock_irq); | |
202 | -#endif | |
203 | - | |
204 | -#ifndef CONFIG_INLINE_SPIN_UNLOCK_BH | |
205 | -void __lockfunc _raw_spin_unlock_bh(raw_spinlock_t *lock) | |
206 | -{ | |
207 | - __raw_spin_unlock_bh(lock); | |
208 | -} | |
209 | -EXPORT_SYMBOL(_raw_spin_unlock_bh); | |
210 | -#endif | |
211 | - | |
212 | -#ifndef CONFIG_INLINE_READ_TRYLOCK | |
213 | -int __lockfunc _raw_read_trylock(rwlock_t *lock) | |
214 | -{ | |
215 | - return __raw_read_trylock(lock); | |
216 | -} | |
217 | -EXPORT_SYMBOL(_raw_read_trylock); | |
218 | -#endif | |
219 | - | |
220 | -#ifndef CONFIG_INLINE_READ_LOCK | |
221 | -void __lockfunc _raw_read_lock(rwlock_t *lock) | |
222 | -{ | |
223 | - __raw_read_lock(lock); | |
224 | -} | |
225 | -EXPORT_SYMBOL(_raw_read_lock); | |
226 | -#endif | |
227 | - | |
228 | -#ifndef CONFIG_INLINE_READ_LOCK_IRQSAVE | |
229 | -unsigned long __lockfunc _raw_read_lock_irqsave(rwlock_t *lock) | |
230 | -{ | |
231 | - return __raw_read_lock_irqsave(lock); | |
232 | -} | |
233 | -EXPORT_SYMBOL(_raw_read_lock_irqsave); | |
234 | -#endif | |
235 | - | |
236 | -#ifndef CONFIG_INLINE_READ_LOCK_IRQ | |
237 | -void __lockfunc _raw_read_lock_irq(rwlock_t *lock) | |
238 | -{ | |
239 | - __raw_read_lock_irq(lock); | |
240 | -} | |
241 | -EXPORT_SYMBOL(_raw_read_lock_irq); | |
242 | -#endif | |
243 | - | |
244 | -#ifndef CONFIG_INLINE_READ_LOCK_BH | |
245 | -void __lockfunc _raw_read_lock_bh(rwlock_t *lock) | |
246 | -{ | |
247 | - __raw_read_lock_bh(lock); | |
248 | -} | |
249 | -EXPORT_SYMBOL(_raw_read_lock_bh); | |
250 | -#endif | |
251 | - | |
252 | -#ifndef CONFIG_INLINE_READ_UNLOCK | |
253 | -void __lockfunc _raw_read_unlock(rwlock_t *lock) | |
254 | -{ | |
255 | - __raw_read_unlock(lock); | |
256 | -} | |
257 | -EXPORT_SYMBOL(_raw_read_unlock); | |
258 | -#endif | |
259 | - | |
260 | -#ifndef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE | |
261 | -void __lockfunc _raw_read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) | |
262 | -{ | |
263 | - __raw_read_unlock_irqrestore(lock, flags); | |
264 | -} | |
265 | -EXPORT_SYMBOL(_raw_read_unlock_irqrestore); | |
266 | -#endif | |
267 | - | |
268 | -#ifndef CONFIG_INLINE_READ_UNLOCK_IRQ | |
269 | -void __lockfunc _raw_read_unlock_irq(rwlock_t *lock) | |
270 | -{ | |
271 | - __raw_read_unlock_irq(lock); | |
272 | -} | |
273 | -EXPORT_SYMBOL(_raw_read_unlock_irq); | |
274 | -#endif | |
275 | - | |
276 | -#ifndef CONFIG_INLINE_READ_UNLOCK_BH | |
277 | -void __lockfunc _raw_read_unlock_bh(rwlock_t *lock) | |
278 | -{ | |
279 | - __raw_read_unlock_bh(lock); | |
280 | -} | |
281 | -EXPORT_SYMBOL(_raw_read_unlock_bh); | |
282 | -#endif | |
283 | - | |
284 | -#ifndef CONFIG_INLINE_WRITE_TRYLOCK | |
285 | -int __lockfunc _raw_write_trylock(rwlock_t *lock) | |
286 | -{ | |
287 | - return __raw_write_trylock(lock); | |
288 | -} | |
289 | -EXPORT_SYMBOL(_raw_write_trylock); | |
290 | -#endif | |
291 | - | |
292 | -#ifndef CONFIG_INLINE_WRITE_LOCK | |
293 | -void __lockfunc _raw_write_lock(rwlock_t *lock) | |
294 | -{ | |
295 | - __raw_write_lock(lock); | |
296 | -} | |
297 | -EXPORT_SYMBOL(_raw_write_lock); | |
298 | -#endif | |
299 | - | |
300 | -#ifndef CONFIG_INLINE_WRITE_LOCK_IRQSAVE | |
301 | -unsigned long __lockfunc _raw_write_lock_irqsave(rwlock_t *lock) | |
302 | -{ | |
303 | - return __raw_write_lock_irqsave(lock); | |
304 | -} | |
305 | -EXPORT_SYMBOL(_raw_write_lock_irqsave); | |
306 | -#endif | |
307 | - | |
308 | -#ifndef CONFIG_INLINE_WRITE_LOCK_IRQ | |
309 | -void __lockfunc _raw_write_lock_irq(rwlock_t *lock) | |
310 | -{ | |
311 | - __raw_write_lock_irq(lock); | |
312 | -} | |
313 | -EXPORT_SYMBOL(_raw_write_lock_irq); | |
314 | -#endif | |
315 | - | |
316 | -#ifndef CONFIG_INLINE_WRITE_LOCK_BH | |
317 | -void __lockfunc _raw_write_lock_bh(rwlock_t *lock) | |
318 | -{ | |
319 | - __raw_write_lock_bh(lock); | |
320 | -} | |
321 | -EXPORT_SYMBOL(_raw_write_lock_bh); | |
322 | -#endif | |
323 | - | |
324 | -#ifndef CONFIG_INLINE_WRITE_UNLOCK | |
325 | -void __lockfunc _raw_write_unlock(rwlock_t *lock) | |
326 | -{ | |
327 | - __raw_write_unlock(lock); | |
328 | -} | |
329 | -EXPORT_SYMBOL(_raw_write_unlock); | |
330 | -#endif | |
331 | - | |
332 | -#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE | |
333 | -void __lockfunc _raw_write_unlock_irqrestore(rwlock_t *lock, unsigned long flags) | |
334 | -{ | |
335 | - __raw_write_unlock_irqrestore(lock, flags); | |
336 | -} | |
337 | -EXPORT_SYMBOL(_raw_write_unlock_irqrestore); | |
338 | -#endif | |
339 | - | |
340 | -#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQ | |
341 | -void __lockfunc _raw_write_unlock_irq(rwlock_t *lock) | |
342 | -{ | |
343 | - __raw_write_unlock_irq(lock); | |
344 | -} | |
345 | -EXPORT_SYMBOL(_raw_write_unlock_irq); | |
346 | -#endif | |
347 | - | |
348 | -#ifndef CONFIG_INLINE_WRITE_UNLOCK_BH | |
349 | -void __lockfunc _raw_write_unlock_bh(rwlock_t *lock) | |
350 | -{ | |
351 | - __raw_write_unlock_bh(lock); | |
352 | -} | |
353 | -EXPORT_SYMBOL(_raw_write_unlock_bh); | |
354 | -#endif | |
355 | - | |
356 | -#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
357 | - | |
358 | -void __lockfunc _raw_spin_lock_nested(raw_spinlock_t *lock, int subclass) | |
359 | -{ | |
360 | - preempt_disable(); | |
361 | - spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | |
362 | - LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); | |
363 | -} | |
364 | -EXPORT_SYMBOL(_raw_spin_lock_nested); | |
365 | - | |
366 | -unsigned long __lockfunc _raw_spin_lock_irqsave_nested(raw_spinlock_t *lock, | |
367 | - int subclass) | |
368 | -{ | |
369 | - unsigned long flags; | |
370 | - | |
371 | - local_irq_save(flags); | |
372 | - preempt_disable(); | |
373 | - spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | |
374 | - LOCK_CONTENDED_FLAGS(lock, do_raw_spin_trylock, do_raw_spin_lock, | |
375 | - do_raw_spin_lock_flags, &flags); | |
376 | - return flags; | |
377 | -} | |
378 | -EXPORT_SYMBOL(_raw_spin_lock_irqsave_nested); | |
379 | - | |
380 | -void __lockfunc _raw_spin_lock_nest_lock(raw_spinlock_t *lock, | |
381 | - struct lockdep_map *nest_lock) | |
382 | -{ | |
383 | - preempt_disable(); | |
384 | - spin_acquire_nest(&lock->dep_map, 0, 0, nest_lock, _RET_IP_); | |
385 | - LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock); | |
386 | -} | |
387 | -EXPORT_SYMBOL(_raw_spin_lock_nest_lock); | |
388 | - | |
389 | -#endif | |
390 | - | |
391 | -notrace int in_lock_functions(unsigned long addr) | |
392 | -{ | |
393 | - /* Linker adds these: start and end of __lockfunc functions */ | |
394 | - extern char __lock_text_start[], __lock_text_end[]; | |
395 | - | |
396 | - return addr >= (unsigned long)__lock_text_start | |
397 | - && addr < (unsigned long)__lock_text_end; | |
398 | -} | |
399 | -EXPORT_SYMBOL(in_lock_functions); |
lib/Makefile
... | ... | @@ -42,7 +42,6 @@ |
42 | 42 | obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o |
43 | 43 | obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o |
44 | 44 | obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o |
45 | -obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock_debug.o | |
46 | 45 | lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o |
47 | 46 | lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o |
48 | 47 | lib-$(CONFIG_PERCPU_RWSEM) += percpu-rwsem.o |
lib/spinlock_debug.c
1 | -/* | |
2 | - * Copyright 2005, Red Hat, Inc., Ingo Molnar | |
3 | - * Released under the General Public License (GPL). | |
4 | - * | |
5 | - * This file contains the spinlock/rwlock implementations for | |
6 | - * DEBUG_SPINLOCK. | |
7 | - */ | |
8 | - | |
9 | -#include <linux/spinlock.h> | |
10 | -#include <linux/nmi.h> | |
11 | -#include <linux/interrupt.h> | |
12 | -#include <linux/debug_locks.h> | |
13 | -#include <linux/delay.h> | |
14 | -#include <linux/export.h> | |
15 | - | |
16 | -void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, | |
17 | - struct lock_class_key *key) | |
18 | -{ | |
19 | -#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
20 | - /* | |
21 | - * Make sure we are not reinitializing a held lock: | |
22 | - */ | |
23 | - debug_check_no_locks_freed((void *)lock, sizeof(*lock)); | |
24 | - lockdep_init_map(&lock->dep_map, name, key, 0); | |
25 | -#endif | |
26 | - lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; | |
27 | - lock->magic = SPINLOCK_MAGIC; | |
28 | - lock->owner = SPINLOCK_OWNER_INIT; | |
29 | - lock->owner_cpu = -1; | |
30 | -} | |
31 | - | |
32 | -EXPORT_SYMBOL(__raw_spin_lock_init); | |
33 | - | |
34 | -void __rwlock_init(rwlock_t *lock, const char *name, | |
35 | - struct lock_class_key *key) | |
36 | -{ | |
37 | -#ifdef CONFIG_DEBUG_LOCK_ALLOC | |
38 | - /* | |
39 | - * Make sure we are not reinitializing a held lock: | |
40 | - */ | |
41 | - debug_check_no_locks_freed((void *)lock, sizeof(*lock)); | |
42 | - lockdep_init_map(&lock->dep_map, name, key, 0); | |
43 | -#endif | |
44 | - lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED; | |
45 | - lock->magic = RWLOCK_MAGIC; | |
46 | - lock->owner = SPINLOCK_OWNER_INIT; | |
47 | - lock->owner_cpu = -1; | |
48 | -} | |
49 | - | |
50 | -EXPORT_SYMBOL(__rwlock_init); | |
51 | - | |
52 | -static void spin_dump(raw_spinlock_t *lock, const char *msg) | |
53 | -{ | |
54 | - struct task_struct *owner = NULL; | |
55 | - | |
56 | - if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) | |
57 | - owner = lock->owner; | |
58 | - printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n", | |
59 | - msg, raw_smp_processor_id(), | |
60 | - current->comm, task_pid_nr(current)); | |
61 | - printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, " | |
62 | - ".owner_cpu: %d\n", | |
63 | - lock, lock->magic, | |
64 | - owner ? owner->comm : "<none>", | |
65 | - owner ? task_pid_nr(owner) : -1, | |
66 | - lock->owner_cpu); | |
67 | - dump_stack(); | |
68 | -} | |
69 | - | |
70 | -static void spin_bug(raw_spinlock_t *lock, const char *msg) | |
71 | -{ | |
72 | - if (!debug_locks_off()) | |
73 | - return; | |
74 | - | |
75 | - spin_dump(lock, msg); | |
76 | -} | |
77 | - | |
78 | -#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) | |
79 | - | |
80 | -static inline void | |
81 | -debug_spin_lock_before(raw_spinlock_t *lock) | |
82 | -{ | |
83 | - SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | |
84 | - SPIN_BUG_ON(lock->owner == current, lock, "recursion"); | |
85 | - SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | |
86 | - lock, "cpu recursion"); | |
87 | -} | |
88 | - | |
89 | -static inline void debug_spin_lock_after(raw_spinlock_t *lock) | |
90 | -{ | |
91 | - lock->owner_cpu = raw_smp_processor_id(); | |
92 | - lock->owner = current; | |
93 | -} | |
94 | - | |
95 | -static inline void debug_spin_unlock(raw_spinlock_t *lock) | |
96 | -{ | |
97 | - SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | |
98 | - SPIN_BUG_ON(!raw_spin_is_locked(lock), lock, "already unlocked"); | |
99 | - SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); | |
100 | - SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | |
101 | - lock, "wrong CPU"); | |
102 | - lock->owner = SPINLOCK_OWNER_INIT; | |
103 | - lock->owner_cpu = -1; | |
104 | -} | |
105 | - | |
106 | -static void __spin_lock_debug(raw_spinlock_t *lock) | |
107 | -{ | |
108 | - u64 i; | |
109 | - u64 loops = loops_per_jiffy * HZ; | |
110 | - | |
111 | - for (i = 0; i < loops; i++) { | |
112 | - if (arch_spin_trylock(&lock->raw_lock)) | |
113 | - return; | |
114 | - __delay(1); | |
115 | - } | |
116 | - /* lockup suspected: */ | |
117 | - spin_dump(lock, "lockup suspected"); | |
118 | -#ifdef CONFIG_SMP | |
119 | - trigger_all_cpu_backtrace(); | |
120 | -#endif | |
121 | - | |
122 | - /* | |
123 | - * The trylock above was causing a livelock. Give the lower level arch | |
124 | - * specific lock code a chance to acquire the lock. We have already | |
125 | - * printed a warning/backtrace at this point. The non-debug arch | |
126 | - * specific code might actually succeed in acquiring the lock. If it is | |
127 | - * not successful, the end-result is the same - there is no forward | |
128 | - * progress. | |
129 | - */ | |
130 | - arch_spin_lock(&lock->raw_lock); | |
131 | -} | |
132 | - | |
133 | -void do_raw_spin_lock(raw_spinlock_t *lock) | |
134 | -{ | |
135 | - debug_spin_lock_before(lock); | |
136 | - if (unlikely(!arch_spin_trylock(&lock->raw_lock))) | |
137 | - __spin_lock_debug(lock); | |
138 | - debug_spin_lock_after(lock); | |
139 | -} | |
140 | - | |
141 | -int do_raw_spin_trylock(raw_spinlock_t *lock) | |
142 | -{ | |
143 | - int ret = arch_spin_trylock(&lock->raw_lock); | |
144 | - | |
145 | - if (ret) | |
146 | - debug_spin_lock_after(lock); | |
147 | -#ifndef CONFIG_SMP | |
148 | - /* | |
149 | - * Must not happen on UP: | |
150 | - */ | |
151 | - SPIN_BUG_ON(!ret, lock, "trylock failure on UP"); | |
152 | -#endif | |
153 | - return ret; | |
154 | -} | |
155 | - | |
156 | -void do_raw_spin_unlock(raw_spinlock_t *lock) | |
157 | -{ | |
158 | - debug_spin_unlock(lock); | |
159 | - arch_spin_unlock(&lock->raw_lock); | |
160 | -} | |
161 | - | |
162 | -static void rwlock_bug(rwlock_t *lock, const char *msg) | |
163 | -{ | |
164 | - if (!debug_locks_off()) | |
165 | - return; | |
166 | - | |
167 | - printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n", | |
168 | - msg, raw_smp_processor_id(), current->comm, | |
169 | - task_pid_nr(current), lock); | |
170 | - dump_stack(); | |
171 | -} | |
172 | - | |
173 | -#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) | |
174 | - | |
175 | -#if 0 /* __write_lock_debug() can lock up - maybe this can too? */ | |
176 | -static void __read_lock_debug(rwlock_t *lock) | |
177 | -{ | |
178 | - u64 i; | |
179 | - u64 loops = loops_per_jiffy * HZ; | |
180 | - int print_once = 1; | |
181 | - | |
182 | - for (;;) { | |
183 | - for (i = 0; i < loops; i++) { | |
184 | - if (arch_read_trylock(&lock->raw_lock)) | |
185 | - return; | |
186 | - __delay(1); | |
187 | - } | |
188 | - /* lockup suspected: */ | |
189 | - if (print_once) { | |
190 | - print_once = 0; | |
191 | - printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, " | |
192 | - "%s/%d, %p\n", | |
193 | - raw_smp_processor_id(), current->comm, | |
194 | - current->pid, lock); | |
195 | - dump_stack(); | |
196 | - } | |
197 | - } | |
198 | -} | |
199 | -#endif | |
200 | - | |
201 | -void do_raw_read_lock(rwlock_t *lock) | |
202 | -{ | |
203 | - RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
204 | - arch_read_lock(&lock->raw_lock); | |
205 | -} | |
206 | - | |
207 | -int do_raw_read_trylock(rwlock_t *lock) | |
208 | -{ | |
209 | - int ret = arch_read_trylock(&lock->raw_lock); | |
210 | - | |
211 | -#ifndef CONFIG_SMP | |
212 | - /* | |
213 | - * Must not happen on UP: | |
214 | - */ | |
215 | - RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | |
216 | -#endif | |
217 | - return ret; | |
218 | -} | |
219 | - | |
220 | -void do_raw_read_unlock(rwlock_t *lock) | |
221 | -{ | |
222 | - RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
223 | - arch_read_unlock(&lock->raw_lock); | |
224 | -} | |
225 | - | |
226 | -static inline void debug_write_lock_before(rwlock_t *lock) | |
227 | -{ | |
228 | - RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
229 | - RWLOCK_BUG_ON(lock->owner == current, lock, "recursion"); | |
230 | - RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | |
231 | - lock, "cpu recursion"); | |
232 | -} | |
233 | - | |
234 | -static inline void debug_write_lock_after(rwlock_t *lock) | |
235 | -{ | |
236 | - lock->owner_cpu = raw_smp_processor_id(); | |
237 | - lock->owner = current; | |
238 | -} | |
239 | - | |
240 | -static inline void debug_write_unlock(rwlock_t *lock) | |
241 | -{ | |
242 | - RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | |
243 | - RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); | |
244 | - RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | |
245 | - lock, "wrong CPU"); | |
246 | - lock->owner = SPINLOCK_OWNER_INIT; | |
247 | - lock->owner_cpu = -1; | |
248 | -} | |
249 | - | |
250 | -#if 0 /* This can cause lockups */ | |
251 | -static void __write_lock_debug(rwlock_t *lock) | |
252 | -{ | |
253 | - u64 i; | |
254 | - u64 loops = loops_per_jiffy * HZ; | |
255 | - int print_once = 1; | |
256 | - | |
257 | - for (;;) { | |
258 | - for (i = 0; i < loops; i++) { | |
259 | - if (arch_write_trylock(&lock->raw_lock)) | |
260 | - return; | |
261 | - __delay(1); | |
262 | - } | |
263 | - /* lockup suspected: */ | |
264 | - if (print_once) { | |
265 | - print_once = 0; | |
266 | - printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, " | |
267 | - "%s/%d, %p\n", | |
268 | - raw_smp_processor_id(), current->comm, | |
269 | - current->pid, lock); | |
270 | - dump_stack(); | |
271 | - } | |
272 | - } | |
273 | -} | |
274 | -#endif | |
275 | - | |
276 | -void do_raw_write_lock(rwlock_t *lock) | |
277 | -{ | |
278 | - debug_write_lock_before(lock); | |
279 | - arch_write_lock(&lock->raw_lock); | |
280 | - debug_write_lock_after(lock); | |
281 | -} | |
282 | - | |
283 | -int do_raw_write_trylock(rwlock_t *lock) | |
284 | -{ | |
285 | - int ret = arch_write_trylock(&lock->raw_lock); | |
286 | - | |
287 | - if (ret) | |
288 | - debug_write_lock_after(lock); | |
289 | -#ifndef CONFIG_SMP | |
290 | - /* | |
291 | - * Must not happen on UP: | |
292 | - */ | |
293 | - RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | |
294 | -#endif | |
295 | - return ret; | |
296 | -} | |
297 | - | |
298 | -void do_raw_write_unlock(rwlock_t *lock) | |
299 | -{ | |
300 | - debug_write_unlock(lock); | |
301 | - arch_write_unlock(&lock->raw_lock); | |
302 | -} |