Linux Documentation
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] sched: Document WF_SYNC wakeup placement semantics
@ 2026-08-25 22:46 Shubhang Kaushik (Ampere)
  2026-08-25 22:46 ` [RFC PATCH 1/2] " Shubhang Kaushik (Ampere)
  2026-08-25 22:46 ` [RFC PATCH 2/2] sched/wait: Clarify WF_SYNC wakeup semantics Shubhang Kaushik (Ampere)
  0 siblings, 2 replies; 4+ messages in thread
From: Shubhang Kaushik (Ampere) @ 2026-08-25 22:46 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Randy Dunlap, Ingo Molnar,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann,
	Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider,
	K Prateek Nayak, Shubhang Kaushik, Shrikanth Hegde,
	Madadi Vineeth Reddy, Christopher Lameter
  Cc: linux-doc, linux-kernel, Shubhang Kaushik (Ampere)

WF_SYNC is passed by synchronous waitqueue wakeup helpers when the
caller expects the waker to schedule away soon. Its fair-class semantics
are not documented.

In particular, the waitqueue API comments state that a synchronous wakee
will not be migrated to another CPU. This is not guaranteed by the
current wakeup path. For a blocked fair-class wakee, wake_affine() can
select the waking CPU, but select_idle_sibling() can select another
eligible CPU.

Document the current fair-class CPU-selection and wakeup-preemption
behavior. Also correct the stale waitqueue API comments.

This series does not change scheduler behavior. It documents WF_SYNC as
a non-binding fair-class hint and does not define a stronger placement
policy.

Signed-off-by: Shubhang Kaushik (Ampere) <sh@gentwo.org>
---
Shubhang Kaushik (Ampere) (2):
      sched: Document WF_SYNC wakeup placement semantics
      sched/wait: Clarify WF_SYNC wakeup semantics

 Documentation/scheduler/index.rst               |   1 +
 Documentation/scheduler/sched-wake-affinity.rst | 133 ++++++++++++++++++++++++
 kernel/sched/wait.c                             |  30 +++---
 3 files changed, 150 insertions(+), 14 deletions(-)
---
base-commit: 66498c75b4f8017f62d720d9b59675bdf3abce91
change-id: 20260824-sched-wf-sync-doc-e92b4fe987f7

Best regards,
-- 
Shubhang Kaushik (Ampere) <sh@gentwo.org>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC PATCH 1/2] sched: Document WF_SYNC wakeup placement semantics
  2026-08-25 22:46 [RFC PATCH 0/2] sched: Document WF_SYNC wakeup placement semantics Shubhang Kaushik (Ampere)
@ 2026-08-25 22:46 ` Shubhang Kaushik (Ampere)
  2026-09-03  2:45   ` Madadi Vineeth Reddy
  2026-08-25 22:46 ` [RFC PATCH 2/2] sched/wait: Clarify WF_SYNC wakeup semantics Shubhang Kaushik (Ampere)
  1 sibling, 1 reply; 4+ messages in thread
From: Shubhang Kaushik (Ampere) @ 2026-08-25 22:46 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Randy Dunlap, Ingo Molnar,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann,
	Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider,
	K Prateek Nayak, Shubhang Kaushik, Shrikanth Hegde,
	Madadi Vineeth Reddy, Christopher Lameter
  Cc: linux-doc, linux-kernel, Shubhang Kaushik (Ampere)

WF_SYNC is supplied by callers that expect the waker to schedule away
soon. The fair-class wakeup path uses it as a heuristic, but its
placement and preemption behavior is not documented.

Document the current behavior from try_to_wake_up() through
select_task_rq_fair(), select_idle_sibling(), and preempt_sync(). In
particular, document that WF_SYNC does not bypass wake_wide(), does not
make wake_affine()'s target final, and does not require immediate wakee
preemption.

This documents existing behavior only. It does not establish a new
WF_SYNC placement policy.

Signed-off-by: Shubhang Kaushik (Ampere) <sh@gentwo.org>
---
 Documentation/scheduler/index.rst               |   1 +
 Documentation/scheduler/sched-wake-affinity.rst | 133 ++++++++++++++++++++++++
 2 files changed, 134 insertions(+)

diff --git a/Documentation/scheduler/index.rst b/Documentation/scheduler/index.rst
index 17ce8d76befc1bb1dc289e9243bdca98c9ccb172..ac95c79617fd2c03564ea4a9dad362091b9d1b86 100644
--- a/Documentation/scheduler/index.rst
+++ b/Documentation/scheduler/index.rst
@@ -14,6 +14,7 @@ Scheduler
     sched-design-CFS
     sched-eevdf
     sched-domains
+    sched-wake-affinity
     sched-capacity
     sched-energy
     schedutil
diff --git a/Documentation/scheduler/sched-wake-affinity.rst b/Documentation/scheduler/sched-wake-affinity.rst
new file mode 100644
index 0000000000000000000000000000000000000000..6b0dc83da537ad576130ef165a2bb1cf5abd814a
--- /dev/null
+++ b/Documentation/scheduler/sched-wake-affinity.rst
@@ -0,0 +1,133 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================
+WF_SYNC Wakeup Placement Hints
+==============================
+
+WF_SYNC is a wakeup flag supplied by callers that expect the waking task
+to schedule away soon after waking another task. It is a scheduler hint,
+not a CPU-placement request.
+
+The synchronous waitqueue helpers pass WF_SYNC to try_to_wake_up(). The
+wakeup path adds WF_TTWU before invoking the scheduler. WF_SYNC itself
+does not block, yield, or otherwise change the state of the waker.
+
+This document describes the current behavior for the fair scheduler.
+Other scheduler classes may ignore WF_SYNC or apply their own policy.
+
+Wakeup paths
+============
+
+A successful wakeup does not always select a CPU. If the wakee is already
+queued, try_to_wake_up() can complete the wakeup through ttwu_runnable().
+That path retains the wakee's current runqueue, although it can still
+invoke wakeup_preempt().
+
+For a wakee that is not queued, try_to_wake_up() calls
+select_task_rq(). If the wakee has one allowed CPU or migration is
+disabled, select_task_rq() bypasses the scheduler-class CPU-selection
+method and selects an allowed CPU directly.
+
+Fair-class CPU selection
+========================
+
+For a fair-class wakee, select_task_rq_fair() derives its local sync
+state as::
+
+        sync = (wake_flags & WF_SYNC) &&
+               !(current->flags & PF_EXITING);
+
+Thus, WF_SYNC does not influence wake-affine selection when the current
+task is exiting.
+
+For WF_TTWU wakeups, select_task_rq_fair() first calls record_wakee().
+It can then return before wake-affine selection in either of these cases:
+
+* WF_CURRENT_CPU is set and the waking CPU is allowed; or
+* find_energy_efficient_cpu() selects a CPU while the root domain is not
+  overutilized.
+
+Otherwise, the fair scheduler computes::
+
+        want_affine = !wake_wide(p) &&
+                      cpumask_test_cpu(cpu, p->cpus_ptr);
+
+wake_wide() uses the wakee-flip state maintained by record_wakee() to
+identify broad wakeup relationships. WF_SYNC does not override this
+classification.
+
+Wake affinity is considered only when want_affine is true, the domain has
+SD_WAKE_AFFINE set, and the wakee's previous CPU belongs to that domain.
+wake_affine() considers only two CPUs: the waking CPU and the wakee's
+previous CPU.
+
+With WF_SYNC, wake_affine_idle() can prefer the waking CPU when::
+
+        rq->nr_running - cfs_h_nr_delayed(rq) == 1
+
+wake_affine_weight() also adjusts the effective load comparison by
+removing the current task's load from the waking CPU and biasing the
+previous-CPU effective load.
+
+The result of wake_affine() is only a candidate. For WF_TTWU wakeups,
+select_task_rq_fair() passes that candidate to select_idle_sibling().
+
+Idle CPU selection
+==================
+
+select_idle_sibling() first tests whether the candidate CPU is idle and
+can run the wakee. If not, it can select:
+
+* the previous CPU when it is cache-affine and idle;
+* a recently used CPU when it is cache-affine and idle;
+* an idle SMT sibling; or
+* another idle CPU in the relevant search domain.
+
+On asymmetric-capacity systems, the search uses sd_asym_cpucapacity when
+available. Otherwise, it uses sd_llc for the candidate CPU.
+
+Consequently, WF_SYNC does not guarantee that the wakee runs on the
+waker CPU, remains on its previous CPU, avoids migration, or shares a
+core with the waker.
+
+Fair-class wakeup preemption
+============================
+
+WF_SYNC can also affect wakeup_preempt_fair(). The normal fair-class
+preemption checks run first. In particular, a non-idle wakee can preempt
+an idle entity, and PREEMPT_SHORT can select the wakee before the
+WF_SYNC-specific path is reached.
+
+If the wakee becomes the next buddy after those checks, preempt_sync()
+uses WF_SYNC to decide whether to request rescheduling. The wakee must
+be earlier than the current entity, and the current entity must have run
+for at least the applicable threshold. The threshold is
+sysctl_sched_migration_cost, divided by four when WF_RQ_SELECTED is set.
+
+If those conditions are not met, preempt_sync() returns
+PREEMPT_WAKEUP_NONE. Consequently, WF_SYNC neither guarantees nor
+prevents immediate wakee preemption. On UP, it can avoid an unnecessary
+preemption when the waker is expected to schedule away.
+
+Semantics and policy
+====================
+
+WF_SYNC is a non-binding hint. It does not guarantee that the wakee:
+
+* runs on the waker CPU;
+* remains on its previous CPU;
+* avoids migration;
+* shares a core with the waker; or
+* immediately preempts the current task.
+
+The scheduler does not verify that the waker subsequently blocks.
+Callers may therefore use WF_SYNC where the waker continues to execute,
+or where several wakeups are issued before it schedules away.
+
+The current policy leaves the locality, parallelism, topology, load, and
+capacity tradeoffs to the scheduler. It does not require the wakee to
+remain on the waker CPU when that CPU has no other runnable task.
+
+Any future policy that strengthens WF_SYNC placement semantics must
+consider the different call sites, workload patterns, and hardware
+topologies that use the flag.

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [RFC PATCH 2/2] sched/wait: Clarify WF_SYNC wakeup semantics
  2026-08-25 22:46 [RFC PATCH 0/2] sched: Document WF_SYNC wakeup placement semantics Shubhang Kaushik (Ampere)
  2026-08-25 22:46 ` [RFC PATCH 1/2] " Shubhang Kaushik (Ampere)
@ 2026-08-25 22:46 ` Shubhang Kaushik (Ampere)
  1 sibling, 0 replies; 4+ messages in thread
From: Shubhang Kaushik (Ampere) @ 2026-08-25 22:46 UTC (permalink / raw)
  To: Jonathan Corbet, Shuah Khan, Randy Dunlap, Ingo Molnar,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann,
	Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider,
	K Prateek Nayak, Shubhang Kaushik, Shrikanth Hegde,
	Madadi Vineeth Reddy, Christopher Lameter
  Cc: linux-doc, linux-kernel, Shubhang Kaushik (Ampere)

The synchronous waitqueue wakeup comments state that the wakee will not
be migrated to another CPU. This is not guaranteed by the current
scheduler wakeup path.

The synchronous helpers pass WF_SYNC to waitqueue wake functions. The
default wake function forwards it to the scheduler, where fair-class
tasks can use it as a wakeup-placement and preemption hint.

Correct the API comments to describe this behavior and remove the
incorrect no-migration guarantee.

Signed-off-by: Shubhang Kaushik (Ampere) <sh@gentwo.org>
---
 kernel/sched/wait.c | 30 ++++++++++++++++--------------
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c
index d033f600f48c6fc3a0a088ea5d9f6ed95ec4c86e..ac1d260a6a37fc35b934079706819b79e20df4ba 100644
--- a/kernel/sched/wait.c
+++ b/kernel/sched/wait.c
@@ -174,15 +174,16 @@ EXPORT_SYMBOL_GPL(__wake_up_locked_key);
  * @mode: which threads
  * @key: opaque value to be passed to wakeup targets
  *
- * The sync wakeup differs that the waker knows that it will schedule
- * away soon, so while the target thread will be woken up, it will not
- * be migrated to another CPU - ie. the two threads are 'synchronized'
- * with each other. This can prevent needless bouncing between CPUs.
+ * The caller expects the waker to schedule away soon. This helper passes
+ * WF_SYNC to waitqueue wake functions. The default wake function forwards
+ * it to the scheduler.
  *
- * On UP it can prevent extra preemption.
+ * For fair-class tasks, WF_SYNC is a wakeup-placement and preemption
+ * hint. It does not guarantee that the wakee will run on the waker CPU
+ * or avoid migration. On UP, this may avoid an unnecessary preemption.
  *
- * If this function wakes up a task, it executes a full memory barrier before
- * accessing the task state.
+ * If this function wakes up a task, it executes a full memory barrier
+ * before accessing the task state.
  */
 void __wake_up_sync_key(struct wait_queue_head *wq_head, unsigned int mode,
 			void *key)
@@ -200,15 +201,16 @@ EXPORT_SYMBOL_GPL(__wake_up_sync_key);
  * @mode: which threads
  * @key: opaque value to be passed to wakeup targets
  *
- * The sync wakeup differs in that the waker knows that it will schedule
- * away soon, so while the target thread will be woken up, it will not
- * be migrated to another CPU - ie. the two threads are 'synchronized'
- * with each other. This can prevent needless bouncing between CPUs.
+ * The caller expects the waker to schedule away soon. This helper passes
+ * WF_SYNC to waitqueue wake functions. The default wake function forwards
+ * it to the scheduler
  *
- * On UP it can prevent extra preemption.
+ * For fair-class tasks, WF_SYNC is a wakeup-placement and preemption
+ * hint. It does not guarantee that the wakee will run on the waker CPU
+ * or avoid migration. On UP, this may avoid an unnecessary preemption.
  *
- * If this function wakes up a task, it executes a full memory barrier before
- * accessing the task state.
+ * If this function wakes up a task, it executes a full memory barrier
+ * before accessing the task state.
  */
 void __wake_up_locked_sync_key(struct wait_queue_head *wq_head,
 			       unsigned int mode, void *key)

-- 
2.52.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH 1/2] sched: Document WF_SYNC wakeup placement semantics
  2026-08-25 22:46 ` [RFC PATCH 1/2] " Shubhang Kaushik (Ampere)
@ 2026-09-03  2:45   ` Madadi Vineeth Reddy
  0 siblings, 0 replies; 4+ messages in thread
From: Madadi Vineeth Reddy @ 2026-09-03  2:45 UTC (permalink / raw)
  To: Shubhang Kaushik (Ampere)
  Cc: Jonathan Corbet, Shuah Khan, Randy Dunlap, Ingo Molnar,
	Peter Zijlstra, Juri Lelli, Vincent Guittot, Dietmar Eggemann,
	Steven Rostedt, Ben Segall, Mel Gorman, Valentin Schneider,
	K Prateek Nayak, Shubhang Kaushik, Christopher Lameter,
	Shrikanth Hegde, linux-doc, linux-kernel, Madadi Vineeth Reddy

On 26/08/26 04:16, Shubhang Kaushik (Ampere) wrote:
> WF_SYNC is supplied by callers that expect the waker to schedule away
> soon. The fair-class wakeup path uses it as a heuristic, but its
> placement and preemption behavior is not documented.
> 
> Document the current behavior from try_to_wake_up() through
> select_task_rq_fair(), select_idle_sibling(), and preempt_sync(). In
> particular, document that WF_SYNC does not bypass wake_wide(), does not
> make wake_affine()'s target final, and does not require immediate wakee
> preemption.
> 
> This documents existing behavior only. It does not establish a new
> WF_SYNC placement policy.
> 
> Signed-off-by: Shubhang Kaushik (Ampere) <sh@gentwo.org>
> ---
>  Documentation/scheduler/index.rst               |   1 +
>  Documentation/scheduler/sched-wake-affinity.rst | 133 ++++++++++++++++++++++++
>  2 files changed, 134 insertions(+)
> 
> diff --git a/Documentation/scheduler/index.rst b/Documentation/scheduler/index.rst
> index 17ce8d76befc1bb1dc289e9243bdca98c9ccb172..ac95c79617fd2c03564ea4a9dad362091b9d1b86 100644
> --- a/Documentation/scheduler/index.rst
> +++ b/Documentation/scheduler/index.rst
> @@ -14,6 +14,7 @@ Scheduler
>      sched-design-CFS
>      sched-eevdf
>      sched-domains
> +    sched-wake-affinity
>      sched-capacity
>      sched-energy
>      schedutil
> diff --git a/Documentation/scheduler/sched-wake-affinity.rst b/Documentation/scheduler/sched-wake-affinity.rst
> new file mode 100644
> index 0000000000000000000000000000000000000000..6b0dc83da537ad576130ef165a2bb1cf5abd814a
> --- /dev/null
> +++ b/Documentation/scheduler/sched-wake-affinity.rst
> @@ -0,0 +1,133 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +==============================
> +WF_SYNC Wakeup Placement Hints
> +==============================
> +
> +WF_SYNC is a wakeup flag supplied by callers that expect the waking task
> +to schedule away soon after waking another task. It is a scheduler hint,
> +not a CPU-placement request.
> +
> +The synchronous waitqueue helpers pass WF_SYNC to try_to_wake_up(). The
> +wakeup path adds WF_TTWU before invoking the scheduler. WF_SYNC itself
> +does not block, yield, or otherwise change the state of the waker.
> +
> +This document describes the current behavior for the fair scheduler.
> +Other scheduler classes may ignore WF_SYNC or apply their own policy.
> +
> +Wakeup paths
> +============
> +
> +A successful wakeup does not always select a CPU. If the wakee is already
> +queued, try_to_wake_up() can complete the wakeup through ttwu_runnable().
> +That path retains the wakee's current runqueue, although it can still
> +invoke wakeup_preempt().
> +
> +For a wakee that is not queued, try_to_wake_up() calls
> +select_task_rq(). If the wakee has one allowed CPU or migration is
> +disabled, select_task_rq() bypasses the scheduler-class CPU-selection
> +method and selects an allowed CPU directly.
> +
> +Fair-class CPU selection
> +========================
> +
> +For a fair-class wakee, select_task_rq_fair() derives its local sync
> +state as::
> +
> +        sync = (wake_flags & WF_SYNC) &&
> +               !(current->flags & PF_EXITING);
> +
> +Thus, WF_SYNC does not influence wake-affine selection when the current
> +task is exiting.
> +
> +For WF_TTWU wakeups, select_task_rq_fair() first calls record_wakee().
> +It can then return before wake-affine selection in either of these cases:
> +
> +* WF_CURRENT_CPU is set and the waking CPU is allowed; or
> +* find_energy_efficient_cpu() selects a CPU while the root domain is not
> +  overutilized.
> +
> +Otherwise, the fair scheduler computes::
> +
> +        want_affine = !wake_wide(p) &&
> +                      cpumask_test_cpu(cpu, p->cpus_ptr);
> +
> +wake_wide() uses the wakee-flip state maintained by record_wakee() to
> +identify broad wakeup relationships. WF_SYNC does not override this
> +classification.
> +
> +Wake affinity is considered only when want_affine is true, the domain has
> +SD_WAKE_AFFINE set, and the wakee's previous CPU belongs to that domain.
> +wake_affine() considers only two CPUs: the waking CPU and the wakee's
> +previous CPU.
> +
> +With WF_SYNC, wake_affine_idle() can prefer the waking CPU when::
> +
> +        rq->nr_running - cfs_h_nr_delayed(rq) == 1
> +
> +wake_affine_weight() also adjusts the effective load comparison by
> +removing the current task's load from the waking CPU and biasing the
> +previous-CPU effective load.
> +
> +The result of wake_affine() is only a candidate. For WF_TTWU wakeups,
> +select_task_rq_fair() passes that candidate to select_idle_sibling().

This document reproduces the implementation literally like want_affine,
nr_running, helper names. This could quickly go stale with code changes
and nothing will tell us then. I think the contract doesn't need the
call flow.

Thanks,
Vineeth

> +
> +Idle CPU selection
> +==================
> +
> +select_idle_sibling() first tests whether the candidate CPU is idle and
> +can run the wakee. If not, it can select:
> +
> +* the previous CPU when it is cache-affine and idle;
> +* a recently used CPU when it is cache-affine and idle;
> +* an idle SMT sibling; or
> +* another idle CPU in the relevant search domain.
> +
> +On asymmetric-capacity systems, the search uses sd_asym_cpucapacity when
> +available. Otherwise, it uses sd_llc for the candidate CPU.
> +
> +Consequently, WF_SYNC does not guarantee that the wakee runs on the
> +waker CPU, remains on its previous CPU, avoids migration, or shares a
> +core with the waker.
> +
> +Fair-class wakeup preemption
> +============================
> +
> +WF_SYNC can also affect wakeup_preempt_fair(). The normal fair-class
> +preemption checks run first. In particular, a non-idle wakee can preempt
> +an idle entity, and PREEMPT_SHORT can select the wakee before the
> +WF_SYNC-specific path is reached.
> +
> +If the wakee becomes the next buddy after those checks, preempt_sync()
> +uses WF_SYNC to decide whether to request rescheduling. The wakee must
> +be earlier than the current entity, and the current entity must have run
> +for at least the applicable threshold. The threshold is
> +sysctl_sched_migration_cost, divided by four when WF_RQ_SELECTED is set.
> +
> +If those conditions are not met, preempt_sync() returns
> +PREEMPT_WAKEUP_NONE. Consequently, WF_SYNC neither guarantees nor
> +prevents immediate wakee preemption. On UP, it can avoid an unnecessary
> +preemption when the waker is expected to schedule away.
> +
> +Semantics and policy
> +====================
> +
> +WF_SYNC is a non-binding hint. It does not guarantee that the wakee:
> +
> +* runs on the waker CPU;
> +* remains on its previous CPU;
> +* avoids migration;
> +* shares a core with the waker; or
> +* immediately preempts the current task.
> +
> +The scheduler does not verify that the waker subsequently blocks.
> +Callers may therefore use WF_SYNC where the waker continues to execute,
> +or where several wakeups are issued before it schedules away.
> +
> +The current policy leaves the locality, parallelism, topology, load, and
> +capacity tradeoffs to the scheduler. It does not require the wakee to
> +remain on the waker CPU when that CPU has no other runnable task.
> +
> +Any future policy that strengthens WF_SYNC placement semantics must
> +consider the different call sites, workload patterns, and hardware
> +topologies that use the flag.
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-09-03  2:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-25 22:46 [RFC PATCH 0/2] sched: Document WF_SYNC wakeup placement semantics Shubhang Kaushik (Ampere)
2026-08-25 22:46 ` [RFC PATCH 1/2] " Shubhang Kaushik (Ampere)
2026-09-03  2:45   ` Madadi Vineeth Reddy
2026-08-25 22:46 ` [RFC PATCH 2/2] sched/wait: Clarify WF_SYNC wakeup semantics Shubhang Kaushik (Ampere)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox