| From 2cafb0a670cbd6571dec957bde90e908819d01d9 Mon Sep 17 00:00:00 2001 |
| From: john stultz <johnstul@us.ibm.com> |
| Date: Fri, 3 Jul 2009 08:44:25 -0500 |
| Subject: [PATCH] rtmutex: Fix CONFIG_DEBUG_RT_MUTEX lock underflow warnings |
| |
| commit 2c237cf3487394a46a92c002d8c15f19a8e4faf7 in tip. |
| |
| So if I enable CONFIG_DEBUG_RT_MUTEXES with 2.6.24.7-rt14, I tend to |
| quickly see a number of BUG warnings when running Java tests: |
| |
| BUG: jxeinajar/3383: lock count underflow! |
| Pid: 3383, comm: jxeinajar Not tainted 2.6.24-ibmrt2.5john #3 |
| |
| Call Trace: |
| [<ffffffff8107208d>] rt_mutex_deadlock_account_unlock+0x5d/0x70 |
| [<ffffffff817d6aa5>] rt_read_slowunlock+0x35/0x550 |
| [<ffffffff8107173d>] rt_mutex_up_read+0x3d/0xc0 |
| [<ffffffff81072a99>] rt_up_read+0x29/0x30 |
| [<ffffffff8106e34e>] do_futex+0x32e/0xd40 |
| [<ffffffff8107173d>] ? rt_mutex_up_read+0x3d/0xc0 |
| [<ffffffff81072a99>] ? rt_up_read+0x29/0x30 |
| [<ffffffff8106f370>] compat_sys_futex+0xa0/0x110 |
| [<ffffffff81010a36>] ? syscall_trace_enter+0x86/0xb0 |
| [<ffffffff8102ff04>] cstar_do_call+0x1b/0x65 |
| |
| INFO: lockdep is turned off. |
| --------------------------- |
| | preempt count: 00000001 ] |
| | 1-level deep critical section nesting: |
| ---------------------------------------- |
| ... [<ffffffff817d8e42>] .... __spin_lock_irqsave+0x22/0x60 |
| ......[<ffffffff817d6a93>] .. ( <= rt_read_slowunlock+0x23/0x550) |
| |
| After some debugging and with Steven's help, we realized that with |
| rwlocks, rt_mutex_deadlock_account_lock can be called multiple times in |
| parallel (where as in most cases the mutex must be held by the caller to |
| to call the function). This can cause integer lock_count value being |
| used to be non-atomically incremented. |
| |
| The following patch converts lock_count to a atomic_t and resolves the |
| warnings. |
| |
| Signed-off-by: John Stultz <johnstul@us.ibm.com> |
| Cc: Steven Rostedt <rostedt@goodmis.org> |
| Cc: Clark Williams <williams@redhat.com> |
| Cc: dvhltc <dvhltc@linux.vnet.ibm.com> |
| Signed-off-by: Ingo Molnar <mingo@elte.hu> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| |
| diff --git a/include/linux/sched.h b/include/linux/sched.h |
| index a958544..7e50287 100644 |
| --- a/include/linux/sched.h |
| +++ b/include/linux/sched.h |
| @@ -1479,7 +1479,7 @@ struct task_struct { |
| #define MAX_PREEMPT_TRACE 25 |
| #define MAX_LOCK_STACK MAX_PREEMPT_TRACE |
| #ifdef CONFIG_DEBUG_PREEMPT |
| - int lock_count; |
| + atomic_t lock_count; |
| # ifdef CONFIG_PREEMPT_RT |
| struct rt_mutex *owned_lock[MAX_LOCK_STACK]; |
| # endif |
| diff --git a/kernel/fork.c b/kernel/fork.c |
| index 8453327..81fcb2a 100644 |
| --- a/kernel/fork.c |
| +++ b/kernel/fork.c |
| @@ -1171,7 +1171,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, |
| if (retval) |
| goto bad_fork_cleanup_io; |
| #ifdef CONFIG_DEBUG_PREEMPT |
| - p->lock_count = 0; |
| + atomic_set(&p->lock_count, 0); |
| #endif |
| |
| if (pid != &init_struct_pid) { |
| diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c |
| index 2381c7a..e7e6314 100644 |
| --- a/kernel/rtmutex-debug.c |
| +++ b/kernel/rtmutex-debug.c |
| @@ -178,7 +178,7 @@ void |
| rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task) |
| { |
| #ifdef CONFIG_DEBUG_PREEMPT |
| - if (task->lock_count >= MAX_LOCK_STACK) { |
| + if (atomic_read(&task->lock_count) >= MAX_LOCK_STACK) { |
| if (!debug_locks_off()) |
| return; |
| printk("BUG: %s/%d: lock count overflow!\n", |
| @@ -187,16 +187,16 @@ rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task) |
| return; |
| } |
| #ifdef CONFIG_PREEMPT_RT |
| - task->owned_lock[task->lock_count] = lock; |
| + task->owned_lock[atomic_read(&task->lock_count)] = lock; |
| #endif |
| - task->lock_count++; |
| + atomic_inc(&task->lock_count); |
| #endif |
| } |
| |
| void rt_mutex_deadlock_account_unlock(struct task_struct *task) |
| { |
| #ifdef CONFIG_DEBUG_PREEMPT |
| - if (!task->lock_count) { |
| + if (!atomic_read(&task->lock_count)) { |
| if (!debug_locks_off()) |
| return; |
| printk("BUG: %s/%d: lock count underflow!\n", |
| @@ -204,9 +204,9 @@ void rt_mutex_deadlock_account_unlock(struct task_struct *task) |
| dump_stack(); |
| return; |
| } |
| - task->lock_count--; |
| + atomic_dec(&task->lock_count); |
| #ifdef CONFIG_PREEMPT_RT |
| - task->owned_lock[task->lock_count] = NULL; |
| + task->owned_lock[atomic_read(&task->lock_count)] = NULL; |
| #endif |
| #endif |
| } |
| -- |
| 1.7.1.1 |
| |