path: root/kernel/smpboot.c
diff options
authorThomas Gleixner <>2013-02-26 18:44:33 +0100
committerThomas Gleixner <>2013-02-26 22:25:17 +0100
commit46c498c2cdee5efe44f617bcd4f388179be36115 (patch)
treea1f854a24210acb01caa1f9d345297151ef9c97e /kernel/smpboot.c
parent1a13c0b181f218bf56a1a6b8edbaf2876b22314b (diff)
stop_machine: Mark per cpu stopper enabled early
commit 14e568e78 (stop_machine: Use smpboot threads) introduced the following regression: Before this commit the stopper enabled bit was set in the online notifier. CPU0 CPU1 cpu_up cpu online hotplug_notifier(ONLINE) stopper(CPU1)->enabled = true; ... stop_machine() The conversion to smpboot threads moved the enablement to the wakeup path of the parked thread. The majority of users seem to have the following working order: CPU0 CPU1 cpu_up cpu online unpark_threads() wakeup(stopper[CPU1]) .... stopper thread runs stopper(CPU1)->enabled = true; stop_machine() But Konrad and Sander have observed: CPU0 CPU1 cpu_up cpu online unpark_threads() wakeup(stopper[CPU1]) .... stop_machine() stopper thread runs stopper(CPU1)->enabled = true; Now the stop machinery kicks CPU0 into the stop loop, where it gets stuck forever because the queue code saw stopper(CPU1)->enabled == false, so CPU0 waits for CPU1 to enter stomp_machine, but the CPU1 stopper work got discarded due to enabled == false. Add a pre_unpark function to the smpboot thread descriptor and call it before waking the thread. This fixes the problem at hand, but the stop_machine code should be more robust. The stopper->enabled flag smells fishy at best. Thanks to Konrad for going through a loop of debug patches and providing the information to decode this issue. Reported-and-tested-by: Konrad Rzeszutek Wilk <> Reported-and-tested-by: Sander Eikelenboom <> Cc: Srivatsa S. Bhat <> Cc: Rusty Russell <> Link: Signed-off-by: Thomas Gleixner <>
Diffstat (limited to 'kernel/smpboot.c')
1 files changed, 2 insertions, 0 deletions
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
index d4abac261779..8eaed9aa9cf0 100644
--- a/kernel/smpboot.c
+++ b/kernel/smpboot.c
@@ -209,6 +209,8 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp
struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
+ if (ht->pre_unpark)
+ ht->pre_unpark(cpu);