[PATCH 01/14] sched/idle: Handle offlining first in idle loop

Frederic Weisbecker posted 14 patches 20 hours ago
[PATCH 01/14] sched/idle: Handle offlining first in idle loop
Posted by Frederic Weisbecker 20 hours ago
Offline handling happens from within the inner idle loop,
after the beginning of dyntick cputime accounting, nohz idle
load balancing and TIF_NEED_RESCHED polling.

This is not necessary and even buggy because:

* There is no dyntick handling to do. And calling tick_nohz_idle_enter()
  messes up with the struct tick_sched reset that was performed on
  tick_sched_timer_dying().

* There is no nohz idle balancing to do.

* Polling on TIF_RESCHED is irrelevant at this stage, there are no more
  tasks allowed to run.

* No need to check if need_resched() before offline handling since
  stop_machine is done and all per-cpu kthread should be done with
  their job.

Therefore move the offline handling at the beginning of the idle loop.
This will also ease the idle cputime unification later by not elapsing
idle time while offline through the call to:

	tick_nohz_idle_enter() -> tick_nohz_start_idle()

Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Tested-by: Shrikanth Hegde <sshegde@linux.ibm.com>
---
 kernel/sched/idle.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 3681b6ad9276..521a076d8845 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -260,6 +260,14 @@ static void do_idle(void)
 {
 	int cpu = smp_processor_id();
 
+	if (cpu_is_offline(cpu)) {
+		local_irq_disable();
+		/* All per-CPU kernel threads should be done by now. */
+		WARN_ON_ONCE(need_resched());
+		cpuhp_report_idle_dead();
+		arch_cpu_idle_dead();
+	}
+
 	/*
 	 * Check if we need to update blocked load
 	 */
@@ -311,11 +319,6 @@ static void do_idle(void)
 		 */
 		local_irq_disable();
 
-		if (cpu_is_offline(cpu)) {
-			cpuhp_report_idle_dead();
-			arch_cpu_idle_dead();
-		}
-
 		arch_cpu_idle_enter();
 		rcu_nocb_flush_deferred_wakeup();
 
-- 
2.53.0
Re: [PATCH 01/14] sched/idle: Handle offlining first in idle loop
Posted by Rafael J. Wysocki 19 hours ago
On Tue, Mar 31, 2026 at 3:16 PM Frederic Weisbecker <frederic@kernel.org> wrote:
>
> Offline handling happens from within the inner idle loop,
> after the beginning of dyntick cputime accounting, nohz idle
> load balancing and TIF_NEED_RESCHED polling.
>
> This is not necessary and even buggy because:
>
> * There is no dyntick handling to do. And calling tick_nohz_idle_enter()
>   messes up with the struct tick_sched reset that was performed on
>   tick_sched_timer_dying().
>
> * There is no nohz idle balancing to do.
>
> * Polling on TIF_RESCHED is irrelevant at this stage, there are no more
>   tasks allowed to run.
>
> * No need to check if need_resched() before offline handling since
>   stop_machine is done and all per-cpu kthread should be done with
>   their job.
>
> Therefore move the offline handling at the beginning of the idle loop.
> This will also ease the idle cputime unification later by not elapsing
> idle time while offline through the call to:
>
>         tick_nohz_idle_enter() -> tick_nohz_start_idle()
>
> Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
> Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
> Tested-by: Shrikanth Hegde <sshegde@linux.ibm.com>

No issues found, so

Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>

> ---
>  kernel/sched/idle.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
> index 3681b6ad9276..521a076d8845 100644
> --- a/kernel/sched/idle.c
> +++ b/kernel/sched/idle.c
> @@ -260,6 +260,14 @@ static void do_idle(void)
>  {
>         int cpu = smp_processor_id();
>
> +       if (cpu_is_offline(cpu)) {
> +               local_irq_disable();
> +               /* All per-CPU kernel threads should be done by now. */
> +               WARN_ON_ONCE(need_resched());
> +               cpuhp_report_idle_dead();
> +               arch_cpu_idle_dead();
> +       }
> +
>         /*
>          * Check if we need to update blocked load
>          */
> @@ -311,11 +319,6 @@ static void do_idle(void)
>                  */
>                 local_irq_disable();
>
> -               if (cpu_is_offline(cpu)) {
> -                       cpuhp_report_idle_dead();
> -                       arch_cpu_idle_dead();
> -               }
> -
>                 arch_cpu_idle_enter();
>                 rcu_nocb_flush_deferred_wakeup();
>
> --
> 2.53.0
>