Blame view

lib/spinlock_debug.c 6.81 KB
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
1
2
3
4
5
6
7
  /*
   * Copyright 2005, Red Hat, Inc., Ingo Molnar
   * Released under the General Public License (GPL).
   *
   * This file contains the spinlock/rwlock implementations for
   * DEBUG_SPINLOCK.
   */
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
8
  #include <linux/spinlock.h>
bb81a09e5   Andrew Morton   [PATCH] x86: all ...
9
  #include <linux/nmi.h>
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
10
  #include <linux/interrupt.h>
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
11
  #include <linux/debug_locks.h>
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
12
  #include <linux/delay.h>
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
13
  #include <linux/module.h>
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
14

c2f21ce2e   Thomas Gleixner   locking: Implemen...
15
16
  void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
  			  struct lock_class_key *key)
8a25d5deb   Ingo Molnar   [PATCH] lockdep: ...
17
18
19
20
21
22
  {
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  	/*
  	 * Make sure we are not reinitializing a held lock:
  	 */
  	debug_check_no_locks_freed((void *)lock, sizeof(*lock));
4dfbb9d8c   Peter Zijlstra   Lockdep: add lock...
23
  	lockdep_init_map(&lock->dep_map, name, key, 0);
8a25d5deb   Ingo Molnar   [PATCH] lockdep: ...
24
  #endif
edc35bd72   Thomas Gleixner   locking: Rename _...
25
  	lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
8a25d5deb   Ingo Molnar   [PATCH] lockdep: ...
26
27
28
29
  	lock->magic = SPINLOCK_MAGIC;
  	lock->owner = SPINLOCK_OWNER_INIT;
  	lock->owner_cpu = -1;
  }
c2f21ce2e   Thomas Gleixner   locking: Implemen...
30
  EXPORT_SYMBOL(__raw_spin_lock_init);
8a25d5deb   Ingo Molnar   [PATCH] lockdep: ...
31
32
33
34
35
36
37
38
39
  
  void __rwlock_init(rwlock_t *lock, const char *name,
  		   struct lock_class_key *key)
  {
  #ifdef CONFIG_DEBUG_LOCK_ALLOC
  	/*
  	 * Make sure we are not reinitializing a held lock:
  	 */
  	debug_check_no_locks_freed((void *)lock, sizeof(*lock));
4dfbb9d8c   Peter Zijlstra   Lockdep: add lock...
40
  	lockdep_init_map(&lock->dep_map, name, key, 0);
8a25d5deb   Ingo Molnar   [PATCH] lockdep: ...
41
  #endif
fb3a6bbc9   Thomas Gleixner   locking: Convert ...
42
  	lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED;
8a25d5deb   Ingo Molnar   [PATCH] lockdep: ...
43
44
45
46
47
48
  	lock->magic = RWLOCK_MAGIC;
  	lock->owner = SPINLOCK_OWNER_INIT;
  	lock->owner_cpu = -1;
  }
  
  EXPORT_SYMBOL(__rwlock_init);
4e101b0e6   Akinobu Mita   lib/spinlock_debu...
49
  static void spin_dump(raw_spinlock_t *lock, const char *msg)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
50
  {
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
51
  	struct task_struct *owner = NULL;
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
52
53
54
55
56
  	if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
  		owner = lock->owner;
  	printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d
  ",
  		msg, raw_smp_processor_id(),
ba25f9dcc   Pavel Emelyanov   Use helpers to ob...
57
  		current->comm, task_pid_nr(current));
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
58
59
60
61
62
  	printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
  			".owner_cpu: %d
  ",
  		lock, lock->magic,
  		owner ? owner->comm : "<none>",
ba25f9dcc   Pavel Emelyanov   Use helpers to ob...
63
  		owner ? task_pid_nr(owner) : -1,
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
64
65
  		lock->owner_cpu);
  	dump_stack();
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
66
  }
4e101b0e6   Akinobu Mita   lib/spinlock_debu...
67
68
69
70
71
72
73
  static void spin_bug(raw_spinlock_t *lock, const char *msg)
  {
  	if (!debug_locks_off())
  		return;
  
  	spin_dump(lock, msg);
  }
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
74
  #define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
75
  static inline void
c2f21ce2e   Thomas Gleixner   locking: Implemen...
76
  debug_spin_lock_before(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
77
78
79
80
81
82
  {
  	SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
  	SPIN_BUG_ON(lock->owner == current, lock, "recursion");
  	SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
  							lock, "cpu recursion");
  }
c2f21ce2e   Thomas Gleixner   locking: Implemen...
83
  static inline void debug_spin_lock_after(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
84
85
86
87
  {
  	lock->owner_cpu = raw_smp_processor_id();
  	lock->owner = current;
  }
c2f21ce2e   Thomas Gleixner   locking: Implemen...
88
  static inline void debug_spin_unlock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
89
90
  {
  	SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
c2f21ce2e   Thomas Gleixner   locking: Implemen...
91
  	SPIN_BUG_ON(!raw_spin_is_locked(lock), lock, "already unlocked");
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
92
93
94
95
96
97
  	SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
  	SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
  							lock, "wrong CPU");
  	lock->owner = SPINLOCK_OWNER_INIT;
  	lock->owner_cpu = -1;
  }
c2f21ce2e   Thomas Gleixner   locking: Implemen...
98
  static void __spin_lock_debug(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
99
  {
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
100
  	u64 i;
c22f008ba   Chuck Ebbert   [PATCH] spinlock_...
101
102
  	u64 loops = loops_per_jiffy * HZ;
  	int print_once = 1;
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
103
104
  
  	for (;;) {
c22f008ba   Chuck Ebbert   [PATCH] spinlock_...
105
  		for (i = 0; i < loops; i++) {
0199c4e68   Thomas Gleixner   locking: Convert ...
106
  			if (arch_spin_trylock(&lock->raw_lock))
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
107
  				return;
e0a602963   Ingo Molnar   [PATCH] Fix spinl...
108
  			__delay(1);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
109
110
111
112
  		}
  		/* lockup suspected: */
  		if (print_once) {
  			print_once = 0;
4e101b0e6   Akinobu Mita   lib/spinlock_debu...
113
  			spin_dump(lock, "lockup");
bb81a09e5   Andrew Morton   [PATCH] x86: all ...
114
115
116
  #ifdef CONFIG_SMP
  			trigger_all_cpu_backtrace();
  #endif
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
117
118
119
  		}
  	}
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
120
  void do_raw_spin_lock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
121
122
  {
  	debug_spin_lock_before(lock);
0199c4e68   Thomas Gleixner   locking: Convert ...
123
  	if (unlikely(!arch_spin_trylock(&lock->raw_lock)))
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
124
125
126
  		__spin_lock_debug(lock);
  	debug_spin_lock_after(lock);
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
127
  int do_raw_spin_trylock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
128
  {
0199c4e68   Thomas Gleixner   locking: Convert ...
129
  	int ret = arch_spin_trylock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
130
131
132
133
134
135
136
137
138
139
140
  
  	if (ret)
  		debug_spin_lock_after(lock);
  #ifndef CONFIG_SMP
  	/*
  	 * Must not happen on UP:
  	 */
  	SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
  #endif
  	return ret;
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
141
  void do_raw_spin_unlock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
142
143
  {
  	debug_spin_unlock(lock);
0199c4e68   Thomas Gleixner   locking: Convert ...
144
  	arch_spin_unlock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
145
146
147
148
  }
  
  static void rwlock_bug(rwlock_t *lock, const char *msg)
  {
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
149
150
151
152
153
154
  	if (!debug_locks_off())
  		return;
  
  	printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p
  ",
  		msg, raw_smp_processor_id(), current->comm,
ba25f9dcc   Pavel Emelyanov   Use helpers to ob...
155
  		task_pid_nr(current), lock);
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
156
  	dump_stack();
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
157
158
159
  }
  
  #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
72f0b4e21   Andrew Morton   [PATCH] disable d...
160
  #if 0		/* __write_lock_debug() can lock up - maybe this can too? */
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
161
162
  static void __read_lock_debug(rwlock_t *lock)
  {
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
163
  	u64 i;
c22f008ba   Chuck Ebbert   [PATCH] spinlock_...
164
165
  	u64 loops = loops_per_jiffy * HZ;
  	int print_once = 1;
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
166
167
  
  	for (;;) {
c22f008ba   Chuck Ebbert   [PATCH] spinlock_...
168
  		for (i = 0; i < loops; i++) {
e5931943d   Thomas Gleixner   locking: Convert ...
169
  			if (arch_read_trylock(&lock->raw_lock))
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
170
  				return;
e0a602963   Ingo Molnar   [PATCH] Fix spinl...
171
  			__delay(1);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
172
173
174
175
  		}
  		/* lockup suspected: */
  		if (print_once) {
  			print_once = 0;
51989b9ff   Dave Jones   [PATCH] printk le...
176
177
178
  			printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
  					"%s/%d, %p
  ",
bb44f116a   Ingo Molnar   [PATCH] fix spinl...
179
180
  				raw_smp_processor_id(), current->comm,
  				current->pid, lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
181
182
183
184
  			dump_stack();
  		}
  	}
  }
72f0b4e21   Andrew Morton   [PATCH] disable d...
185
  #endif
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
186

9828ea9d7   Thomas Gleixner   locking: Further ...
187
  void do_raw_read_lock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
188
189
  {
  	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
e5931943d   Thomas Gleixner   locking: Convert ...
190
  	arch_read_lock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
191
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
192
  int do_raw_read_trylock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
193
  {
e5931943d   Thomas Gleixner   locking: Convert ...
194
  	int ret = arch_read_trylock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
195
196
197
198
199
200
201
202
203
  
  #ifndef CONFIG_SMP
  	/*
  	 * Must not happen on UP:
  	 */
  	RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
  #endif
  	return ret;
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
204
  void do_raw_read_unlock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
205
206
  {
  	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
e5931943d   Thomas Gleixner   locking: Convert ...
207
  	arch_read_unlock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  }
  
  static inline void debug_write_lock_before(rwlock_t *lock)
  {
  	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
  	RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
  	RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
  							lock, "cpu recursion");
  }
  
  static inline void debug_write_lock_after(rwlock_t *lock)
  {
  	lock->owner_cpu = raw_smp_processor_id();
  	lock->owner = current;
  }
  
  static inline void debug_write_unlock(rwlock_t *lock)
  {
  	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
  	RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
  	RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
  							lock, "wrong CPU");
  	lock->owner = SPINLOCK_OWNER_INIT;
  	lock->owner_cpu = -1;
  }
72f0b4e21   Andrew Morton   [PATCH] disable d...
233
  #if 0		/* This can cause lockups */
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
234
235
  static void __write_lock_debug(rwlock_t *lock)
  {
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
236
  	u64 i;
c22f008ba   Chuck Ebbert   [PATCH] spinlock_...
237
238
  	u64 loops = loops_per_jiffy * HZ;
  	int print_once = 1;
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
239
240
  
  	for (;;) {
c22f008ba   Chuck Ebbert   [PATCH] spinlock_...
241
  		for (i = 0; i < loops; i++) {
e5931943d   Thomas Gleixner   locking: Convert ...
242
  			if (arch_write_trylock(&lock->raw_lock))
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
243
  				return;
e0a602963   Ingo Molnar   [PATCH] Fix spinl...
244
  			__delay(1);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
245
246
247
248
  		}
  		/* lockup suspected: */
  		if (print_once) {
  			print_once = 0;
51989b9ff   Dave Jones   [PATCH] printk le...
249
250
251
  			printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
  					"%s/%d, %p
  ",
bb44f116a   Ingo Molnar   [PATCH] fix spinl...
252
253
  				raw_smp_processor_id(), current->comm,
  				current->pid, lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
254
255
256
257
  			dump_stack();
  		}
  	}
  }
72f0b4e21   Andrew Morton   [PATCH] disable d...
258
  #endif
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
259

9828ea9d7   Thomas Gleixner   locking: Further ...
260
  void do_raw_write_lock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
261
262
  {
  	debug_write_lock_before(lock);
e5931943d   Thomas Gleixner   locking: Convert ...
263
  	arch_write_lock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
264
265
  	debug_write_lock_after(lock);
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
266
  int do_raw_write_trylock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
267
  {
e5931943d   Thomas Gleixner   locking: Convert ...
268
  	int ret = arch_write_trylock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
269
270
271
272
273
274
275
276
277
278
279
  
  	if (ret)
  		debug_write_lock_after(lock);
  #ifndef CONFIG_SMP
  	/*
  	 * Must not happen on UP:
  	 */
  	RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
  #endif
  	return ret;
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
280
  void do_raw_write_unlock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
281
282
  {
  	debug_write_unlock(lock);
e5931943d   Thomas Gleixner   locking: Convert ...
283
  	arch_write_unlock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
284
  }