From fe6f4b82d6710d4f93e8f56ec60e971843ba90ef Mon Sep 17 00:00:00 2001 From: Stephen Dickey Date: Fri, 11 Dec 2020 17:10:32 -0800 Subject: [PATCH] ANDROID: sched/core: prevent timers on paused cpus The pause feature is designed to keep CPUs idle as much as possible. When the timers migration feature is enabled (with sysctl_timer_migration = 1 ) timer/hrtimer can be migrated to other CPUs than the CPU currently queueing the CPU. For example, a pinned kworker runs on a paused CPU and queued the timer. The other use case is an interrupt coming on paused CPU and queueing the time. Update the get nohz cpu path to use the active and online masks to prevent paused cpus from being woken up to queue a timer. Bug: 161210528 Change-Id: I3707164ab6ea35cb6202b6c6b2018e1583c3e95c Signed-off-by: Stephen Dickey --- kernel/sched/core.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 63b182e72b67..6c6384153c55 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -671,7 +671,7 @@ int get_nohz_timer_target(void) int i, cpu = smp_processor_id(), default_cpu = -1; struct sched_domain *sd; - if (housekeeping_cpu(cpu, HK_FLAG_TIMER)) { + if (housekeeping_cpu(cpu, HK_FLAG_TIMER) && cpu_active(cpu)) { if (!idle_cpu(cpu)) return cpu; default_cpu = cpu; @@ -691,8 +691,25 @@ int get_nohz_timer_target(void) } } - if (default_cpu == -1) - default_cpu = housekeeping_any_cpu(HK_FLAG_TIMER); + if (default_cpu == -1) { + for_each_cpu_and(i, cpu_active_mask, + housekeeping_cpumask(HK_FLAG_TIMER)) { + if (cpu == i) + continue; + + if (!idle_cpu(i)) { + cpu = i; + goto unlock; + } + } + + /* no active, not-idle, housekpeeing CPU found. */ + default_cpu = cpumask_any(cpu_active_mask); + + if (unlikely(default_cpu >= nr_cpu_ids)) + goto unlock; + } + cpu = default_cpu; unlock: rcu_read_unlock();