[RFC PATCH 2/3] sched: Allow isolated CPUs as a last resort during CPU freeze
From: Guopeng Zhang
Date: Wed Jul 22 2026 - 07:54:16 EST
From: Guopeng Zhang <zhangguopeng@xxxxxxxxxx>
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 <zhangguopeng@xxxxxxxxxx>
---
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