]> bbs.cooldavid.org Git - net-next-2.6.git/blame - lib/spinlock_debug.c
[PATCH] lockdep: prove rwsem locking correctness
[net-next-2.6.git] / lib / spinlock_debug.c
CommitLineData
fb1c8f93
IM
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
fb1c8f93
IM
9#include <linux/spinlock.h>
10#include <linux/interrupt.h>
9a11b49a 11#include <linux/debug_locks.h>
fb1c8f93 12#include <linux/delay.h>
9a11b49a 13#include <linux/module.h>
fb1c8f93
IM
14
15static void spin_bug(spinlock_t *lock, const char *msg)
16{
fb1c8f93
IM
17 struct task_struct *owner = NULL;
18
9a11b49a
IM
19 if (!debug_locks_off())
20 return;
21
22 if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
23 owner = lock->owner;
24 printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
25 msg, raw_smp_processor_id(),
26 current->comm, current->pid);
27 printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
28 ".owner_cpu: %d\n",
29 lock, lock->magic,
30 owner ? owner->comm : "<none>",
31 owner ? owner->pid : -1,
32 lock->owner_cpu);
33 dump_stack();
fb1c8f93
IM
34}
35
36#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
37
9a11b49a
IM
38static inline void
39debug_spin_lock_before(spinlock_t *lock)
fb1c8f93
IM
40{
41 SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
42 SPIN_BUG_ON(lock->owner == current, lock, "recursion");
43 SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
44 lock, "cpu recursion");
45}
46
47static inline void debug_spin_lock_after(spinlock_t *lock)
48{
49 lock->owner_cpu = raw_smp_processor_id();
50 lock->owner = current;
51}
52
53static inline void debug_spin_unlock(spinlock_t *lock)
54{
55 SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
56 SPIN_BUG_ON(!spin_is_locked(lock), lock, "already unlocked");
57 SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
58 SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
59 lock, "wrong CPU");
60 lock->owner = SPINLOCK_OWNER_INIT;
61 lock->owner_cpu = -1;
62}
63
64static void __spin_lock_debug(spinlock_t *lock)
65{
66 int print_once = 1;
67 u64 i;
68
69 for (;;) {
70 for (i = 0; i < loops_per_jiffy * HZ; i++) {
fb1c8f93
IM
71 if (__raw_spin_trylock(&lock->raw_lock))
72 return;
e0a60296 73 __delay(1);
fb1c8f93
IM
74 }
75 /* lockup suspected: */
76 if (print_once) {
77 print_once = 0;
51989b9f
DJ
78 printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
79 "%s/%d, %p\n",
bb44f116
IM
80 raw_smp_processor_id(), current->comm,
81 current->pid, lock);
fb1c8f93
IM
82 dump_stack();
83 }
84 }
85}
86
87void _raw_spin_lock(spinlock_t *lock)
88{
89 debug_spin_lock_before(lock);
90 if (unlikely(!__raw_spin_trylock(&lock->raw_lock)))
91 __spin_lock_debug(lock);
92 debug_spin_lock_after(lock);
93}
94
95int _raw_spin_trylock(spinlock_t *lock)
96{
97 int ret = __raw_spin_trylock(&lock->raw_lock);
98
99 if (ret)
100 debug_spin_lock_after(lock);
101#ifndef CONFIG_SMP
102 /*
103 * Must not happen on UP:
104 */
105 SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
106#endif
107 return ret;
108}
109
110void _raw_spin_unlock(spinlock_t *lock)
111{
112 debug_spin_unlock(lock);
113 __raw_spin_unlock(&lock->raw_lock);
114}
115
116static void rwlock_bug(rwlock_t *lock, const char *msg)
117{
9a11b49a
IM
118 if (!debug_locks_off())
119 return;
120
121 printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
122 msg, raw_smp_processor_id(), current->comm,
123 current->pid, lock);
124 dump_stack();
fb1c8f93
IM
125}
126
127#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
128
129static void __read_lock_debug(rwlock_t *lock)
130{
131 int print_once = 1;
132 u64 i;
133
134 for (;;) {
135 for (i = 0; i < loops_per_jiffy * HZ; i++) {
fb1c8f93
IM
136 if (__raw_read_trylock(&lock->raw_lock))
137 return;
e0a60296 138 __delay(1);
fb1c8f93
IM
139 }
140 /* lockup suspected: */
141 if (print_once) {
142 print_once = 0;
51989b9f
DJ
143 printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
144 "%s/%d, %p\n",
bb44f116
IM
145 raw_smp_processor_id(), current->comm,
146 current->pid, lock);
fb1c8f93
IM
147 dump_stack();
148 }
149 }
150}
151
152void _raw_read_lock(rwlock_t *lock)
153{
154 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
155 if (unlikely(!__raw_read_trylock(&lock->raw_lock)))
156 __read_lock_debug(lock);
157}
158
159int _raw_read_trylock(rwlock_t *lock)
160{
161 int ret = __raw_read_trylock(&lock->raw_lock);
162
163#ifndef CONFIG_SMP
164 /*
165 * Must not happen on UP:
166 */
167 RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
168#endif
169 return ret;
170}
171
172void _raw_read_unlock(rwlock_t *lock)
173{
174 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
175 __raw_read_unlock(&lock->raw_lock);
176}
177
178static inline void debug_write_lock_before(rwlock_t *lock)
179{
180 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
181 RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
182 RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
183 lock, "cpu recursion");
184}
185
186static inline void debug_write_lock_after(rwlock_t *lock)
187{
188 lock->owner_cpu = raw_smp_processor_id();
189 lock->owner = current;
190}
191
192static inline void debug_write_unlock(rwlock_t *lock)
193{
194 RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
195 RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
196 RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
197 lock, "wrong CPU");
198 lock->owner = SPINLOCK_OWNER_INIT;
199 lock->owner_cpu = -1;
200}
201
202static void __write_lock_debug(rwlock_t *lock)
203{
204 int print_once = 1;
205 u64 i;
206
207 for (;;) {
208 for (i = 0; i < loops_per_jiffy * HZ; i++) {
fb1c8f93
IM
209 if (__raw_write_trylock(&lock->raw_lock))
210 return;
e0a60296 211 __delay(1);
fb1c8f93
IM
212 }
213 /* lockup suspected: */
214 if (print_once) {
215 print_once = 0;
51989b9f
DJ
216 printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
217 "%s/%d, %p\n",
bb44f116
IM
218 raw_smp_processor_id(), current->comm,
219 current->pid, lock);
fb1c8f93
IM
220 dump_stack();
221 }
222 }
223}
224
225void _raw_write_lock(rwlock_t *lock)
226{
227 debug_write_lock_before(lock);
228 if (unlikely(!__raw_write_trylock(&lock->raw_lock)))
229 __write_lock_debug(lock);
230 debug_write_lock_after(lock);
231}
232
233int _raw_write_trylock(rwlock_t *lock)
234{
235 int ret = __raw_write_trylock(&lock->raw_lock);
236
237 if (ret)
238 debug_write_lock_after(lock);
239#ifndef CONFIG_SMP
240 /*
241 * Must not happen on UP:
242 */
243 RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
244#endif
245 return ret;
246}
247
248void _raw_write_unlock(rwlock_t *lock)
249{
250 debug_write_unlock(lock);
251 __raw_write_unlock(&lock->raw_lock);
252}