[RFC PATCH 2/3] sched: Allow isolated CPUs as a last resort during CPU freeze
Guopeng Zhang <[email protected]> Wed, 22 Jul 2026 19:52:37 +0800
| Newsgroups | org.kernel.vger.cgroups,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Guopeng Zhang <[email protected]> task_cpu_fallback_mask() normally excludes domain-isolated CPUs. During CPU freeze, however, every CPU except the suspend primary is taken offline. If the primary CPU is excluded from HK_TYPE_DOMAIN, the normal fallback mask eventually contains no active CPU and select_fallback_rq() can exhaust its fallback states. When CPU freeze is in progress and the normal fallback mask contains no active CPU, use task_cpu_possible_mask() as a temporary last resort if it still contains an active CPU. select_fallback_rq() will select only an active CPU from that mask, while architecture-specific task CPU capability constraints remain intact. Keep the normal housekeeping fallback while it contains an active CPU. The temporary affinity is preserved and restored by the preceding change. Fixes: bf5b0c27fad2 ("sched: Switch the fallback task allowed cpumask to HK_TYPE_DOMAIN") Signed-off-by: Guopeng Zhang <[email protected]> --- kernel/sched/core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8160d3287ad9..5f8ffded1a20 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2806,8 +2806,10 @@ do_set_cpus_allowed(struct task_struct *p, struct affinity_context *ctx) static DEFINE_RAW_SPINLOCK(cpu_fallback_lock); static bool cpu_fallback_active; -static bool mark_cpu_fallback(struct task_struct *p) +static bool mark_cpu_fallback(struct task_struct *p, + const struct cpumask **fallback_mask) { + const struct cpumask *possible_mask; unsigned long flags; bool temporary = false; @@ -2817,6 +2819,11 @@ static bool mark_cpu_fallback(struct task_struct *p) raw_spin_lock_irqsave(&cpu_fallback_lock, flags); if (cpu_fallback_active) { p->migration_flags |= MDF_CPUHP_FALLBACK; + if (!cpumask_intersects(*fallback_mask, cpu_active_mask)) { + possible_mask = task_cpu_possible_mask(p); + if (cpumask_intersects(possible_mask, cpu_active_mask)) + *fallback_mask = possible_mask; + } temporary = true; } raw_spin_unlock_irqrestore(&cpu_fallback_lock, flags); @@ -2842,7 +2849,7 @@ void set_cpus_allowed_force(struct task_struct *p, const struct cpumask *new_mas }; scoped_guard (__task_rq_lock, p) { - if (mark_cpu_fallback(p)) + if (mark_cpu_fallback(p, &ac.new_mask)) ac.flags = 0; do_set_cpus_allowed(p, &ac); } -- 2.43.0