Re: [PATCH v3] sched/fair: Skip sched_balance_running cmpxchg when balance is not due
From: Shrikanth Hegde
Date: Fri Nov 07 2025 - 03:57:24 EST
On 11/7/25 8:27 AM, K Prateek Nayak wrote:
Hello Tim,
On 11/7/2025 4:57 AM, Tim Chen wrote:
@@ -11757,6 +11772,7 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,
.fbq_type = all,
.tasks = LIST_HEAD_INIT(env.tasks),
};
+ int need_unlock = false;
cpumask_and(cpus, sched_domain_span(sd), cpu_active_mask);
@@ -11768,6 +11784,13 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,
goto out_balanced;
}
+ if (idle != CPU_NEWLY_IDLE && (sd->flags & SD_SERIALIZE)) {
Can you also try removing "idle != CPU_NEWLY_IDLE" and see the workload behavior?
If workloads don't observe regression, it might be worth serializing it too.
+ if (atomic_cmpxchg_acquire(&sched_balance_running, 0, 1)) {
+ goto out_balanced;
+ }
+ need_unlock = true;
+ }
+
group = sched_balance_find_src_group(&env);
if (!group) {
schedstat_inc(sd->lb_nobusyg[idle]);
@@ -11892,6 +11915,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,
if (!cpumask_subset(cpus, env.dst_grpmask)) {
env.loop = 0;
env.loop_break = SCHED_NR_MIGRATE_BREAK;
+ if (need_unlock)
+ atomic_set_release(&sched_balance_running, 0);
I believe we should reset "need_unlock" to false here since "redo" can
fail the atomic_cmpxchg_acquire() while still having "need_unlock" set
to "true" and the "out_balanced" path will then perform the
atomic_set_release() when another CPU is in middle of a busy / idle
balance on a SD_SERIALIZE domain.
Yes. Setting need_unlock = false looks better.
We can also initialize the "need_unlock" to false just after
the redo label too - whichever you prefer.
nit. "need_unlock" can just be a bool instead of an int.
Apart from that, feel free to include:
Reviewed-by: K Prateek Nayak <kprateek.nayak@xxxxxxx>
+
goto redo;
}
goto out_all_pinned;
@@ -12008,6 +12034,9 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,
sd->balance_interval < sd->max_interval)
sd->balance_interval *= 2;
out:
+ if (need_unlock)
+ atomic_set_release(&sched_balance_running, 0);
+
return ld_moved;
}