aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-05-23 01:10:24 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-07-02 15:34:24 -0400
commit62fde6edf12b60fddb13a3f0a779c8be0bb7447e (patch)
tree2fa26e28ce311acb29c60f1595235240be6e7d97 /kernel/rcutree.c
parent28f5c693d03530eb15c5354f758b789189b98c37 (diff)
rcu: Make __call_rcu() handle invocation from idle
Although __call_rcu() is handled correctly when called from a momentary non-idle period, if it is called on a CPU that RCU believes to be idle on RCU_FAST_NO_HZ kernels, the callback might be indefinitely postponed. This commit therefore ensures that RCU is aware of the new callback and has a chance to force the CPU out of dyntick-idle mode when a new callback is posted. Reported-by: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 89addada3e3a..a4a9c916ad36 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -585,8 +585,6 @@ void rcu_nmi_exit(void)
585 WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1); 585 WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
586} 586}
587 587
588#ifdef CONFIG_PROVE_RCU
589
590/** 588/**
591 * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle 589 * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle
592 * 590 *
@@ -604,7 +602,7 @@ int rcu_is_cpu_idle(void)
604} 602}
605EXPORT_SYMBOL(rcu_is_cpu_idle); 603EXPORT_SYMBOL(rcu_is_cpu_idle);
606 604
607#ifdef CONFIG_HOTPLUG_CPU 605#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
608 606
609/* 607/*
610 * Is the current CPU online? Disable preemption to avoid false positives 608 * Is the current CPU online? Disable preemption to avoid false positives
@@ -645,9 +643,7 @@ bool rcu_lockdep_current_cpu_online(void)
645} 643}
646EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online); 644EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online);
647 645
648#endif /* #ifdef CONFIG_HOTPLUG_CPU */ 646#endif /* #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) */
649
650#endif /* #ifdef CONFIG_PROVE_RCU */
651 647
652/** 648/**
653 * rcu_is_cpu_rrupt_from_idle - see if idle or immediately interrupted from idle 649 * rcu_is_cpu_rrupt_from_idle - see if idle or immediately interrupted from idle
@@ -1904,6 +1900,13 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
1904 else 1900 else
1905 trace_rcu_callback(rsp->name, head, rdp->qlen_lazy, rdp->qlen); 1901 trace_rcu_callback(rsp->name, head, rdp->qlen_lazy, rdp->qlen);
1906 1902
1903 /*
1904 * If called from an extended quiescent state, invoke the RCU
1905 * core in order to force a re-evaluation of RCU's idleness.
1906 */
1907 if (rcu_is_cpu_idle())
1908 invoke_rcu_core();
1909
1907 /* If interrupts were disabled, don't dive into RCU core. */ 1910 /* If interrupts were disabled, don't dive into RCU core. */
1908 if (irqs_disabled_flags(flags)) { 1911 if (irqs_disabled_flags(flags)) {
1909 local_irq_restore(flags); 1912 local_irq_restore(flags);