spinlock_debug.c 6.8 KB
Newer Older
I
Ingo Molnar 已提交
1 2 3 4 5 6 7 8 9
/*
 * Copyright 2005, Red Hat, Inc., Ingo Molnar
 * Released under the General Public License (GPL).
 *
 * This file contains the spinlock/rwlock implementations for
 * DEBUG_SPINLOCK.
 */

#include <linux/spinlock.h>
A
Andrew Morton 已提交
10
#include <linux/nmi.h>
I
Ingo Molnar 已提交
11
#include <linux/interrupt.h>
12
#include <linux/debug_locks.h>
I
Ingo Molnar 已提交
13
#include <linux/delay.h>
14
#include <linux/export.h>
I
Ingo Molnar 已提交
15

16 17
void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
			  struct lock_class_key *key)
18 19 20 21 22 23
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	/*
	 * Make sure we are not reinitializing a held lock:
	 */
	debug_check_no_locks_freed((void *)lock, sizeof(*lock));
24
	lockdep_init_map(&lock->dep_map, name, key, 0);
25
#endif
26
	lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
27 28 29 30 31
	lock->magic = SPINLOCK_MAGIC;
	lock->owner = SPINLOCK_OWNER_INIT;
	lock->owner_cpu = -1;
}

32
EXPORT_SYMBOL(__raw_spin_lock_init);
33 34 35 36 37 38 39 40 41

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));
42
	lockdep_init_map(&lock->dep_map, name, key, 0);
43
#endif
44
	lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED;
45 46 47 48 49 50 51
	lock->magic = RWLOCK_MAGIC;
	lock->owner = SPINLOCK_OWNER_INIT;
	lock->owner_cpu = -1;
}

EXPORT_SYMBOL(__rwlock_init);

52
static void spin_dump(raw_spinlock_t *lock, const char *msg)
I
Ingo Molnar 已提交
53 54 55
{
	struct task_struct *owner = NULL;

56 57 58 59
	if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
		owner = lock->owner;
	printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
		msg, raw_smp_processor_id(),
60
		current->comm, task_pid_nr(current));
61 62 63 64
	printk(KERN_EMERG " lock: %p, .magic: %08x, .owner: %s/%d, "
			".owner_cpu: %d\n",
		lock, lock->magic,
		owner ? owner->comm : "<none>",
65
		owner ? task_pid_nr(owner) : -1,
66 67
		lock->owner_cpu);
	dump_stack();
I
Ingo Molnar 已提交
68 69
}

70 71 72 73 74 75 76 77
static void spin_bug(raw_spinlock_t *lock, const char *msg)
{
	if (!debug_locks_off())
		return;

	spin_dump(lock, msg);
}

I
Ingo Molnar 已提交
78 79
#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)

80
static inline void
81
debug_spin_lock_before(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
82 83 84 85 86 87 88
{
	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");
}

89
static inline void debug_spin_lock_after(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
90 91 92 93 94
{
	lock->owner_cpu = raw_smp_processor_id();
	lock->owner = current;
}

95
static inline void debug_spin_unlock(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
96 97
{
	SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
98
	SPIN_BUG_ON(!raw_spin_is_locked(lock), lock, "already unlocked");
I
Ingo Molnar 已提交
99 100 101 102 103 104 105
	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;
}

106
static void __spin_lock_debug(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
107 108
{
	u64 i;
109 110
	u64 loops = loops_per_jiffy * HZ;
	int print_once = 1;
I
Ingo Molnar 已提交
111 112

	for (;;) {
113
		for (i = 0; i < loops; i++) {
114
			if (arch_spin_trylock(&lock->raw_lock))
I
Ingo Molnar 已提交
115
				return;
116
			__delay(1);
I
Ingo Molnar 已提交
117 118 119 120
		}
		/* lockup suspected: */
		if (print_once) {
			print_once = 0;
121
			spin_dump(lock, "lockup");
A
Andrew Morton 已提交
122 123 124
#ifdef CONFIG_SMP
			trigger_all_cpu_backtrace();
#endif
I
Ingo Molnar 已提交
125 126 127 128
		}
	}
}

129
void do_raw_spin_lock(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
130 131
{
	debug_spin_lock_before(lock);
132
	if (unlikely(!arch_spin_trylock(&lock->raw_lock)))
I
Ingo Molnar 已提交
133 134 135 136
		__spin_lock_debug(lock);
	debug_spin_lock_after(lock);
}

137
int do_raw_spin_trylock(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
138
{
139
	int ret = arch_spin_trylock(&lock->raw_lock);
I
Ingo Molnar 已提交
140 141 142 143 144 145 146 147 148 149 150 151

	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;
}

152
void do_raw_spin_unlock(raw_spinlock_t *lock)
I
Ingo Molnar 已提交
153 154
{
	debug_spin_unlock(lock);
155
	arch_spin_unlock(&lock->raw_lock);
I
Ingo Molnar 已提交
156 157 158 159
}

static void rwlock_bug(rwlock_t *lock, const char *msg)
{
160 161 162 163 164
	if (!debug_locks_off())
		return;

	printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
		msg, raw_smp_processor_id(), current->comm,
165
		task_pid_nr(current), lock);
166
	dump_stack();
I
Ingo Molnar 已提交
167 168 169 170
}

#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)

171
#if 0		/* __write_lock_debug() can lock up - maybe this can too? */
I
Ingo Molnar 已提交
172 173 174
static void __read_lock_debug(rwlock_t *lock)
{
	u64 i;
175 176
	u64 loops = loops_per_jiffy * HZ;
	int print_once = 1;
I
Ingo Molnar 已提交
177 178

	for (;;) {
179
		for (i = 0; i < loops; i++) {
180
			if (arch_read_trylock(&lock->raw_lock))
I
Ingo Molnar 已提交
181
				return;
182
			__delay(1);
I
Ingo Molnar 已提交
183 184 185 186
		}
		/* lockup suspected: */
		if (print_once) {
			print_once = 0;
187 188
			printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
					"%s/%d, %p\n",
189 190
				raw_smp_processor_id(), current->comm,
				current->pid, lock);
I
Ingo Molnar 已提交
191 192 193 194
			dump_stack();
		}
	}
}
195
#endif
I
Ingo Molnar 已提交
196

197
void do_raw_read_lock(rwlock_t *lock)
I
Ingo Molnar 已提交
198 199
{
	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
200
	arch_read_lock(&lock->raw_lock);
I
Ingo Molnar 已提交
201 202
}

203
int do_raw_read_trylock(rwlock_t *lock)
I
Ingo Molnar 已提交
204
{
205
	int ret = arch_read_trylock(&lock->raw_lock);
I
Ingo Molnar 已提交
206 207 208 209 210 211 212 213 214 215

#ifndef CONFIG_SMP
	/*
	 * Must not happen on UP:
	 */
	RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
#endif
	return ret;
}

216
void do_raw_read_unlock(rwlock_t *lock)
I
Ingo Molnar 已提交
217 218
{
	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
219
	arch_read_unlock(&lock->raw_lock);
I
Ingo Molnar 已提交
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
}

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;
}

246
#if 0		/* This can cause lockups */
I
Ingo Molnar 已提交
247 248 249
static void __write_lock_debug(rwlock_t *lock)
{
	u64 i;
250 251
	u64 loops = loops_per_jiffy * HZ;
	int print_once = 1;
I
Ingo Molnar 已提交
252 253

	for (;;) {
254
		for (i = 0; i < loops; i++) {
255
			if (arch_write_trylock(&lock->raw_lock))
I
Ingo Molnar 已提交
256
				return;
257
			__delay(1);
I
Ingo Molnar 已提交
258 259 260 261
		}
		/* lockup suspected: */
		if (print_once) {
			print_once = 0;
262 263
			printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
					"%s/%d, %p\n",
264 265
				raw_smp_processor_id(), current->comm,
				current->pid, lock);
I
Ingo Molnar 已提交
266 267 268 269
			dump_stack();
		}
	}
}
270
#endif
I
Ingo Molnar 已提交
271

272
void do_raw_write_lock(rwlock_t *lock)
I
Ingo Molnar 已提交
273 274
{
	debug_write_lock_before(lock);
275
	arch_write_lock(&lock->raw_lock);
I
Ingo Molnar 已提交
276 277 278
	debug_write_lock_after(lock);
}

279
int do_raw_write_trylock(rwlock_t *lock)
I
Ingo Molnar 已提交
280
{
281
	int ret = arch_write_trylock(&lock->raw_lock);
I
Ingo Molnar 已提交
282 283 284 285 286 287 288 289 290 291 292 293

	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;
}

294
void do_raw_write_unlock(rwlock_t *lock)
I
Ingo Molnar 已提交
295 296
{
	debug_write_unlock(lock);
297
	arch_write_unlock(&lock->raw_lock);
I
Ingo Molnar 已提交
298
}