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