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 /include/linux | |
| 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 'include/linux')
| -rw-r--r-- | include/linux/spinlock.h | 63 | ||||
| -rw-r--r-- | include/linux/spinlock_api_smp.h | 2 | ||||
| -rw-r--r-- | include/linux/spinlock_api_up.h | 1 | ||||
| -rw-r--r-- | include/linux/spinlock_types.h | 32 | ||||
| -rw-r--r-- | include/linux/spinlock_types_up.h | 9 | ||||
| -rw-r--r-- | include/linux/spinlock_up.h | 1 |
6 files changed, 85 insertions, 23 deletions
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index ae23beef9cc9..31473db92d3b 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
| @@ -82,14 +82,40 @@ extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); | |||
| 82 | /* | 82 | /* |
| 83 | * Pull the __raw*() functions/declarations (UP-nondebug doesnt need them): | 83 | * Pull the __raw*() functions/declarations (UP-nondebug doesnt need them): |
| 84 | */ | 84 | */ |
| 85 | #if defined(CONFIG_SMP) | 85 | #ifdef CONFIG_SMP |
| 86 | # include <asm/spinlock.h> | 86 | # include <asm/spinlock.h> |
| 87 | #else | 87 | #else |
| 88 | # include <linux/spinlock_up.h> | 88 | # include <linux/spinlock_up.h> |
| 89 | #endif | 89 | #endif |
| 90 | 90 | ||
| 91 | #define spin_lock_init(lock) do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0) | 91 | #ifdef CONFIG_DEBUG_SPINLOCK |
| 92 | #define rwlock_init(lock) do { *(lock) = RW_LOCK_UNLOCKED; } while (0) | 92 | extern void __spin_lock_init(spinlock_t *lock, const char *name, |
| 93 | struct lock_class_key *key); | ||
| 94 | # define spin_lock_init(lock) \ | ||
| 95 | do { \ | ||
| 96 | static struct lock_class_key __key; \ | ||
| 97 | \ | ||
| 98 | __spin_lock_init((lock), #lock, &__key); \ | ||
| 99 | } while (0) | ||
| 100 | |||
| 101 | #else | ||
| 102 | # define spin_lock_init(lock) \ | ||
| 103 | do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0) | ||
| 104 | #endif | ||
| 105 | |||
| 106 | #ifdef CONFIG_DEBUG_SPINLOCK | ||
| 107 | extern void __rwlock_init(rwlock_t *lock, const char *name, | ||
| 108 | struct lock_class_key *key); | ||
| 109 | # define rwlock_init(lock) \ | ||
| 110 | do { \ | ||
| 111 | static struct lock_class_key __key; \ | ||
| 112 | \ | ||
| 113 | __rwlock_init((lock), #lock, &__key); \ | ||
| 114 | } while (0) | ||
| 115 | #else | ||
| 116 | # define rwlock_init(lock) \ | ||
| 117 | do { *(lock) = RW_LOCK_UNLOCKED; } while (0) | ||
| 118 | #endif | ||
| 93 | 119 | ||
| 94 | #define spin_is_locked(lock) __raw_spin_is_locked(&(lock)->raw_lock) | 120 | #define spin_is_locked(lock) __raw_spin_is_locked(&(lock)->raw_lock) |
| 95 | 121 | ||
| @@ -113,7 +139,6 @@ extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); | |||
| 113 | #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock) | 139 | #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock) |
| 114 | extern int _raw_spin_trylock(spinlock_t *lock); | 140 | extern int _raw_spin_trylock(spinlock_t *lock); |
| 115 | extern void _raw_spin_unlock(spinlock_t *lock); | 141 | extern void _raw_spin_unlock(spinlock_t *lock); |
| 116 | |||
| 117 | extern void _raw_read_lock(rwlock_t *lock); | 142 | extern void _raw_read_lock(rwlock_t *lock); |
| 118 | extern int _raw_read_trylock(rwlock_t *lock); | 143 | extern int _raw_read_trylock(rwlock_t *lock); |
| 119 | extern void _raw_read_unlock(rwlock_t *lock); | 144 | extern void _raw_read_unlock(rwlock_t *lock); |
| @@ -121,17 +146,17 @@ extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); | |||
| 121 | extern int _raw_write_trylock(rwlock_t *lock); | 146 | extern int _raw_write_trylock(rwlock_t *lock); |
| 122 | extern void _raw_write_unlock(rwlock_t *lock); | 147 | extern void _raw_write_unlock(rwlock_t *lock); |
| 123 | #else | 148 | #else |
| 124 | # define _raw_spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock) | ||
| 125 | # define _raw_spin_trylock(lock) __raw_spin_trylock(&(lock)->raw_lock) | ||
| 126 | # define _raw_spin_lock(lock) __raw_spin_lock(&(lock)->raw_lock) | 149 | # define _raw_spin_lock(lock) __raw_spin_lock(&(lock)->raw_lock) |
| 127 | # define _raw_spin_lock_flags(lock, flags) \ | 150 | # define _raw_spin_lock_flags(lock, flags) \ |
| 128 | __raw_spin_lock_flags(&(lock)->raw_lock, *(flags)) | 151 | __raw_spin_lock_flags(&(lock)->raw_lock, *(flags)) |
| 152 | # define _raw_spin_trylock(lock) __raw_spin_trylock(&(lock)->raw_lock) | ||
| 153 | # define _raw_spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock) | ||
| 129 | # define _raw_read_lock(rwlock) __raw_read_lock(&(rwlock)->raw_lock) | 154 | # define _raw_read_lock(rwlock) __raw_read_lock(&(rwlock)->raw_lock) |
| 130 | # define _raw_write_lock(rwlock) __raw_write_lock(&(rwlock)->raw_lock) | ||
| 131 | # define _raw_read_unlock(rwlock) __raw_read_unlock(&(rwlock)->raw_lock) | ||
| 132 | # define _raw_write_unlock(rwlock) __raw_write_unlock(&(rwlock)->raw_lock) | ||
| 133 | # define _raw_read_trylock(rwlock) __raw_read_trylock(&(rwlock)->raw_lock) | 155 | # define _raw_read_trylock(rwlock) __raw_read_trylock(&(rwlock)->raw_lock) |
| 156 | # define _raw_read_unlock(rwlock) __raw_read_unlock(&(rwlock)->raw_lock) | ||
| 157 | # define _raw_write_lock(rwlock) __raw_write_lock(&(rwlock)->raw_lock) | ||
| 134 | # define _raw_write_trylock(rwlock) __raw_write_trylock(&(rwlock)->raw_lock) | 158 | # define _raw_write_trylock(rwlock) __raw_write_trylock(&(rwlock)->raw_lock) |
| 159 | # define _raw_write_unlock(rwlock) __raw_write_unlock(&(rwlock)->raw_lock) | ||
| 135 | #endif | 160 | #endif |
| 136 | 161 | ||
| 137 | #define read_can_lock(rwlock) __raw_read_can_lock(&(rwlock)->raw_lock) | 162 | #define read_can_lock(rwlock) __raw_read_can_lock(&(rwlock)->raw_lock) |
| @@ -147,6 +172,13 @@ extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); | |||
| 147 | #define write_trylock(lock) __cond_lock(_write_trylock(lock)) | 172 | #define write_trylock(lock) __cond_lock(_write_trylock(lock)) |
| 148 | 173 | ||
| 149 | #define spin_lock(lock) _spin_lock(lock) | 174 | #define spin_lock(lock) _spin_lock(lock) |
| 175 | |||
| 176 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 177 | # define spin_lock_nested(lock, subclass) _spin_lock_nested(lock, subclass) | ||
| 178 | #else | ||
| 179 | # define spin_lock_nested(lock, subclass) _spin_lock(lock) | ||
| 180 | #endif | ||
| 181 | |||
| 150 | #define write_lock(lock) _write_lock(lock) | 182 | #define write_lock(lock) _write_lock(lock) |
| 151 | #define read_lock(lock) _read_lock(lock) | 183 | #define read_lock(lock) _read_lock(lock) |
| 152 | 184 | ||
| @@ -172,21 +204,18 @@ extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); | |||
| 172 | /* | 204 | /* |
| 173 | * We inline the unlock functions in the nondebug case: | 205 | * We inline the unlock functions in the nondebug case: |
| 174 | */ | 206 | */ |
| 175 | #if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) | 207 | #if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || \ |
| 208 | !defined(CONFIG_SMP) | ||
| 176 | # define spin_unlock(lock) _spin_unlock(lock) | 209 | # define spin_unlock(lock) _spin_unlock(lock) |
| 177 | # define read_unlock(lock) _read_unlock(lock) | 210 | # define read_unlock(lock) _read_unlock(lock) |
| 178 | # define write_unlock(lock) _write_unlock(lock) | 211 | # define write_unlock(lock) _write_unlock(lock) |
| 179 | #else | ||
| 180 | # define spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock) | ||
| 181 | # define read_unlock(lock) __raw_read_unlock(&(lock)->raw_lock) | ||
| 182 | # define write_unlock(lock) __raw_write_unlock(&(lock)->raw_lock) | ||
| 183 | #endif | ||
| 184 | |||
| 185 | #if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) | ||
| 186 | # define spin_unlock_irq(lock) _spin_unlock_irq(lock) | 212 | # define spin_unlock_irq(lock) _spin_unlock_irq(lock) |
| 187 | # define read_unlock_irq(lock) _read_unlock_irq(lock) | 213 | # define read_unlock_irq(lock) _read_unlock_irq(lock) |
| 188 | # define write_unlock_irq(lock) _write_unlock_irq(lock) | 214 | # define write_unlock_irq(lock) _write_unlock_irq(lock) |
| 189 | #else | 215 | #else |
| 216 | # define spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock) | ||
| 217 | # define read_unlock(lock) __raw_read_unlock(&(lock)->raw_lock) | ||
| 218 | # define write_unlock(lock) __raw_write_unlock(&(lock)->raw_lock) | ||
| 190 | # define spin_unlock_irq(lock) \ | 219 | # define spin_unlock_irq(lock) \ |
| 191 | do { __raw_spin_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0) | 220 | do { __raw_spin_unlock(&(lock)->raw_lock); local_irq_enable(); } while (0) |
| 192 | # define read_unlock_irq(lock) \ | 221 | # define read_unlock_irq(lock) \ |
diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index 78e6989ffb54..b2c4f8299464 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h | |||
| @@ -20,6 +20,8 @@ int in_lock_functions(unsigned long addr); | |||
| 20 | #define assert_spin_locked(x) BUG_ON(!spin_is_locked(x)) | 20 | #define assert_spin_locked(x) BUG_ON(!spin_is_locked(x)) |
| 21 | 21 | ||
| 22 | void __lockfunc _spin_lock(spinlock_t *lock) __acquires(spinlock_t); | 22 | void __lockfunc _spin_lock(spinlock_t *lock) __acquires(spinlock_t); |
| 23 | void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass) | ||
| 24 | __acquires(spinlock_t); | ||
| 23 | void __lockfunc _read_lock(rwlock_t *lock) __acquires(rwlock_t); | 25 | void __lockfunc _read_lock(rwlock_t *lock) __acquires(rwlock_t); |
| 24 | void __lockfunc _write_lock(rwlock_t *lock) __acquires(rwlock_t); | 26 | void __lockfunc _write_lock(rwlock_t *lock) __acquires(rwlock_t); |
| 25 | void __lockfunc _spin_lock_bh(spinlock_t *lock) __acquires(spinlock_t); | 27 | void __lockfunc _spin_lock_bh(spinlock_t *lock) __acquires(spinlock_t); |
diff --git a/include/linux/spinlock_api_up.h b/include/linux/spinlock_api_up.h index cd81cee566f4..67faa044c5f5 100644 --- a/include/linux/spinlock_api_up.h +++ b/include/linux/spinlock_api_up.h | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | do { local_irq_restore(flags); __UNLOCK(lock); } while (0) | 49 | do { local_irq_restore(flags); __UNLOCK(lock); } while (0) |
| 50 | 50 | ||
| 51 | #define _spin_lock(lock) __LOCK(lock) | 51 | #define _spin_lock(lock) __LOCK(lock) |
| 52 | #define _spin_lock_nested(lock, subclass) __LOCK(lock) | ||
| 52 | #define _read_lock(lock) __LOCK(lock) | 53 | #define _read_lock(lock) __LOCK(lock) |
| 53 | #define _write_lock(lock) __LOCK(lock) | 54 | #define _write_lock(lock) __LOCK(lock) |
| 54 | #define _spin_lock_bh(lock) __LOCK_BH(lock) | 55 | #define _spin_lock_bh(lock) __LOCK_BH(lock) |
diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h index f5d4ed7bc785..dc5fb69e4de9 100644 --- a/include/linux/spinlock_types.h +++ b/include/linux/spinlock_types.h | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | * Released under the General Public License (GPL). | 9 | * Released under the General Public License (GPL). |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/lockdep.h> | ||
| 13 | |||
| 12 | #if defined(CONFIG_SMP) | 14 | #if defined(CONFIG_SMP) |
| 13 | # include <asm/spinlock_types.h> | 15 | # include <asm/spinlock_types.h> |
| 14 | #else | 16 | #else |
| @@ -24,6 +26,9 @@ typedef struct { | |||
| 24 | unsigned int magic, owner_cpu; | 26 | unsigned int magic, owner_cpu; |
| 25 | void *owner; | 27 | void *owner; |
| 26 | #endif | 28 | #endif |
| 29 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 30 | struct lockdep_map dep_map; | ||
| 31 | #endif | ||
| 27 | } spinlock_t; | 32 | } spinlock_t; |
| 28 | 33 | ||
| 29 | #define SPINLOCK_MAGIC 0xdead4ead | 34 | #define SPINLOCK_MAGIC 0xdead4ead |
| @@ -37,28 +42,47 @@ typedef struct { | |||
| 37 | unsigned int magic, owner_cpu; | 42 | unsigned int magic, owner_cpu; |
| 38 | void *owner; | 43 | void *owner; |
| 39 | #endif | 44 | #endif |
| 45 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 46 | struct lockdep_map dep_map; | ||
| 47 | #endif | ||
| 40 | } rwlock_t; | 48 | } rwlock_t; |
| 41 | 49 | ||
| 42 | #define RWLOCK_MAGIC 0xdeaf1eed | 50 | #define RWLOCK_MAGIC 0xdeaf1eed |
| 43 | 51 | ||
| 44 | #define SPINLOCK_OWNER_INIT ((void *)-1L) | 52 | #define SPINLOCK_OWNER_INIT ((void *)-1L) |
| 45 | 53 | ||
| 54 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 55 | # define SPIN_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname } | ||
| 56 | #else | ||
| 57 | # define SPIN_DEP_MAP_INIT(lockname) | ||
| 58 | #endif | ||
| 59 | |||
| 60 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 61 | # define RW_DEP_MAP_INIT(lockname) .dep_map = { .name = #lockname } | ||
| 62 | #else | ||
| 63 | # define RW_DEP_MAP_INIT(lockname) | ||
| 64 | #endif | ||
| 65 | |||
| 46 | #ifdef CONFIG_DEBUG_SPINLOCK | 66 | #ifdef CONFIG_DEBUG_SPINLOCK |
| 47 | # define __SPIN_LOCK_UNLOCKED(lockname) \ | 67 | # define __SPIN_LOCK_UNLOCKED(lockname) \ |
| 48 | (spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, \ | 68 | (spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, \ |
| 49 | .magic = SPINLOCK_MAGIC, \ | 69 | .magic = SPINLOCK_MAGIC, \ |
| 50 | .owner = SPINLOCK_OWNER_INIT, \ | 70 | .owner = SPINLOCK_OWNER_INIT, \ |
| 51 | .owner_cpu = -1 } | 71 | .owner_cpu = -1, \ |
| 72 | SPIN_DEP_MAP_INIT(lockname) } | ||
| 52 | #define __RW_LOCK_UNLOCKED(lockname) \ | 73 | #define __RW_LOCK_UNLOCKED(lockname) \ |
| 53 | (rwlock_t) { .raw_lock = __RAW_RW_LOCK_UNLOCKED, \ | 74 | (rwlock_t) { .raw_lock = __RAW_RW_LOCK_UNLOCKED, \ |
| 54 | .magic = RWLOCK_MAGIC, \ | 75 | .magic = RWLOCK_MAGIC, \ |
| 55 | .owner = SPINLOCK_OWNER_INIT, \ | 76 | .owner = SPINLOCK_OWNER_INIT, \ |
| 56 | .owner_cpu = -1 } | 77 | .owner_cpu = -1, \ |
| 78 | RW_DEP_MAP_INIT(lockname) } | ||
| 57 | #else | 79 | #else |
| 58 | # define __SPIN_LOCK_UNLOCKED(lockname) \ | 80 | # define __SPIN_LOCK_UNLOCKED(lockname) \ |
| 59 | (spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED } | 81 | (spinlock_t) { .raw_lock = __RAW_SPIN_LOCK_UNLOCKED, \ |
| 82 | SPIN_DEP_MAP_INIT(lockname) } | ||
| 60 | #define __RW_LOCK_UNLOCKED(lockname) \ | 83 | #define __RW_LOCK_UNLOCKED(lockname) \ |
| 61 | (rwlock_t) { .raw_lock = __RAW_RW_LOCK_UNLOCKED } | 84 | (rwlock_t) { .raw_lock = __RAW_RW_LOCK_UNLOCKED, \ |
| 85 | RW_DEP_MAP_INIT(lockname) } | ||
| 62 | #endif | 86 | #endif |
| 63 | 87 | ||
| 64 | #define SPIN_LOCK_UNLOCKED __SPIN_LOCK_UNLOCKED(old_style_spin_init) | 88 | #define SPIN_LOCK_UNLOCKED __SPIN_LOCK_UNLOCKED(old_style_spin_init) |
diff --git a/include/linux/spinlock_types_up.h b/include/linux/spinlock_types_up.h index 04135b0e198e..27644af20b7c 100644 --- a/include/linux/spinlock_types_up.h +++ b/include/linux/spinlock_types_up.h | |||
| @@ -12,10 +12,14 @@ | |||
| 12 | * Released under the General Public License (GPL). | 12 | * Released under the General Public License (GPL). |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #ifdef CONFIG_DEBUG_SPINLOCK | 15 | #if defined(CONFIG_DEBUG_SPINLOCK) || \ |
| 16 | defined(CONFIG_DEBUG_LOCK_ALLOC) | ||
| 16 | 17 | ||
| 17 | typedef struct { | 18 | typedef struct { |
| 18 | volatile unsigned int slock; | 19 | volatile unsigned int slock; |
| 20 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 21 | struct lockdep_map dep_map; | ||
| 22 | #endif | ||
| 19 | } raw_spinlock_t; | 23 | } raw_spinlock_t; |
| 20 | 24 | ||
| 21 | #define __RAW_SPIN_LOCK_UNLOCKED { 1 } | 25 | #define __RAW_SPIN_LOCK_UNLOCKED { 1 } |
| @@ -30,6 +34,9 @@ typedef struct { } raw_spinlock_t; | |||
| 30 | 34 | ||
| 31 | typedef struct { | 35 | typedef struct { |
| 32 | /* no debug version on UP */ | 36 | /* no debug version on UP */ |
| 37 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
| 38 | struct lockdep_map dep_map; | ||
| 39 | #endif | ||
| 33 | } raw_rwlock_t; | 40 | } raw_rwlock_t; |
| 34 | 41 | ||
| 35 | #define __RAW_RW_LOCK_UNLOCKED { } | 42 | #define __RAW_RW_LOCK_UNLOCKED { } |
diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h index 31accf2f0b13..ea54c4c9a4ec 100644 --- a/include/linux/spinlock_up.h +++ b/include/linux/spinlock_up.h | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #ifdef CONFIG_DEBUG_SPINLOCK | 20 | #ifdef CONFIG_DEBUG_SPINLOCK |
| 21 | |||
| 22 | #define __raw_spin_is_locked(x) ((x)->slock == 0) | 21 | #define __raw_spin_is_locked(x) ((x)->slock == 0) |
| 23 | 22 | ||
| 24 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | 23 | static inline void __raw_spin_lock(raw_spinlock_t *lock) |
