aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2011-06-21 11:17:27 -0400
committerIngo Molnar <mingo@elte.hu>2011-06-22 05:39:34 -0400
commitdd4e5d3ac4a76b868daf30e35bd572def96c30ed (patch)
tree76ee78919a212b2c28171d39ccb53195aec7284f
parent4f2a8d3cf5e0486fd547633fa86c5d130ae98cad (diff)
lockdep: Fix trace_[soft,hard]irqs_[on,off]() recursion
Commit: 1efc5da3cf56: [PATCH] order of lockdep off/on in vprintk() should be changed explains the reason for having raw_local_irq_*() and lockdep_off() in printk(). Instead of working around the broken recursion detection of interrupt state tracking, fix it. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: efault@gmx.de Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Link: http://lkml.kernel.org/r/20110621153806.185242734@chello.nl Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/lockdep.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 63437d065ac8..81968a065b4c 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -2478,15 +2478,10 @@ mark_held_locks(struct task_struct *curr, enum mark_type mark)
2478/* 2478/*
2479 * Hardirqs will be enabled: 2479 * Hardirqs will be enabled:
2480 */ 2480 */
2481void trace_hardirqs_on_caller(unsigned long ip) 2481static void __trace_hardirqs_on_caller(unsigned long ip)
2482{ 2482{
2483 struct task_struct *curr = current; 2483 struct task_struct *curr = current;
2484 2484
2485 time_hardirqs_on(CALLER_ADDR0, ip);
2486
2487 if (unlikely(!debug_locks || current->lockdep_recursion))
2488 return;
2489
2490 if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled))) 2485 if (DEBUG_LOCKS_WARN_ON(unlikely(early_boot_irqs_disabled)))
2491 return; 2486 return;
2492 2487
@@ -2502,8 +2497,6 @@ void trace_hardirqs_on_caller(unsigned long ip)
2502 /* we'll do an OFF -> ON transition: */ 2497 /* we'll do an OFF -> ON transition: */
2503 curr->hardirqs_enabled = 1; 2498 curr->hardirqs_enabled = 1;
2504 2499
2505 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
2506 return;
2507 if (DEBUG_LOCKS_WARN_ON(current->hardirq_context)) 2500 if (DEBUG_LOCKS_WARN_ON(current->hardirq_context))
2508 return; 2501 return;
2509 /* 2502 /*
@@ -2525,6 +2518,21 @@ void trace_hardirqs_on_caller(unsigned long ip)
2525 curr->hardirq_enable_event = ++curr->irq_events; 2518 curr->hardirq_enable_event = ++curr->irq_events;
2526 debug_atomic_inc(hardirqs_on_events); 2519 debug_atomic_inc(hardirqs_on_events);
2527} 2520}
2521
2522void trace_hardirqs_on_caller(unsigned long ip)
2523{
2524 time_hardirqs_on(CALLER_ADDR0, ip);
2525
2526 if (unlikely(!debug_locks || current->lockdep_recursion))
2527 return;
2528
2529 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
2530 return;
2531
2532 current->lockdep_recursion = 1;
2533 __trace_hardirqs_on_caller(ip);
2534 current->lockdep_recursion = 0;
2535}
2528EXPORT_SYMBOL(trace_hardirqs_on_caller); 2536EXPORT_SYMBOL(trace_hardirqs_on_caller);
2529 2537
2530void trace_hardirqs_on(void) 2538void trace_hardirqs_on(void)
@@ -2574,7 +2582,7 @@ void trace_softirqs_on(unsigned long ip)
2574{ 2582{
2575 struct task_struct *curr = current; 2583 struct task_struct *curr = current;
2576 2584
2577 if (unlikely(!debug_locks)) 2585 if (unlikely(!debug_locks || current->lockdep_recursion))
2578 return; 2586 return;
2579 2587
2580 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) 2588 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))
@@ -2585,6 +2593,7 @@ void trace_softirqs_on(unsigned long ip)
2585 return; 2593 return;
2586 } 2594 }
2587 2595
2596 current->lockdep_recursion = 1;
2588 /* 2597 /*
2589 * We'll do an OFF -> ON transition: 2598 * We'll do an OFF -> ON transition:
2590 */ 2599 */
@@ -2599,6 +2608,7 @@ void trace_softirqs_on(unsigned long ip)
2599 */ 2608 */
2600 if (curr->hardirqs_enabled) 2609 if (curr->hardirqs_enabled)
2601 mark_held_locks(curr, SOFTIRQ); 2610 mark_held_locks(curr, SOFTIRQ);
2611 current->lockdep_recursion = 0;
2602} 2612}
2603 2613
2604/* 2614/*
@@ -2608,7 +2618,7 @@ void trace_softirqs_off(unsigned long ip)
2608{ 2618{
2609 struct task_struct *curr = current; 2619 struct task_struct *curr = current;
2610 2620
2611 if (unlikely(!debug_locks)) 2621 if (unlikely(!debug_locks || current->lockdep_recursion))
2612 return; 2622 return;
2613 2623
2614 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) 2624 if (DEBUG_LOCKS_WARN_ON(!irqs_disabled()))