Commit bb44f116a14c4c932f15c79acfafd46bcb43ca9a
Committed by
Linus Torvalds
1 parent
391eadeec8
[PATCH] fix spinlock-debugging smp_processor_id() usage
When a spinlock debugging check hits, we print the CPU number as an informational thing - but there is no guarantee that preemption is off at that point - hence we should use raw_smp_processor_id(). Otherwise DEBUG_PREEMPT will print a warning. With this fix the warning goes away and only the spinlock-debugging info is printed. Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 1 changed file with 10 additions and 8 deletions Inline Diff
lib/spinlock_debug.c
1 | /* | 1 | /* |
2 | * Copyright 2005, Red Hat, Inc., Ingo Molnar | 2 | * Copyright 2005, Red Hat, Inc., Ingo Molnar |
3 | * Released under the General Public License (GPL). | 3 | * Released under the General Public License (GPL). |
4 | * | 4 | * |
5 | * This file contains the spinlock/rwlock implementations for | 5 | * This file contains the spinlock/rwlock implementations for |
6 | * DEBUG_SPINLOCK. | 6 | * DEBUG_SPINLOCK. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
10 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | 13 | ||
14 | static void spin_bug(spinlock_t *lock, const char *msg) | 14 | static void spin_bug(spinlock_t *lock, const char *msg) |
15 | { | 15 | { |
16 | static long print_once = 1; | 16 | static long print_once = 1; |
17 | struct task_struct *owner = NULL; | 17 | struct task_struct *owner = NULL; |
18 | 18 | ||
19 | if (xchg(&print_once, 0)) { | 19 | if (xchg(&print_once, 0)) { |
20 | if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) | 20 | if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT) |
21 | owner = lock->owner; | 21 | owner = lock->owner; |
22 | printk("BUG: spinlock %s on CPU#%d, %s/%d\n", | 22 | printk("BUG: spinlock %s on CPU#%d, %s/%d\n", |
23 | msg, smp_processor_id(), current->comm, current->pid); | 23 | msg, raw_smp_processor_id(), |
24 | current->comm, current->pid); | ||
24 | printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n", | 25 | printk(" lock: %p, .magic: %08x, .owner: %s/%d, .owner_cpu: %d\n", |
25 | lock, lock->magic, | 26 | lock, lock->magic, |
26 | owner ? owner->comm : "<none>", | 27 | owner ? owner->comm : "<none>", |
27 | owner ? owner->pid : -1, | 28 | owner ? owner->pid : -1, |
28 | lock->owner_cpu); | 29 | lock->owner_cpu); |
29 | dump_stack(); | 30 | dump_stack(); |
30 | #ifdef CONFIG_SMP | 31 | #ifdef CONFIG_SMP |
31 | /* | 32 | /* |
32 | * We cannot continue on SMP: | 33 | * We cannot continue on SMP: |
33 | */ | 34 | */ |
34 | // panic("bad locking"); | 35 | // panic("bad locking"); |
35 | #endif | 36 | #endif |
36 | } | 37 | } |
37 | } | 38 | } |
38 | 39 | ||
39 | #define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) | 40 | #define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg) |
40 | 41 | ||
41 | static inline void debug_spin_lock_before(spinlock_t *lock) | 42 | static inline void debug_spin_lock_before(spinlock_t *lock) |
42 | { | 43 | { |
43 | SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | 44 | SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); |
44 | SPIN_BUG_ON(lock->owner == current, lock, "recursion"); | 45 | SPIN_BUG_ON(lock->owner == current, lock, "recursion"); |
45 | SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | 46 | SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), |
46 | lock, "cpu recursion"); | 47 | lock, "cpu recursion"); |
47 | } | 48 | } |
48 | 49 | ||
49 | static inline void debug_spin_lock_after(spinlock_t *lock) | 50 | static inline void debug_spin_lock_after(spinlock_t *lock) |
50 | { | 51 | { |
51 | lock->owner_cpu = raw_smp_processor_id(); | 52 | lock->owner_cpu = raw_smp_processor_id(); |
52 | lock->owner = current; | 53 | lock->owner = current; |
53 | } | 54 | } |
54 | 55 | ||
55 | static inline void debug_spin_unlock(spinlock_t *lock) | 56 | static inline void debug_spin_unlock(spinlock_t *lock) |
56 | { | 57 | { |
57 | SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); | 58 | SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic"); |
58 | SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked"); | 59 | SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked"); |
59 | SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); | 60 | SPIN_BUG_ON(lock->owner != current, lock, "wrong owner"); |
60 | SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | 61 | SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), |
61 | lock, "wrong CPU"); | 62 | lock, "wrong CPU"); |
62 | lock->owner = SPINLOCK_OWNER_INIT; | 63 | lock->owner = SPINLOCK_OWNER_INIT; |
63 | lock->owner_cpu = -1; | 64 | lock->owner_cpu = -1; |
64 | } | 65 | } |
65 | 66 | ||
66 | static void __spin_lock_debug(spinlock_t *lock) | 67 | static void __spin_lock_debug(spinlock_t *lock) |
67 | { | 68 | { |
68 | int print_once = 1; | 69 | int print_once = 1; |
69 | u64 i; | 70 | u64 i; |
70 | 71 | ||
71 | for (;;) { | 72 | for (;;) { |
72 | for (i = 0; i < loops_per_jiffy * HZ; i++) { | 73 | for (i = 0; i < loops_per_jiffy * HZ; i++) { |
73 | cpu_relax(); | 74 | cpu_relax(); |
74 | if (__raw_spin_trylock(&lock->raw_lock)) | 75 | if (__raw_spin_trylock(&lock->raw_lock)) |
75 | return; | 76 | return; |
76 | } | 77 | } |
77 | /* lockup suspected: */ | 78 | /* lockup suspected: */ |
78 | if (print_once) { | 79 | if (print_once) { |
79 | print_once = 0; | 80 | print_once = 0; |
80 | printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n", | 81 | printk("BUG: spinlock lockup on CPU#%d, %s/%d, %p\n", |
81 | smp_processor_id(), current->comm, current->pid, | 82 | raw_smp_processor_id(), current->comm, |
82 | lock); | 83 | current->pid, lock); |
83 | dump_stack(); | 84 | dump_stack(); |
84 | } | 85 | } |
85 | } | 86 | } |
86 | } | 87 | } |
87 | 88 | ||
88 | void _raw_spin_lock(spinlock_t *lock) | 89 | void _raw_spin_lock(spinlock_t *lock) |
89 | { | 90 | { |
90 | debug_spin_lock_before(lock); | 91 | debug_spin_lock_before(lock); |
91 | if (unlikely(!__raw_spin_trylock(&lock->raw_lock))) | 92 | if (unlikely(!__raw_spin_trylock(&lock->raw_lock))) |
92 | __spin_lock_debug(lock); | 93 | __spin_lock_debug(lock); |
93 | debug_spin_lock_after(lock); | 94 | debug_spin_lock_after(lock); |
94 | } | 95 | } |
95 | 96 | ||
96 | int _raw_spin_trylock(spinlock_t *lock) | 97 | int _raw_spin_trylock(spinlock_t *lock) |
97 | { | 98 | { |
98 | int ret = __raw_spin_trylock(&lock->raw_lock); | 99 | int ret = __raw_spin_trylock(&lock->raw_lock); |
99 | 100 | ||
100 | if (ret) | 101 | if (ret) |
101 | debug_spin_lock_after(lock); | 102 | debug_spin_lock_after(lock); |
102 | #ifndef CONFIG_SMP | 103 | #ifndef CONFIG_SMP |
103 | /* | 104 | /* |
104 | * Must not happen on UP: | 105 | * Must not happen on UP: |
105 | */ | 106 | */ |
106 | SPIN_BUG_ON(!ret, lock, "trylock failure on UP"); | 107 | SPIN_BUG_ON(!ret, lock, "trylock failure on UP"); |
107 | #endif | 108 | #endif |
108 | return ret; | 109 | return ret; |
109 | } | 110 | } |
110 | 111 | ||
111 | void _raw_spin_unlock(spinlock_t *lock) | 112 | void _raw_spin_unlock(spinlock_t *lock) |
112 | { | 113 | { |
113 | debug_spin_unlock(lock); | 114 | debug_spin_unlock(lock); |
114 | __raw_spin_unlock(&lock->raw_lock); | 115 | __raw_spin_unlock(&lock->raw_lock); |
115 | } | 116 | } |
116 | 117 | ||
117 | static void rwlock_bug(rwlock_t *lock, const char *msg) | 118 | static void rwlock_bug(rwlock_t *lock, const char *msg) |
118 | { | 119 | { |
119 | static long print_once = 1; | 120 | static long print_once = 1; |
120 | 121 | ||
121 | if (xchg(&print_once, 0)) { | 122 | if (xchg(&print_once, 0)) { |
122 | printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg, | 123 | printk("BUG: rwlock %s on CPU#%d, %s/%d, %p\n", msg, |
123 | smp_processor_id(), current->comm, current->pid, lock); | 124 | raw_smp_processor_id(), current->comm, |
125 | current->pid, lock); | ||
124 | dump_stack(); | 126 | dump_stack(); |
125 | #ifdef CONFIG_SMP | 127 | #ifdef CONFIG_SMP |
126 | /* | 128 | /* |
127 | * We cannot continue on SMP: | 129 | * We cannot continue on SMP: |
128 | */ | 130 | */ |
129 | panic("bad locking"); | 131 | panic("bad locking"); |
130 | #endif | 132 | #endif |
131 | } | 133 | } |
132 | } | 134 | } |
133 | 135 | ||
134 | #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) | 136 | #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) |
135 | 137 | ||
136 | static void __read_lock_debug(rwlock_t *lock) | 138 | static void __read_lock_debug(rwlock_t *lock) |
137 | { | 139 | { |
138 | int print_once = 1; | 140 | int print_once = 1; |
139 | u64 i; | 141 | u64 i; |
140 | 142 | ||
141 | for (;;) { | 143 | for (;;) { |
142 | for (i = 0; i < loops_per_jiffy * HZ; i++) { | 144 | for (i = 0; i < loops_per_jiffy * HZ; i++) { |
143 | cpu_relax(); | 145 | cpu_relax(); |
144 | if (__raw_read_trylock(&lock->raw_lock)) | 146 | if (__raw_read_trylock(&lock->raw_lock)) |
145 | return; | 147 | return; |
146 | } | 148 | } |
147 | /* lockup suspected: */ | 149 | /* lockup suspected: */ |
148 | if (print_once) { | 150 | if (print_once) { |
149 | print_once = 0; | 151 | print_once = 0; |
150 | printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n", | 152 | printk("BUG: read-lock lockup on CPU#%d, %s/%d, %p\n", |
151 | smp_processor_id(), current->comm, current->pid, | 153 | raw_smp_processor_id(), current->comm, |
152 | lock); | 154 | current->pid, lock); |
153 | dump_stack(); | 155 | dump_stack(); |
154 | } | 156 | } |
155 | } | 157 | } |
156 | } | 158 | } |
157 | 159 | ||
158 | void _raw_read_lock(rwlock_t *lock) | 160 | void _raw_read_lock(rwlock_t *lock) |
159 | { | 161 | { |
160 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | 162 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); |
161 | if (unlikely(!__raw_read_trylock(&lock->raw_lock))) | 163 | if (unlikely(!__raw_read_trylock(&lock->raw_lock))) |
162 | __read_lock_debug(lock); | 164 | __read_lock_debug(lock); |
163 | } | 165 | } |
164 | 166 | ||
165 | int _raw_read_trylock(rwlock_t *lock) | 167 | int _raw_read_trylock(rwlock_t *lock) |
166 | { | 168 | { |
167 | int ret = __raw_read_trylock(&lock->raw_lock); | 169 | int ret = __raw_read_trylock(&lock->raw_lock); |
168 | 170 | ||
169 | #ifndef CONFIG_SMP | 171 | #ifndef CONFIG_SMP |
170 | /* | 172 | /* |
171 | * Must not happen on UP: | 173 | * Must not happen on UP: |
172 | */ | 174 | */ |
173 | RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | 175 | RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); |
174 | #endif | 176 | #endif |
175 | return ret; | 177 | return ret; |
176 | } | 178 | } |
177 | 179 | ||
178 | void _raw_read_unlock(rwlock_t *lock) | 180 | void _raw_read_unlock(rwlock_t *lock) |
179 | { | 181 | { |
180 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | 182 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); |
181 | __raw_read_unlock(&lock->raw_lock); | 183 | __raw_read_unlock(&lock->raw_lock); |
182 | } | 184 | } |
183 | 185 | ||
184 | static inline void debug_write_lock_before(rwlock_t *lock) | 186 | static inline void debug_write_lock_before(rwlock_t *lock) |
185 | { | 187 | { |
186 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | 188 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); |
187 | RWLOCK_BUG_ON(lock->owner == current, lock, "recursion"); | 189 | RWLOCK_BUG_ON(lock->owner == current, lock, "recursion"); |
188 | RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), | 190 | RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(), |
189 | lock, "cpu recursion"); | 191 | lock, "cpu recursion"); |
190 | } | 192 | } |
191 | 193 | ||
192 | static inline void debug_write_lock_after(rwlock_t *lock) | 194 | static inline void debug_write_lock_after(rwlock_t *lock) |
193 | { | 195 | { |
194 | lock->owner_cpu = raw_smp_processor_id(); | 196 | lock->owner_cpu = raw_smp_processor_id(); |
195 | lock->owner = current; | 197 | lock->owner = current; |
196 | } | 198 | } |
197 | 199 | ||
198 | static inline void debug_write_unlock(rwlock_t *lock) | 200 | static inline void debug_write_unlock(rwlock_t *lock) |
199 | { | 201 | { |
200 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); | 202 | RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); |
201 | RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); | 203 | RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner"); |
202 | RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), | 204 | RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(), |
203 | lock, "wrong CPU"); | 205 | lock, "wrong CPU"); |
204 | lock->owner = SPINLOCK_OWNER_INIT; | 206 | lock->owner = SPINLOCK_OWNER_INIT; |
205 | lock->owner_cpu = -1; | 207 | lock->owner_cpu = -1; |
206 | } | 208 | } |
207 | 209 | ||
208 | static void __write_lock_debug(rwlock_t *lock) | 210 | static void __write_lock_debug(rwlock_t *lock) |
209 | { | 211 | { |
210 | int print_once = 1; | 212 | int print_once = 1; |
211 | u64 i; | 213 | u64 i; |
212 | 214 | ||
213 | for (;;) { | 215 | for (;;) { |
214 | for (i = 0; i < loops_per_jiffy * HZ; i++) { | 216 | for (i = 0; i < loops_per_jiffy * HZ; i++) { |
215 | cpu_relax(); | 217 | cpu_relax(); |
216 | if (__raw_write_trylock(&lock->raw_lock)) | 218 | if (__raw_write_trylock(&lock->raw_lock)) |
217 | return; | 219 | return; |
218 | } | 220 | } |
219 | /* lockup suspected: */ | 221 | /* lockup suspected: */ |
220 | if (print_once) { | 222 | if (print_once) { |
221 | print_once = 0; | 223 | print_once = 0; |
222 | printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n", | 224 | printk("BUG: write-lock lockup on CPU#%d, %s/%d, %p\n", |
223 | smp_processor_id(), current->comm, current->pid, | 225 | raw_smp_processor_id(), current->comm, |
224 | lock); | 226 | current->pid, lock); |
225 | dump_stack(); | 227 | dump_stack(); |
226 | } | 228 | } |
227 | } | 229 | } |
228 | } | 230 | } |
229 | 231 | ||
230 | void _raw_write_lock(rwlock_t *lock) | 232 | void _raw_write_lock(rwlock_t *lock) |
231 | { | 233 | { |
232 | debug_write_lock_before(lock); | 234 | debug_write_lock_before(lock); |
233 | if (unlikely(!__raw_write_trylock(&lock->raw_lock))) | 235 | if (unlikely(!__raw_write_trylock(&lock->raw_lock))) |
234 | __write_lock_debug(lock); | 236 | __write_lock_debug(lock); |
235 | debug_write_lock_after(lock); | 237 | debug_write_lock_after(lock); |
236 | } | 238 | } |
237 | 239 | ||
238 | int _raw_write_trylock(rwlock_t *lock) | 240 | int _raw_write_trylock(rwlock_t *lock) |
239 | { | 241 | { |
240 | int ret = __raw_write_trylock(&lock->raw_lock); | 242 | int ret = __raw_write_trylock(&lock->raw_lock); |
241 | 243 | ||
242 | if (ret) | 244 | if (ret) |
243 | debug_write_lock_after(lock); | 245 | debug_write_lock_after(lock); |
244 | #ifndef CONFIG_SMP | 246 | #ifndef CONFIG_SMP |
245 | /* | 247 | /* |
246 | * Must not happen on UP: | 248 | * Must not happen on UP: |
247 | */ | 249 | */ |
248 | RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); | 250 | RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP"); |
249 | #endif | 251 | #endif |
250 | return ret; | 252 | return ret; |
251 | } | 253 | } |
252 | 254 | ||
253 | void _raw_write_unlock(rwlock_t *lock) | 255 | void _raw_write_unlock(rwlock_t *lock) |
254 | { | 256 | { |
255 | debug_write_unlock(lock); | 257 | debug_write_unlock(lock); |
256 | __raw_write_unlock(&lock->raw_lock); | 258 | __raw_write_unlock(&lock->raw_lock); |
257 | } | 259 | } |
258 | 260 |