]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
sched/idle: Handle offlining first in idle loop
authorFrederic Weisbecker <frederic@kernel.org>
Fri, 8 May 2026 13:16:34 +0000 (15:16 +0200)
committerThomas Gleixner <tglx@kernel.org>
Tue, 2 Jun 2026 19:27:25 +0000 (21:27 +0200)
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>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Link: https://patch.msgid.link/20260508131647.43868-3-frederic@kernel.org
kernel/sched/idle.c

index a83be0c834ddb5ec8a236c525d8a5edd84b3175a..aa7e3dc59856155418e20ed5960e25fcb55a366c 100644 (file)
@@ -280,6 +280,14 @@ static void do_idle(void)
        int cpu = smp_processor_id();
        bool got_tick = false;
 
+       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
         */
@@ -331,11 +339,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();