From: Frederic Weisbecker Wake up a CPU when a timer list timer is enqueued there and the CPU is in adaptive nohz mode. Sending an IPI to it makes it reconsidering the next timer to program on top of recent updates. Signed-off-by: Frederic Weisbecker Cc: Alessio Igor Bogani Cc: Andrew Morton Cc: Avi Kivity Cc: Chris Metcalf Cc: Christoph Lameter Cc: Daniel Lezcano Cc: Geoff Levand Cc: Gilad Ben Yossef Cc: Hakan Akkan Cc: Ingo Molnar Cc: Kevin Hilman Cc: Max Krasnyansky Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Stephen Hemminger Cc: Steven Rostedt Cc: Sven-Thorsten Dietrich Cc: Thomas Gleixner --- include/linux/sched.h | 4 ++-- kernel/sched/core.c | 28 +++++++++++++++++++++++++++- kernel/timer.c | 2 +- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 749752e..a41dd22 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1972,9 +1972,9 @@ static inline void idle_task_exit(void) {} #endif #if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP) -extern void wake_up_idle_cpu(int cpu); +extern void wake_up_nohz_cpu(int cpu); #else -static inline void wake_up_idle_cpu(int cpu) { } +static inline void wake_up_nohz_cpu(int cpu) { } #endif extern unsigned int sysctl_sched_latency; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2716b79..7b35eda 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -578,7 +578,7 @@ unlock: * account when the CPU goes back to idle and evaluates the timer * wheel for the next timer event. */ -void wake_up_idle_cpu(int cpu) +static void wake_up_idle_cpu(int cpu) { struct rq *rq = cpu_rq(cpu); @@ -608,6 +608,32 @@ void wake_up_idle_cpu(int cpu) smp_send_reschedule(cpu); } +static bool wake_up_cpuset_nohz_cpu(int cpu) +{ +#ifdef CONFIG_CPUSETS_NO_HZ + /* + * If the current CPU doesn't see the target as nohz + * then it means the target hasn't seen itself nohz + * yet either. In this case we don't send an IPI to the + * target because it hasn't yet tried to stop the tick. + * But if the nohz flag is set concurrently, the target + * will find the newly enqueued timer once we release + * the base->lock. + */ + if (cpuset_cpu_adaptive_nohz(cpu)) { + smp_cpuset_update_nohz(cpu); + return true; + } +#endif + return false; +} + +void wake_up_nohz_cpu(int cpu) +{ + if (!wake_up_cpuset_nohz_cpu(cpu)) + wake_up_idle_cpu(cpu); +} + static inline bool got_nohz_idle_kick(void) { int cpu = smp_processor_id(); diff --git a/kernel/timer.c b/kernel/timer.c index 367d008..51e20ca 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -936,7 +936,7 @@ void add_timer_on(struct timer_list *timer, int cpu) * makes sure that a CPU on the way to idle can not evaluate * the timer wheel. */ - wake_up_idle_cpu(cpu); + wake_up_nohz_cpu(cpu); spin_unlock_irqrestore(&base->lock, flags); } EXPORT_SYMBOL_GPL(add_timer_on); -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/