]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
cpu: Make CPU-offline idle-loop transition point more precise
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Wed, 28 Jan 2015 22:09:43 +0000 (14:09 -0800)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Thu, 12 Mar 2015 22:19:37 +0000 (15:19 -0700)
This commit uses a per-CPU variable to make the CPU-offline code path
through the idle loop more precise, so that the outgoing CPU is
guaranteed to make it into the idle loop before it is powered off.
This commit is in preparation for putting the RCU offline-handling
code on this code path, which will eliminate the magic one-jiffy
wait that RCU uses as the maximum time for an outgoing CPU to get
all the way through the scheduler.

The magic one-jiffy wait for incoming CPUs remains a separate issue.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
kernel/cpu.c
kernel/sched/idle.c

index 1972b161c61e98fbe3e3ce003744cf1d2e8c5b1c..d46b4dae0ca097130f78ffa39a5aada6931e5a95 100644 (file)
@@ -408,8 +408,10 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
         *
         * Wait for the stop thread to go away.
         */
-       while (!idle_cpu(cpu))
+       while (!per_cpu(cpu_dead_idle, cpu))
                cpu_relax();
+       smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
+       per_cpu(cpu_dead_idle, cpu) = false;
 
        /* This actually kills the CPU. */
        __cpu_die(cpu);
index 94b2d7b88a272856bf0f49ac0f0bdce430a5255d..e99e361ade2078b67ac144375025ad9ed7a92cca 100644 (file)
@@ -198,6 +198,8 @@ exit_idle:
        start_critical_timings();
 }
 
+DEFINE_PER_CPU(bool, cpu_dead_idle);
+
 /*
  * Generic idle loop implementation
  *
@@ -222,8 +224,11 @@ static void cpu_idle_loop(void)
                        check_pgt_cache();
                        rmb();
 
-                       if (cpu_is_offline(smp_processor_id()))
+                       if (cpu_is_offline(smp_processor_id())) {
+                               smp_mb(); /* all activity before dead. */
+                               this_cpu_write(cpu_dead_idle, true);
                                arch_cpu_idle_dead();
+                       }
 
                        local_irq_disable();
                        arch_cpu_idle_enter();