Re: [PATCH] sched/fair: Prefer waker CPU for reciprocal sync wakeups

From: Shubhang

Date: Wed Jul 22 2026 - 14:10:57 EST


Hi Christian,

Thanks for the review.

On Wed, 22 Jul 2026, Christian Loehle wrote:

On 7/22/26 01:04, Shubhang Kaushik (Ampere) wrote:
Pipe and futex ping-pong workloads can be dominated by handoff cost. In
such cases, placing the wakee on an idle CPU can be slower than keeping
the pair on the same runqueue.

Use the existing last_wakee and wake_wide() state to identify narrow
reciprocal WF_SYNC wakeups:

A wakes B
B wakes A
A wakes B
...

But the futex ping-pong doesn't set WF_SYNC in the first place or am I missing
something?

Yes, the futex runs were only regression checks here. I'll drop the futex wording from the description and keep the motivation to pipe sync handoffs.

@@ -9548,6 +9570,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
int cpu = smp_processor_id();
int new_cpu = prev_cpu;
int want_affine = 0;
+ int wide = 0;
/* SD_flags and WF_flags share the first nibble */
int sd_flag = wake_flags & 0xF;

@@ -9557,6 +9580,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
lockdep_assert_held(&p->pi_lock);
if (wake_flags & WF_TTWU) {
record_wakee(p);
+ wide = wake_wide(p);

if ((wake_flags & WF_CURRENT_CPU) &&
cpumask_test_cpu(cpu, p->cpus_ptr))
@@ -9569,7 +9593,12 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int wake_flags)
new_cpu = prev_cpu;
}

- want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr);
+ if (sync && !wide &&
+ READ_ONCE(p->last_wakee) == current &&
+ prefer_sync_pair_cpu(p, cpu))
+ return cpu;

This must move further below (to check for SD_WAKE_AFFINE) otherwise it ignores isolcpus.

Agreed. The early return bypasses the existing SD_WAKE_AFFINE check,
including the isolcpus handling that comes through the sched-domain
setup. I'll move it into the wake-affine block so it only applies after
that check.

Regards,
Shubhang Kaushik