diff options
-rw-r--r-- | kernel/cpu.c | 4 | ||||
-rw-r--r-- | kernel/sched/idle.c | 7 |
2 files changed, 9 insertions, 2 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 1972b161c61e..d46b4dae0ca0 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -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); diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 94b2d7b88a27..e99e361ade20 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -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(); |