[PATCH v2 05/17] sched/core: allow only preferred CPUs in is_cpu_allowed

From: Shrikanth Hegde

Date: Tue Apr 07 2026 - 15:23:15 EST


When possible, choose a preferred CPUs to pick.

Push task mechanism uses stopper thread which going to call
select_fallback_rq and use this mechanism to pick only a preferred CPU.

When task is affined only to non-preferred CPUs it should continue to
run there. Detect that by checking if cpus_ptr and cpu_preferred_mask
interesect or not.

Signed-off-by: Shrikanth Hegde <sshegde@xxxxxxxxxxxxx>
---
kernel/sched/core.c | 17 ++++++++++++++---
kernel/sched/sched.h | 12 ++++++++++++
2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7ea05a7a717b..336e7c694eb7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2463,9 +2463,16 @@ static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
if (is_migration_disabled(p))
return cpu_online(cpu);

- /* Non kernel threads are not allowed during either online or offline. */
- if (!(p->flags & PF_KTHREAD))
- return cpu_active(cpu);
+ /*
+ * Non kernel threads are not allowed during either online or offline.
+ * Ensure it is a preferred CPU to avoid further contention
+ */
+ if (!(p->flags & PF_KTHREAD)) {
+ if (!cpu_active(cpu))
+ return false;
+ if (!cpu_preferred(cpu) && task_can_run_on_preferred_cpu(p))
+ return false;
+ }

/* KTHREAD_IS_PER_CPU is always allowed. */
if (kthread_is_per_cpu(p))
@@ -2475,6 +2482,10 @@ static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
if (cpu_dying(cpu))
return false;

+ /* Try on preferred CPU first */
+ if (!cpu_preferred(cpu) && task_can_run_on_preferred_cpu(p))
+ return false;
+
/* But are allowed during online. */
return cpu_online(cpu);
}
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 88e0c93b9e21..7271af2ca64f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -4130,4 +4130,16 @@ DEFINE_CLASS_IS_UNCONDITIONAL(sched_change)

#include "ext.h"

+#ifdef CONFIG_PARAVIRT
+static inline bool task_can_run_on_preferred_cpu(struct task_struct *p)
+{
+ return cpumask_intersects(p->cpus_ptr, cpu_preferred_mask);
+}
+#else
+static inline bool task_can_run_on_preferred_cpu(struct task_struct *p)
+{
+ return true;
+}
+#endif
+
#endif /* _KERNEL_SCHED_SCHED_H */
--
2.47.3