rcu: Fix unpaired rcu_irq_enter() from locking selftests
authorFrederic Weisbecker <fweisbec@gmail.com>
Fri, 20 May 2011 00:09:54 +0000 (02:09 +0200)
committerSteve Conklin <sconklin@canonical.com>
Fri, 15 Jul 2011 17:21:01 +0000 (12:21 -0500)
commitbb6d542f371ae60616c667102badd2fa254ee7d7
tree2e04f354cedcef4b63124b7a9c940ed741e97237
parentfb69091cbe326b28a92bdd3e2fe0452f021584d5
rcu: Fix unpaired rcu_irq_enter() from locking selftests

BugLink: http://bugs.launchpad.net/bugs/793702

commit ba9f207c9f82115aba4ce04b22e0081af0ae300f upstream.

HARDIRQ_ENTER() maps to irq_enter() which calls rcu_irq_enter().
But HARDIRQ_EXIT() maps to __irq_exit() which doesn't call
rcu_irq_exit().

So for every locking selftest that simulates hardirq disabled,
we create an imbalance in the rcu extended quiescent state
internal state.

As a result, after the first missing rcu_irq_exit(), subsequent
irqs won't exit dyntick-idle mode after leaving the interrupt
handler.  This means that RCU won't see the affected CPU as being
in an extended quiescent state, resulting in long grace-period
delays (as in grace periods extending for hours).

To fix this, just use __irq_enter() to simulate the hardirq
context. This is sufficient for the locking selftests as we
don't need to exit any extended quiescent state or perform
any check that irqs normally do when they wake up from idle.

As a side effect, this patch makes it possible to restore
"rcu: Decrease memory-barrier usage based on semi-formal proof",
which eventually helped finding this bug.

Reported-and-tested-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
lib/locking-selftest.c