[PATCH 6/7] sched/fair: Push sched_balance_newidle() unlock down

From: Peter Zijlstra

Date: Fri Aug 28 2026 - 06:42:04 EST


By pushing down the this_rq unlock, there are more cases where the lock isn't
dropped.

XXX needs numbers

Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
---
kernel/sched/fair.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)

--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -13417,6 +13417,7 @@ static int sched_balance_rq(int this_cpu
struct sched_domain *sd, enum cpu_idle_type idle,
int *continue_balancing)
{
+ bool lock_rq = false, unlock_rq = idle == CPU_NEWLY_IDLE;
int ld_moved, cur_ld_moved, active_balance = 0;
struct sched_domain *sd_parent = sd->parent;
struct sched_group *group;
@@ -13485,6 +13486,12 @@ static int sched_balance_rq(int this_cpu
*/
env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running);

+ if (unlock_rq) {
+ raw_spin_rq_unlock(this_rq);
+ unlock_rq = false;
+ lock_rq = true;
+ }
+
more_balance:
rq_lock_irqsave(busiest, &rf);
update_rq_clock(busiest);
@@ -13613,6 +13620,12 @@ static int sched_balance_rq(int this_cpu
if (!need_active_balance(&env))
goto out_unbalanced;

+ if (unlock_rq) {
+ raw_spin_rq_unlock(this_rq);
+ unlock_rq = false;
+ lock_rq = true;
+ }
+
scoped_guard (raw_spin_rq_lock_irqsave, busiest) {
/*
* Don't kick the active_load_balance_cpu_stop,
@@ -13706,6 +13719,8 @@ static int sched_balance_rq(int this_cpu
out:
if (need_unlock)
atomic_set_release(&sched_balance_running, 0);
+ if (lock_rq)
+ raw_spin_rq_lock(this_rq);

return ld_moved;
}
@@ -14582,8 +14597,6 @@ static void sched_balance_newidle(struct
t0 = sched_clock_cpu(this_cpu);
__sched_balance_update_blocked_averages(this_rq);

- raw_spin_rq_unlock(this_rq);
-
for_each_domain(this_cpu, sd) {
u64 domain_cost;

@@ -14634,8 +14647,6 @@ static void sched_balance_newidle(struct
break;
}

- raw_spin_rq_lock(this_rq);
-
if (curr_cost > this_rq->max_idle_balance_cost)
this_rq->max_idle_balance_cost = curr_cost;