summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Wadekar <vwadekar@nvidia.com>2011-12-26 16:50:05 +0530
committerVarun Wadekar <vwadekar@nvidia.com>2011-12-26 21:28:19 -0800
commit66fa0f6523f8013b9f60af94bebbcc216f367a67 (patch)
tree350ccddfac1080d8ca9988b2b9b80c3db4672991
parent456363b8d52925d43f9255b2152935cf0d39aabe (diff)
cpu-hotplug: CPUx should be active before it is marked online
CPU0 CPUn _cpu_up() __cpu_up() boostrap() notify_cpu_starting() set_cpu_online() while (!cpu_active()) cpu_relax() <PREEMPT-out> smp_call_function(.wait=1) /* we find cpu_online() is true */ arch_send_call_function_ipi_mask() /* wait-forever-more */ <PREEMPT-in> local_irq_enable() cpu_notify(CPU_ONLINE) sched_cpu_active() set_cpu_active() Now the purpose of cpu_active is mostly with bringing down a cpu, where we mark it !active to avoid the load-balancer from moving tasks to it while we tear down the cpu. This is required because we only update the sched_domain tree after we brought the cpu-down. And this is needed so that some tasks can still run while we bring it down, we just don't want new tasks to appear. On cpu-up however the sched_domain tree doesn't yet include the new cpu, so its invisible to the load-balancer, regardless of the active state. So instead of setting the active state after we boot the new cpu (and consequently having to wait for it before enabling interrupts) set the cpu active before we set it online and avoid the whole mess. Bug 916986 Original Patch: https://lkml.org/lkml/2011/12/15/255 Change-Id: Ia1c07bdc1b3eb07a7cd4d69756fa7bec509c9400 Reported-by: Stepan Moskovchenko <stepanm@codeaurora.org> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Varun Wadekar <vwadekar@nvidia.com> Reviewed-on: http://git-master/r/72130 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Mayuresh Kulkarni <mkulkarni@nvidia.com>
-rw-r--r--arch/arm/kernel/smp.c7
-rw-r--r--arch/s390/kernel/smp.c6
-rw-r--r--arch/x86/kernel/smpboot.c13
-rw-r--r--kernel/sched.c2
4 files changed, 1 insertions, 27 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index a63326923e84..d1fe8b4abbc3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -320,13 +320,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
*/
percpu_timer_setup();
- while (!cpu_active(cpu))
- cpu_relax();
-
- /*
- * cpu_active bit is set, so it's safe to enable interrupts
- * now.
- */
local_irq_enable();
local_fiq_enable();
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 6ab16ac64d29..07f73cde90be 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -467,12 +467,6 @@ int __cpuinit start_secondary(void *cpuvoid)
S390_lowcore.restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
__ctl_set_bit(0, 28); /* Enable lowcore protection */
- /*
- * Wait until the cpu which brought this one up marked it
- * active before enabling interrupts.
- */
- while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask))
- cpu_relax();
local_irq_enable();
/* cpu_idle will call schedule for us */
cpu_idle();
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 9f548cb4a958..39e11500b9b9 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -285,19 +285,6 @@ notrace static void __cpuinit start_secondary(void *unused)
per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
x86_platform.nmi_init();
- /*
- * Wait until the cpu which brought this one up marked it
- * online before enabling interrupts. If we don't do that then
- * we can end up waking up the softirq thread before this cpu
- * reached the active state, which makes the scheduler unhappy
- * and schedule the softirq thread on the wrong cpu. This is
- * only observable with forced threaded interrupts, but in
- * theory it could also happen w/o them. It's just way harder
- * to achieve.
- */
- while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask))
- cpu_relax();
-
/* enable local interrupts */
local_irq_enable();
diff --git a/kernel/sched.c b/kernel/sched.c
index e7ec90424ded..5525f209ebdf 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6511,7 +6511,7 @@ static int __cpuinit sched_cpu_active(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_ONLINE:
+ case CPU_STARTING:
case CPU_DOWN_FAILED:
set_cpu_active((long)hcpu, true);
return NOTIFY_OK;