aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2012-08-23 11:34:07 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-09-23 10:42:52 -0400
commit803b0ebae921714d1c36f0996db8125eda5fae53 (patch)
tree06366b934b3e703e4f8e633d853e9eb22495931b
parent7a11e2058f02feb6884efb067f328012c318a13f (diff)
time: RCU permitted to stop idle entry via softirq
The can_stop_idle_tick() function complains if a softirq vector is raised too late in the idle-entry process, presumably in order to prevent dangling softirq invocations from being delayed across the full idle period, which might be indefinitely long -- and if softirq was asserted any later than the call to this function, such a delay might well happen. However, RCU needs to be able to use softirq to stop idle entry in order to be able to drain RCU callbacks from the current CPU, which in turn enables faster entry into dyntick-idle mode, which in turn reduces power consumption. Because RCU takes this action at a well-defined point in the idle-entry path, it is safe for RCU to take this approach. This commit therefore silences the error message that is sometimes produced when the going-idle CPU suddenly finds that it has an RCU_SOFTIRQ to process. The error message will continue to be issued for other softirq vectors. Reported-by: Sedat Dilek <sedat.dilek@gmail.com> Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
-rw-r--r--include/linux/interrupt.h2
-rw-r--r--kernel/time/tick-sched.c3
2 files changed, 4 insertions, 1 deletions
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index c5f856a040b9..5e4e6170f43a 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -430,6 +430,8 @@ enum
430 NR_SOFTIRQS 430 NR_SOFTIRQS
431}; 431};
432 432
433#define SOFTIRQ_STOP_IDLE_MASK (~(1 << RCU_SOFTIRQ))
434
433/* map softirq index to softirq name. update 'softirq_to_name' in 435/* map softirq index to softirq name. update 'softirq_to_name' in
434 * kernel/softirq.c when adding a new softirq. 436 * kernel/softirq.c when adding a new softirq.
435 */ 437 */
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 024540f97f74..4b1785a7bb83 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -436,7 +436,8 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
436 if (unlikely(local_softirq_pending() && cpu_online(cpu))) { 436 if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
437 static int ratelimit; 437 static int ratelimit;
438 438
439 if (ratelimit < 10) { 439 if (ratelimit < 10 &&
440 (local_softirq_pending() & SOFTIRQ_STOP_IDLE_MASK)) {
440 printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n", 441 printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
441 (unsigned int) local_softirq_pending()); 442 (unsigned int) local_softirq_pending());
442 ratelimit++; 443 ratelimit++;