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