aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-01-22 19:01:40 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-23 05:10:57 -0500
commit7e49fcce1bdadd723ae6a0b3b324c4daced61563 (patch)
treea2bf1a143ed33ca01612dfab1fb7c993c467cdb0 /kernel/sched.c
parentb06a830183b610c0a88c29a92feb7991a867ab46 (diff)
trace, lockdep: manual preempt count adding for local_bh_disable
Impact: fix to preempt trace triggering lockdep check_flag failure In local_bh_disable, the use of add_preempt_count causes the preempt tracer to start recording the time preemption is off. But because it already modified the preempt_count to show softirqs disabled, and before it called the lockdep code to handle this, it causes a state that lockdep can not handle. The preempt tracer will reset the ring buffer on start of a trace, and the ring buffer reset code does a spin_lock_irqsave. This calls into lockdep and lockdep will fail when it detects the invalid state of having softirqs disabled but the internal current->softirqs_enabled is still set. The fix is to manually add the SOFTIRQ_OFFSET to preempt count and call the preempt tracer code outside the lockdep critical area. Thanks to Peter Zijlstra for suggesting this solution. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 52bbf1c842a..c154825ae75 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4399,10 +4399,7 @@ void scheduler_tick(void)
4399#endif 4399#endif
4400} 4400}
4401 4401
4402#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \ 4402unsigned long get_parent_ip(unsigned long addr)
4403 defined(CONFIG_PREEMPT_TRACER))
4404
4405static inline unsigned long get_parent_ip(unsigned long addr)
4406{ 4403{
4407 if (in_lock_functions(addr)) { 4404 if (in_lock_functions(addr)) {
4408 addr = CALLER_ADDR2; 4405 addr = CALLER_ADDR2;
@@ -4412,6 +4409,9 @@ static inline unsigned long get_parent_ip(unsigned long addr)
4412 return addr; 4409 return addr;
4413} 4410}
4414 4411
4412#if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
4413 defined(CONFIG_PREEMPT_TRACER))
4414
4415void __kprobes add_preempt_count(int val) 4415void __kprobes add_preempt_count(int val)
4416{ 4416{
4417#ifdef CONFIG_DEBUG_PREEMPT 4417#ifdef CONFIG_DEBUG_PREEMPT