cpu/hotplug: Make wait for dead cpu completion based
authorThomas Gleixner <tglx@linutronix.de>
Fri, 26 Feb 2016 18:43:43 +0000 (18:43 +0000)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 1 Mar 2016 19:36:58 +0000 (20:36 +0100)
Kill the busy spinning on the control side and just wait for the hotplugged
cpu to tell that it reached the dead state.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Rik van Riel <riel@redhat.com>
Cc: Rafael Wysocki <rafael.j.wysocki@intel.com>
Cc: "Srivatsa S. Bhat" <srivatsa@mit.edu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Sebastian Siewior <bigeasy@linutronix.de>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul Turner <pjt@google.com>
Link: http://lkml.kernel.org/r/20160226182341.776157858@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
include/linux/cpu.h
include/linux/cpuhotplug.h
kernel/cpu.c
kernel/sched/idle.c

index 83f35767016d59c3ff56d91482c0c03380ae5a78..91a48d1b4ca01346e89efcd9737487f34f0c1c7a 100644 (file)
@@ -276,14 +276,15 @@ void arch_cpu_idle_enter(void);
 void arch_cpu_idle_exit(void);
 void arch_cpu_idle_dead(void);
 
-DECLARE_PER_CPU(bool, cpu_dead_idle);
-
 int cpu_report_state(int cpu);
 int cpu_check_up_prepare(int cpu);
 void cpu_set_state_online(int cpu);
 #ifdef CONFIG_HOTPLUG_CPU
 bool cpu_wait_death(unsigned int cpu, int seconds);
 bool cpu_report_death(void);
+void cpuhp_report_idle_dead(void);
+#else
+static inline void cpuhp_report_idle_dead(void) { }
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
 #endif /* _LINUX_CPU_H_ */
index ad5d7fcb013021811c57a87bc8a7b6e798142a34..5d68e15e46b779d4cb0ff4613fd77d28403c72b5 100644 (file)
@@ -6,6 +6,7 @@ enum cpuhp_state {
        CPUHP_CREATE_THREADS,
        CPUHP_NOTIFY_PREPARE,
        CPUHP_BRINGUP_CPU,
+       CPUHP_AP_IDLE_DEAD,
        CPUHP_AP_OFFLINE,
        CPUHP_AP_NOTIFY_STARTING,
        CPUHP_AP_ONLINE,
index f1f880fac83217dfcb6cc7a3b0446ee50f36d89a..0e8c07f2566e8de4bb3814dccc6b1413f4b0b95a 100644 (file)
@@ -688,6 +688,7 @@ static int take_cpu_down(void *_param)
 
 static int takedown_cpu(unsigned int cpu)
 {
+       struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
        int err;
 
        /*
@@ -733,10 +734,8 @@ static int takedown_cpu(unsigned int cpu)
         *
         * Wait for the stop thread to go away.
         */
-       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;
+       wait_for_completion(&st->done);
+       BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
 
        /* Interrupts are moved away from the dying cpu, reenable alloc/free */
        irq_unlock_sparse();
@@ -756,6 +755,15 @@ static int notify_dead(unsigned int cpu)
        return 0;
 }
 
+void cpuhp_report_idle_dead(void)
+{
+       struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+
+       BUG_ON(st->state != CPUHP_AP_OFFLINE);
+       st->state = CPUHP_AP_IDLE_DEAD;
+       complete(&st->done);
+}
+
 #else
 #define notify_down_prepare    NULL
 #define takedown_cpu           NULL
index a4b9813afc964b8cb4872fa5ebd2ababfe13b988..8abbe89e91143c417dd986b81be76be379eb8001 100644 (file)
@@ -194,8 +194,6 @@ exit_idle:
        rcu_idle_exit();
 }
 
-DEFINE_PER_CPU(bool, cpu_dead_idle);
-
 /*
  * Generic idle loop implementation
  *
@@ -224,8 +222,7 @@ static void cpu_idle_loop(void)
                        if (cpu_is_offline(smp_processor_id())) {
                                rcu_cpu_notify(NULL, CPU_DYING_IDLE,
                                               (void *)(long)smp_processor_id());
-                               smp_mb(); /* all activity before dead. */
-                               this_cpu_write(cpu_dead_idle, true);
+                               cpuhp_report_idle_dead();
                                arch_cpu_idle_dead();
                        }