diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-07-03 03:24:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-03 18:27:04 -0400 |
commit | 8a25d5debff2daee280e83e09d8c25d67c26a972 (patch) | |
tree | 3bccfef9acb66fc62863bfd6c16493c5e8c8e394 /kernel/spinlock.c | |
parent | 4ea2176dfa714882e88180b474e4cbcd888b70af (diff) |
[PATCH] lockdep: prove spinlock rwlock locking correctness
Use the lock validator framework to prove spinlock and rwlock locking
correctness.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/spinlock.c')
-rw-r--r-- | kernel/spinlock.c | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/kernel/spinlock.c b/kernel/spinlock.c index b31e54eadf56..bfd6ad9c0330 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/preempt.h> | 13 | #include <linux/preempt.h> |
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/debug_locks.h> | ||
16 | #include <linux/module.h> | 17 | #include <linux/module.h> |
17 | 18 | ||
18 | /* | 19 | /* |
@@ -29,8 +30,10 @@ EXPORT_SYMBOL(generic__raw_read_trylock); | |||
29 | int __lockfunc _spin_trylock(spinlock_t *lock) | 30 | int __lockfunc _spin_trylock(spinlock_t *lock) |
30 | { | 31 | { |
31 | preempt_disable(); | 32 | preempt_disable(); |
32 | if (_raw_spin_trylock(lock)) | 33 | if (_raw_spin_trylock(lock)) { |
34 | spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); | ||
33 | return 1; | 35 | return 1; |
36 | } | ||
34 | 37 | ||
35 | preempt_enable(); | 38 | preempt_enable(); |
36 | return 0; | 39 | return 0; |
@@ -40,8 +43,10 @@ EXPORT_SYMBOL(_spin_trylock); | |||
40 | int __lockfunc _read_trylock(rwlock_t *lock) | 43 | int __lockfunc _read_trylock(rwlock_t *lock) |
41 | { | 44 | { |
42 | preempt_disable(); | 45 | preempt_disable(); |
43 | if (_raw_read_trylock(lock)) | 46 | if (_raw_read_trylock(lock)) { |
47 | rwlock_acquire_read(&lock->dep_map, 0, 1, _RET_IP_); | ||
44 | return 1; | 48 | return 1; |
49 | } | ||
45 | 50 | ||
46 | preempt_enable(); | 51 | preempt_enable(); |
47 | return 0; | 52 | return 0; |
@@ -51,19 +56,28 @@ EXPORT_SYMBOL(_read_trylock); | |||
51 | int __lockfunc _write_trylock(rwlock_t *lock) | 56 | int __lockfunc _write_trylock(rwlock_t *lock) |
52 | { | 57 | { |
53 | preempt_disable(); | 58 | preempt_disable(); |
54 | if (_raw_write_trylock(lock)) | 59 | if (_raw_write_trylock(lock)) { |
60 | rwlock_acquire(&lock->dep_map, 0, 1, _RET_IP_); | ||
55 | return 1; | 61 | return 1; |
62 | } | ||
56 | 63 | ||
57 | preempt_enable(); | 64 | preempt_enable(); |
58 | return 0; | 65 | return 0; |
59 | } | 66 | } |
60 | EXPORT_SYMBOL(_write_trylock); | 67 | EXPORT_SYMBOL(_write_trylock); |
61 | 68 | ||
62 | #if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) | 69 | /* |
70 | * If lockdep is enabled then we use the non-preemption spin-ops | ||
71 | * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are | ||
72 | * not re-enabled during lock-acquire (which the preempt-spin-ops do): | ||
73 | */ | ||
74 | #if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) || \ | ||
75 | defined(CONFIG_PROVE_LOCKING) | ||
63 | 76 | ||
64 | void __lockfunc _read_lock(rwlock_t *lock) | 77 | void __lockfunc _read_lock(rwlock_t *lock) |
65 | { | 78 | { |
66 | preempt_disable(); | 79 | preempt_disable(); |
80 | rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); | ||
67 | _raw_read_lock(lock); | 81 | _raw_read_lock(lock); |
68 | } | 82 | } |
69 | EXPORT_SYMBOL(_read_lock); | 83 | EXPORT_SYMBOL(_read_lock); |
@@ -74,7 +88,17 @@ unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock) | |||
74 | 88 | ||
75 | local_irq_save(flags); | 89 | local_irq_save(flags); |
76 | preempt_disable(); | 90 | preempt_disable(); |
91 | spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
92 | /* | ||
93 | * On lockdep we dont want the hand-coded irq-enable of | ||
94 | * _raw_spin_lock_flags() code, because lockdep assumes | ||
95 | * that interrupts are not re-enabled during lock-acquire: | ||
96 | */ | ||
97 | #ifdef CONFIG_PROVE_LOCKING | ||
98 | _raw_spin_lock(lock); | ||
99 | #else | ||
77 | _raw_spin_lock_flags(lock, &flags); | 100 | _raw_spin_lock_flags(lock, &flags); |
101 | #endif | ||
78 | return flags; | 102 | return flags; |
79 | } | 103 | } |
80 | EXPORT_SYMBOL(_spin_lock_irqsave); | 104 | EXPORT_SYMBOL(_spin_lock_irqsave); |
@@ -83,6 +107,7 @@ void __lockfunc _spin_lock_irq(spinlock_t *lock) | |||
83 | { | 107 | { |
84 | local_irq_disable(); | 108 | local_irq_disable(); |
85 | preempt_disable(); | 109 | preempt_disable(); |
110 | spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
86 | _raw_spin_lock(lock); | 111 | _raw_spin_lock(lock); |
87 | } | 112 | } |
88 | EXPORT_SYMBOL(_spin_lock_irq); | 113 | EXPORT_SYMBOL(_spin_lock_irq); |
@@ -91,6 +116,7 @@ void __lockfunc _spin_lock_bh(spinlock_t *lock) | |||
91 | { | 116 | { |
92 | local_bh_disable(); | 117 | local_bh_disable(); |
93 | preempt_disable(); | 118 | preempt_disable(); |
119 | spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
94 | _raw_spin_lock(lock); | 120 | _raw_spin_lock(lock); |
95 | } | 121 | } |
96 | EXPORT_SYMBOL(_spin_lock_bh); | 122 | EXPORT_SYMBOL(_spin_lock_bh); |
@@ -101,6 +127,7 @@ unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock) | |||
101 | 127 | ||
102 | local_irq_save(flags); | 128 | local_irq_save(flags); |
103 | preempt_disable(); | 129 | preempt_disable(); |
130 | rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); | ||
104 | _raw_read_lock(lock); | 131 | _raw_read_lock(lock); |
105 | return flags; | 132 | return flags; |
106 | } | 133 | } |
@@ -110,6 +137,7 @@ void __lockfunc _read_lock_irq(rwlock_t *lock) | |||
110 | { | 137 | { |
111 | local_irq_disable(); | 138 | local_irq_disable(); |
112 | preempt_disable(); | 139 | preempt_disable(); |
140 | rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); | ||
113 | _raw_read_lock(lock); | 141 | _raw_read_lock(lock); |
114 | } | 142 | } |
115 | EXPORT_SYMBOL(_read_lock_irq); | 143 | EXPORT_SYMBOL(_read_lock_irq); |
@@ -118,6 +146,7 @@ void __lockfunc _read_lock_bh(rwlock_t *lock) | |||
118 | { | 146 | { |
119 | local_bh_disable(); | 147 | local_bh_disable(); |
120 | preempt_disable(); | 148 | preempt_disable(); |
149 | rwlock_acquire_read(&lock->dep_map, 0, 0, _RET_IP_); | ||
121 | _raw_read_lock(lock); | 150 | _raw_read_lock(lock); |
122 | } | 151 | } |
123 | EXPORT_SYMBOL(_read_lock_bh); | 152 | EXPORT_SYMBOL(_read_lock_bh); |
@@ -128,6 +157,7 @@ unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock) | |||
128 | 157 | ||
129 | local_irq_save(flags); | 158 | local_irq_save(flags); |
130 | preempt_disable(); | 159 | preempt_disable(); |
160 | rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
131 | _raw_write_lock(lock); | 161 | _raw_write_lock(lock); |
132 | return flags; | 162 | return flags; |
133 | } | 163 | } |
@@ -137,6 +167,7 @@ void __lockfunc _write_lock_irq(rwlock_t *lock) | |||
137 | { | 167 | { |
138 | local_irq_disable(); | 168 | local_irq_disable(); |
139 | preempt_disable(); | 169 | preempt_disable(); |
170 | rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
140 | _raw_write_lock(lock); | 171 | _raw_write_lock(lock); |
141 | } | 172 | } |
142 | EXPORT_SYMBOL(_write_lock_irq); | 173 | EXPORT_SYMBOL(_write_lock_irq); |
@@ -145,6 +176,7 @@ void __lockfunc _write_lock_bh(rwlock_t *lock) | |||
145 | { | 176 | { |
146 | local_bh_disable(); | 177 | local_bh_disable(); |
147 | preempt_disable(); | 178 | preempt_disable(); |
179 | rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
148 | _raw_write_lock(lock); | 180 | _raw_write_lock(lock); |
149 | } | 181 | } |
150 | EXPORT_SYMBOL(_write_lock_bh); | 182 | EXPORT_SYMBOL(_write_lock_bh); |
@@ -152,6 +184,7 @@ EXPORT_SYMBOL(_write_lock_bh); | |||
152 | void __lockfunc _spin_lock(spinlock_t *lock) | 184 | void __lockfunc _spin_lock(spinlock_t *lock) |
153 | { | 185 | { |
154 | preempt_disable(); | 186 | preempt_disable(); |
187 | spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
155 | _raw_spin_lock(lock); | 188 | _raw_spin_lock(lock); |
156 | } | 189 | } |
157 | 190 | ||
@@ -160,6 +193,7 @@ EXPORT_SYMBOL(_spin_lock); | |||
160 | void __lockfunc _write_lock(rwlock_t *lock) | 193 | void __lockfunc _write_lock(rwlock_t *lock) |
161 | { | 194 | { |
162 | preempt_disable(); | 195 | preempt_disable(); |
196 | rwlock_acquire(&lock->dep_map, 0, 0, _RET_IP_); | ||
163 | _raw_write_lock(lock); | 197 | _raw_write_lock(lock); |
164 | } | 198 | } |
165 | 199 | ||
@@ -255,8 +289,22 @@ BUILD_LOCK_OPS(write, rwlock); | |||
255 | 289 | ||
256 | #endif /* CONFIG_PREEMPT */ | 290 | #endif /* CONFIG_PREEMPT */ |
257 | 291 | ||
292 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
293 | |||
294 | void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass) | ||
295 | { | ||
296 | preempt_disable(); | ||
297 | spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_); | ||
298 | _raw_spin_lock(lock); | ||
299 | } | ||
300 | |||
301 | EXPORT_SYMBOL(_spin_lock_nested); | ||
302 | |||
303 | #endif | ||
304 | |||
258 | void __lockfunc _spin_unlock(spinlock_t *lock) | 305 | void __lockfunc _spin_unlock(spinlock_t *lock) |
259 | { | 306 | { |
307 | spin_release(&lock->dep_map, 1, _RET_IP_); | ||
260 | _raw_spin_unlock(lock); | 308 | _raw_spin_unlock(lock); |
261 | preempt_enable(); | 309 | preempt_enable(); |
262 | } | 310 | } |
@@ -264,6 +312,7 @@ EXPORT_SYMBOL(_spin_unlock); | |||
264 | 312 | ||
265 | void __lockfunc _write_unlock(rwlock_t *lock) | 313 | void __lockfunc _write_unlock(rwlock_t *lock) |
266 | { | 314 | { |
315 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
267 | _raw_write_unlock(lock); | 316 | _raw_write_unlock(lock); |
268 | preempt_enable(); | 317 | preempt_enable(); |
269 | } | 318 | } |
@@ -271,6 +320,7 @@ EXPORT_SYMBOL(_write_unlock); | |||
271 | 320 | ||
272 | void __lockfunc _read_unlock(rwlock_t *lock) | 321 | void __lockfunc _read_unlock(rwlock_t *lock) |
273 | { | 322 | { |
323 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
274 | _raw_read_unlock(lock); | 324 | _raw_read_unlock(lock); |
275 | preempt_enable(); | 325 | preempt_enable(); |
276 | } | 326 | } |
@@ -278,6 +328,7 @@ EXPORT_SYMBOL(_read_unlock); | |||
278 | 328 | ||
279 | void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) | 329 | void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) |
280 | { | 330 | { |
331 | spin_release(&lock->dep_map, 1, _RET_IP_); | ||
281 | _raw_spin_unlock(lock); | 332 | _raw_spin_unlock(lock); |
282 | local_irq_restore(flags); | 333 | local_irq_restore(flags); |
283 | preempt_enable(); | 334 | preempt_enable(); |
@@ -286,6 +337,7 @@ EXPORT_SYMBOL(_spin_unlock_irqrestore); | |||
286 | 337 | ||
287 | void __lockfunc _spin_unlock_irq(spinlock_t *lock) | 338 | void __lockfunc _spin_unlock_irq(spinlock_t *lock) |
288 | { | 339 | { |
340 | spin_release(&lock->dep_map, 1, _RET_IP_); | ||
289 | _raw_spin_unlock(lock); | 341 | _raw_spin_unlock(lock); |
290 | local_irq_enable(); | 342 | local_irq_enable(); |
291 | preempt_enable(); | 343 | preempt_enable(); |
@@ -294,14 +346,16 @@ EXPORT_SYMBOL(_spin_unlock_irq); | |||
294 | 346 | ||
295 | void __lockfunc _spin_unlock_bh(spinlock_t *lock) | 347 | void __lockfunc _spin_unlock_bh(spinlock_t *lock) |
296 | { | 348 | { |
349 | spin_release(&lock->dep_map, 1, _RET_IP_); | ||
297 | _raw_spin_unlock(lock); | 350 | _raw_spin_unlock(lock); |
298 | preempt_enable_no_resched(); | 351 | preempt_enable_no_resched(); |
299 | local_bh_enable(); | 352 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); |
300 | } | 353 | } |
301 | EXPORT_SYMBOL(_spin_unlock_bh); | 354 | EXPORT_SYMBOL(_spin_unlock_bh); |
302 | 355 | ||
303 | void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) | 356 | void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags) |
304 | { | 357 | { |
358 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
305 | _raw_read_unlock(lock); | 359 | _raw_read_unlock(lock); |
306 | local_irq_restore(flags); | 360 | local_irq_restore(flags); |
307 | preempt_enable(); | 361 | preempt_enable(); |
@@ -310,6 +364,7 @@ EXPORT_SYMBOL(_read_unlock_irqrestore); | |||
310 | 364 | ||
311 | void __lockfunc _read_unlock_irq(rwlock_t *lock) | 365 | void __lockfunc _read_unlock_irq(rwlock_t *lock) |
312 | { | 366 | { |
367 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
313 | _raw_read_unlock(lock); | 368 | _raw_read_unlock(lock); |
314 | local_irq_enable(); | 369 | local_irq_enable(); |
315 | preempt_enable(); | 370 | preempt_enable(); |
@@ -318,14 +373,16 @@ EXPORT_SYMBOL(_read_unlock_irq); | |||
318 | 373 | ||
319 | void __lockfunc _read_unlock_bh(rwlock_t *lock) | 374 | void __lockfunc _read_unlock_bh(rwlock_t *lock) |
320 | { | 375 | { |
376 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
321 | _raw_read_unlock(lock); | 377 | _raw_read_unlock(lock); |
322 | preempt_enable_no_resched(); | 378 | preempt_enable_no_resched(); |
323 | local_bh_enable(); | 379 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); |
324 | } | 380 | } |
325 | EXPORT_SYMBOL(_read_unlock_bh); | 381 | EXPORT_SYMBOL(_read_unlock_bh); |
326 | 382 | ||
327 | void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags) | 383 | void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags) |
328 | { | 384 | { |
385 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
329 | _raw_write_unlock(lock); | 386 | _raw_write_unlock(lock); |
330 | local_irq_restore(flags); | 387 | local_irq_restore(flags); |
331 | preempt_enable(); | 388 | preempt_enable(); |
@@ -334,6 +391,7 @@ EXPORT_SYMBOL(_write_unlock_irqrestore); | |||
334 | 391 | ||
335 | void __lockfunc _write_unlock_irq(rwlock_t *lock) | 392 | void __lockfunc _write_unlock_irq(rwlock_t *lock) |
336 | { | 393 | { |
394 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
337 | _raw_write_unlock(lock); | 395 | _raw_write_unlock(lock); |
338 | local_irq_enable(); | 396 | local_irq_enable(); |
339 | preempt_enable(); | 397 | preempt_enable(); |
@@ -342,9 +400,10 @@ EXPORT_SYMBOL(_write_unlock_irq); | |||
342 | 400 | ||
343 | void __lockfunc _write_unlock_bh(rwlock_t *lock) | 401 | void __lockfunc _write_unlock_bh(rwlock_t *lock) |
344 | { | 402 | { |
403 | rwlock_release(&lock->dep_map, 1, _RET_IP_); | ||
345 | _raw_write_unlock(lock); | 404 | _raw_write_unlock(lock); |
346 | preempt_enable_no_resched(); | 405 | preempt_enable_no_resched(); |
347 | local_bh_enable(); | 406 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); |
348 | } | 407 | } |
349 | EXPORT_SYMBOL(_write_unlock_bh); | 408 | EXPORT_SYMBOL(_write_unlock_bh); |
350 | 409 | ||
@@ -352,11 +411,13 @@ int __lockfunc _spin_trylock_bh(spinlock_t *lock) | |||
352 | { | 411 | { |
353 | local_bh_disable(); | 412 | local_bh_disable(); |
354 | preempt_disable(); | 413 | preempt_disable(); |
355 | if (_raw_spin_trylock(lock)) | 414 | if (_raw_spin_trylock(lock)) { |
415 | spin_acquire(&lock->dep_map, 0, 1, _RET_IP_); | ||
356 | return 1; | 416 | return 1; |
417 | } | ||
357 | 418 | ||
358 | preempt_enable_no_resched(); | 419 | preempt_enable_no_resched(); |
359 | local_bh_enable(); | 420 | local_bh_enable_ip((unsigned long)__builtin_return_address(0)); |
360 | return 0; | 421 | return 0; |
361 | } | 422 | } |
362 | EXPORT_SYMBOL(_spin_trylock_bh); | 423 | EXPORT_SYMBOL(_spin_trylock_bh); |