Blame view

kernel/locking/spinlock_debug.c 5.5 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>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
13
  #include <linux/export.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));
4b0681487   Stephen Boyd   spinlock_debug: p...
58
  	printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, "
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
59
60
61
62
  			".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;
  }
bc88c10d7   Waiman Long   locking/spinlock/...
98
99
100
101
  /*
   * We are now relying on the NMI watchdog to detect lockup instead of doing
   * the detection here with an unfair lock which can cause problem of its own.
   */
9828ea9d7   Thomas Gleixner   locking: Further ...
102
  void do_raw_spin_lock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
103
104
  {
  	debug_spin_lock_before(lock);
bc88c10d7   Waiman Long   locking/spinlock/...
105
  	arch_spin_lock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
106
107
  	debug_spin_lock_after(lock);
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
108
  int do_raw_spin_trylock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
109
  {
0199c4e68   Thomas Gleixner   locking: Convert ...
110
  	int ret = arch_spin_trylock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
111
112
113
114
115
116
117
118
119
120
121
  
  	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 ...
122
  void do_raw_spin_unlock(raw_spinlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
123
124
  {
  	debug_spin_unlock(lock);
0199c4e68   Thomas Gleixner   locking: Convert ...
125
  	arch_spin_unlock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
126
127
128
129
  }
  
  static void rwlock_bug(rwlock_t *lock, const char *msg)
  {
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
130
131
132
133
134
135
  	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...
136
  		task_pid_nr(current), lock);
9a11b49a8   Ingo Molnar   [PATCH] lockdep: ...
137
  	dump_stack();
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
138
139
140
  }
  
  #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
9828ea9d7   Thomas Gleixner   locking: Further ...
141
  void do_raw_read_lock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
142
143
  {
  	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
e5931943d   Thomas Gleixner   locking: Convert ...
144
  	arch_read_lock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
145
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
146
  int do_raw_read_trylock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
147
  {
e5931943d   Thomas Gleixner   locking: Convert ...
148
  	int ret = arch_read_trylock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
149
150
151
152
153
154
155
156
157
  
  #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 ...
158
  void do_raw_read_unlock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
159
160
  {
  	RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
e5931943d   Thomas Gleixner   locking: Convert ...
161
  	arch_read_unlock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  }
  
  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;
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
187
  void do_raw_write_lock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
188
189
  {
  	debug_write_lock_before(lock);
e5931943d   Thomas Gleixner   locking: Convert ...
190
  	arch_write_lock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
191
192
  	debug_write_lock_after(lock);
  }
9828ea9d7   Thomas Gleixner   locking: Further ...
193
  int do_raw_write_trylock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
194
  {
e5931943d   Thomas Gleixner   locking: Convert ...
195
  	int ret = arch_write_trylock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
196
197
198
199
200
201
202
203
204
205
206
  
  	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 ...
207
  void do_raw_write_unlock(rwlock_t *lock)
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
208
209
  {
  	debug_write_unlock(lock);
e5931943d   Thomas Gleixner   locking: Convert ...
210
  	arch_write_unlock(&lock->raw_lock);
fb1c8f93d   Ingo Molnar   [PATCH] spinlock ...
211
  }