summaryrefslogtreecommitdiffstats
path: root/kernel/locking
diff options
context:
space:
mode:
authorWaiman Long <longman@redhat.com>2019-04-04 13:43:15 -0400
committerIngo Molnar <mingo@kernel.org>2019-04-10 04:56:03 -0400
commit3b4ba6643d26a95e08067fca9a5da1828f9afabf (patch)
treefad9ad6b108aec17dcd0b2b9da672697b84bd1d3 /kernel/locking
parenta68e2c4c637918da47b3aa270051545cff7d8245 (diff)
locking/rwsem: Enhance DEBUG_RWSEMS_WARN_ON() macro
Currently, the DEBUG_RWSEMS_WARN_ON() macro just dumps a stack trace when the rwsem isn't in the right state. It does not show the actual states of the rwsem. This may not be that helpful in the debugging process. Enhance the DEBUG_RWSEMS_WARN_ON() macro to also show the current content of the rwsem count and owner fields to give more information about what is wrong with the rwsem. The debug_locks_off() function is called as is done inside DEBUG_LOCKS_WARN_ON(). Signed-off-by: Waiman Long <longman@redhat.com> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Acked-by: Davidlohr Bueso <dbueso@suse.de> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Will Deacon <will.deacon@arm.com> Link: http://lkml.kernel.org/r/20190404174320.22416-7-longman@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/locking')
-rw-r--r--kernel/locking/rwsem.c3
-rw-r--r--kernel/locking/rwsem.h21
2 files changed, 16 insertions, 8 deletions
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index 90de5f1780ba..ccbf18f560ff 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -198,7 +198,8 @@ EXPORT_SYMBOL(down_write_killable_nested);
198 198
199void up_read_non_owner(struct rw_semaphore *sem) 199void up_read_non_owner(struct rw_semaphore *sem)
200{ 200{
201 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & RWSEM_READER_OWNED)); 201 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & RWSEM_READER_OWNED),
202 sem);
202 __up_read(sem); 203 __up_read(sem);
203} 204}
204 205
diff --git a/kernel/locking/rwsem.h b/kernel/locking/rwsem.h
index 1d8f722a6761..3059a2dc39f8 100644
--- a/kernel/locking/rwsem.h
+++ b/kernel/locking/rwsem.h
@@ -27,9 +27,15 @@
27#define RWSEM_ANONYMOUSLY_OWNED (1UL << 1) 27#define RWSEM_ANONYMOUSLY_OWNED (1UL << 1)
28 28
29#ifdef CONFIG_DEBUG_RWSEMS 29#ifdef CONFIG_DEBUG_RWSEMS
30# define DEBUG_RWSEMS_WARN_ON(c) DEBUG_LOCKS_WARN_ON(c) 30# define DEBUG_RWSEMS_WARN_ON(c, sem) do { \
31 if (WARN_ONCE(c, "DEBUG_RWSEMS_WARN_ON(%s): count = 0x%lx, owner = 0x%lx, curr 0x%lx, list %sempty\n",\
32 #c, atomic_long_read(&(sem)->count), \
33 (long)((sem)->owner), (long)current, \
34 list_empty(&(sem)->wait_list) ? "" : "not ")) \
35 debug_locks_off(); \
36 } while (0)
31#else 37#else
32# define DEBUG_RWSEMS_WARN_ON(c) 38# define DEBUG_RWSEMS_WARN_ON(c, sem)
33#endif 39#endif
34 40
35/* 41/*
@@ -168,7 +174,7 @@ static inline void __down_read(struct rw_semaphore *sem)
168 if (unlikely(atomic_long_inc_return_acquire(&sem->count) <= 0)) { 174 if (unlikely(atomic_long_inc_return_acquire(&sem->count) <= 0)) {
169 rwsem_down_read_failed(sem); 175 rwsem_down_read_failed(sem);
170 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & 176 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner &
171 RWSEM_READER_OWNED)); 177 RWSEM_READER_OWNED), sem);
172 } else { 178 } else {
173 rwsem_set_reader_owned(sem); 179 rwsem_set_reader_owned(sem);
174 } 180 }
@@ -180,7 +186,7 @@ static inline int __down_read_killable(struct rw_semaphore *sem)
180 if (IS_ERR(rwsem_down_read_failed_killable(sem))) 186 if (IS_ERR(rwsem_down_read_failed_killable(sem)))
181 return -EINTR; 187 return -EINTR;
182 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & 188 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner &
183 RWSEM_READER_OWNED)); 189 RWSEM_READER_OWNED), sem);
184 } else { 190 } else {
185 rwsem_set_reader_owned(sem); 191 rwsem_set_reader_owned(sem);
186 } 192 }
@@ -251,7 +257,8 @@ static inline void __up_read(struct rw_semaphore *sem)
251{ 257{
252 long tmp; 258 long tmp;
253 259
254 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & RWSEM_READER_OWNED)); 260 DEBUG_RWSEMS_WARN_ON(!((unsigned long)sem->owner & RWSEM_READER_OWNED),
261 sem);
255 rwsem_clear_reader_owned(sem); 262 rwsem_clear_reader_owned(sem);
256 tmp = atomic_long_dec_return_release(&sem->count); 263 tmp = atomic_long_dec_return_release(&sem->count);
257 if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)) 264 if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
@@ -263,7 +270,7 @@ static inline void __up_read(struct rw_semaphore *sem)
263 */ 270 */
264static inline void __up_write(struct rw_semaphore *sem) 271static inline void __up_write(struct rw_semaphore *sem)
265{ 272{
266 DEBUG_RWSEMS_WARN_ON(sem->owner != current); 273 DEBUG_RWSEMS_WARN_ON(sem->owner != current, sem);
267 rwsem_clear_owner(sem); 274 rwsem_clear_owner(sem);
268 if (unlikely(atomic_long_sub_return_release(RWSEM_ACTIVE_WRITE_BIAS, 275 if (unlikely(atomic_long_sub_return_release(RWSEM_ACTIVE_WRITE_BIAS,
269 &sem->count) < 0)) 276 &sem->count) < 0))
@@ -284,7 +291,7 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
284 * read-locked region is ok to be re-ordered into the 291 * read-locked region is ok to be re-ordered into the
285 * write side. As such, rely on RELEASE semantics. 292 * write side. As such, rely on RELEASE semantics.
286 */ 293 */
287 DEBUG_RWSEMS_WARN_ON(sem->owner != current); 294 DEBUG_RWSEMS_WARN_ON(sem->owner != current, sem);
288 tmp = atomic_long_add_return_release(-RWSEM_WAITING_BIAS, &sem->count); 295 tmp = atomic_long_add_return_release(-RWSEM_WAITING_BIAS, &sem->count);
289 rwsem_set_reader_owned(sem); 296 rwsem_set_reader_owned(sem);
290 if (tmp < 0) 297 if (tmp < 0)