Merge branch 'master' of /home/sam/kernel/linux-2.6/
[linux-2.6] / 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/spinlock.h>
10 #include <linux/interrupt.h>
11 #include <linux/delay.h>
12
13 static void spin_bug(spinlock_t *lock, const char *msg)
14 {
15         static long print_once = 1;
16         struct task_struct *owner = NULL;
17
18         if (xchg(&print_once, 0)) {
19                 if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
20                         owner = lock->owner;
21                 printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
22                         msg, raw_smp_processor_id(),
23                         current->comm, current->pid);
24                 printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
25                                 ".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                         if (__raw_spin_trylock(&lock->raw_lock))
75                                 return;
76                         __delay(1);
77                 }
78                 /* lockup suspected: */
79                 if (print_once) {
80                         print_once = 0;
81                         printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
82                                         "%s/%d, %p\n",
83                                 raw_smp_processor_id(), current->comm,
84                                 current->pid, lock);
85                         dump_stack();
86                 }
87         }
88 }
89
90 void _raw_spin_lock(spinlock_t *lock)
91 {
92         debug_spin_lock_before(lock);
93         if (unlikely(!__raw_spin_trylock(&lock->raw_lock)))
94                 __spin_lock_debug(lock);
95         debug_spin_lock_after(lock);
96 }
97
98 int _raw_spin_trylock(spinlock_t *lock)
99 {
100         int ret = __raw_spin_trylock(&lock->raw_lock);
101
102         if (ret)
103                 debug_spin_lock_after(lock);
104 #ifndef CONFIG_SMP
105         /*
106          * Must not happen on UP:
107          */
108         SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
109 #endif
110         return ret;
111 }
112
113 void _raw_spin_unlock(spinlock_t *lock)
114 {
115         debug_spin_unlock(lock);
116         __raw_spin_unlock(&lock->raw_lock);
117 }
118
119 static void rwlock_bug(rwlock_t *lock, const char *msg)
120 {
121         static long print_once = 1;
122
123         if (xchg(&print_once, 0)) {
124                 printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
125                         msg, raw_smp_processor_id(), current->comm,
126                         current->pid, lock);
127                 dump_stack();
128 #ifdef CONFIG_SMP
129                 /*
130                  * We cannot continue on SMP:
131                  */
132                 panic("bad locking");
133 #endif
134         }
135 }
136
137 #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
138
139 static void __read_lock_debug(rwlock_t *lock)
140 {
141         int print_once = 1;
142         u64 i;
143
144         for (;;) {
145                 for (i = 0; i < loops_per_jiffy * HZ; i++) {
146                         if (__raw_read_trylock(&lock->raw_lock))
147                                 return;
148                         __delay(1);
149                 }
150                 /* lockup suspected: */
151                 if (print_once) {
152                         print_once = 0;
153                         printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
154                                         "%s/%d, %p\n",
155                                 raw_smp_processor_id(), current->comm,
156                                 current->pid, lock);
157                         dump_stack();
158                 }
159         }
160 }
161
162 void _raw_read_lock(rwlock_t *lock)
163 {
164         RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
165         if (unlikely(!__raw_read_trylock(&lock->raw_lock)))
166                 __read_lock_debug(lock);
167 }
168
169 int _raw_read_trylock(rwlock_t *lock)
170 {
171         int ret = __raw_read_trylock(&lock->raw_lock);
172
173 #ifndef CONFIG_SMP
174         /*
175          * Must not happen on UP:
176          */
177         RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
178 #endif
179         return ret;
180 }
181
182 void _raw_read_unlock(rwlock_t *lock)
183 {
184         RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
185         __raw_read_unlock(&lock->raw_lock);
186 }
187
188 static inline void debug_write_lock_before(rwlock_t *lock)
189 {
190         RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
191         RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
192         RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
193                                                         lock, "cpu recursion");
194 }
195
196 static inline void debug_write_lock_after(rwlock_t *lock)
197 {
198         lock->owner_cpu = raw_smp_processor_id();
199         lock->owner = current;
200 }
201
202 static inline void debug_write_unlock(rwlock_t *lock)
203 {
204         RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
205         RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
206         RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
207                                                         lock, "wrong CPU");
208         lock->owner = SPINLOCK_OWNER_INIT;
209         lock->owner_cpu = -1;
210 }
211
212 static void __write_lock_debug(rwlock_t *lock)
213 {
214         int print_once = 1;
215         u64 i;
216
217         for (;;) {
218                 for (i = 0; i < loops_per_jiffy * HZ; i++) {
219                         if (__raw_write_trylock(&lock->raw_lock))
220                                 return;
221                         __delay(1);
222                 }
223                 /* lockup suspected: */
224                 if (print_once) {
225                         print_once = 0;
226                         printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
227                                         "%s/%d, %p\n",
228                                 raw_smp_processor_id(), current->comm,
229                                 current->pid, lock);
230                         dump_stack();
231                 }
232         }
233 }
234
235 void _raw_write_lock(rwlock_t *lock)
236 {
237         debug_write_lock_before(lock);
238         if (unlikely(!__raw_write_trylock(&lock->raw_lock)))
239                 __write_lock_debug(lock);
240         debug_write_lock_after(lock);
241 }
242
243 int _raw_write_trylock(rwlock_t *lock)
244 {
245         int ret = __raw_write_trylock(&lock->raw_lock);
246
247         if (ret)
248                 debug_write_lock_after(lock);
249 #ifndef CONFIG_SMP
250         /*
251          * Must not happen on UP:
252          */
253         RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
254 #endif
255         return ret;
256 }
257
258 void _raw_write_unlock(rwlock_t *lock)
259 {
260         debug_write_unlock(lock);
261         __raw_write_unlock(&lock->raw_lock);
262 }