aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-01-28 17:09:43 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-03-12 18:19:37 -0400
commit528a25b00e1f84eaba6c98e63f58ee0a8e472102 (patch)
tree449e267d06f42020bcaaae7a218710112bedd38e
parentc199068913c9c5cbb5498e289bb387703e087ea8 (diff)
cpu: Make CPU-offline idle-loop transition point more precise
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>
-rw-r--r--kernel/cpu.c4
-rw-r--r--kernel/sched/idle.c7
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)
408 * 408 *
409 * Wait for the stop thread to go away. 409 * Wait for the stop thread to go away.
410 */ 410 */
411 while (!idle_cpu(cpu)) 411 while (!per_cpu(cpu_dead_idle, cpu))
412 cpu_relax(); 412 cpu_relax();
413 smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
414 per_cpu(cpu_dead_idle, cpu) = false;
413 415
414 /* This actually kills the CPU. */ 416 /* This actually kills the CPU. */
415 __cpu_die(cpu); 417 __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:
198 start_critical_timings(); 198 start_critical_timings();
199} 199}
200 200
201DEFINE_PER_CPU(bool, cpu_dead_idle);
202
201/* 203/*
202 * Generic idle loop implementation 204 * Generic idle loop implementation
203 * 205 *
@@ -222,8 +224,11 @@ static void cpu_idle_loop(void)
222 check_pgt_cache(); 224 check_pgt_cache();
223 rmb(); 225 rmb();
224 226
225 if (cpu_is_offline(smp_processor_id())) 227 if (cpu_is_offline(smp_processor_id())) {
228 smp_mb(); /* all activity before dead. */
229 this_cpu_write(cpu_dead_idle, true);
226 arch_cpu_idle_dead(); 230 arch_cpu_idle_dead();
231 }
227 232
228 local_irq_disable(); 233 local_irq_disable();
229 arch_cpu_idle_enter(); 234 arch_cpu_idle_enter();