mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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.
Change-Id: I636875cf71ea5c5315eb0eb8599a8ebb9eadabf8
Reported-and-tested-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reported-and-tested-by: Sander Eikelenboom <linux@eikelenboom.it>
Cc: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1302261843240.22263@ionos
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
9b73a14959
commit
abd57a700e
3 changed files with 7 additions and 1 deletions
|
@ -24,6 +24,9 @@ struct smpboot_thread_data;
|
||||||
* parked (cpu offline)
|
* parked (cpu offline)
|
||||||
* @unpark: Optional unpark function, called when the thread is
|
* @unpark: Optional unpark function, called when the thread is
|
||||||
* unparked (cpu online)
|
* unparked (cpu online)
|
||||||
|
* @pre_unpark: Optional unpark function, called before the thread is
|
||||||
|
* unparked (cpu online). This is not guaranteed to be
|
||||||
|
* called on the target cpu of the thread. Careful!
|
||||||
* @selfparking: Thread is not parked by the park function.
|
* @selfparking: Thread is not parked by the park function.
|
||||||
* @thread_comm: The base name of the thread
|
* @thread_comm: The base name of the thread
|
||||||
*/
|
*/
|
||||||
|
@ -37,6 +40,7 @@ struct smp_hotplug_thread {
|
||||||
void (*cleanup)(unsigned int cpu, bool online);
|
void (*cleanup)(unsigned int cpu, bool online);
|
||||||
void (*park)(unsigned int cpu);
|
void (*park)(unsigned int cpu);
|
||||||
void (*unpark)(unsigned int cpu);
|
void (*unpark)(unsigned int cpu);
|
||||||
|
void (*pre_unpark)(unsigned int cpu);
|
||||||
bool selfparking;
|
bool selfparking;
|
||||||
const char *thread_comm;
|
const char *thread_comm;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu);
|
||||||
|
|
||||||
|
if (ht->pre_unpark)
|
||||||
|
ht->pre_unpark(cpu);
|
||||||
kthread_unpark(tsk);
|
kthread_unpark(tsk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -336,7 +336,7 @@ static struct smp_hotplug_thread cpu_stop_threads = {
|
||||||
.create = cpu_stop_create,
|
.create = cpu_stop_create,
|
||||||
.setup = cpu_stop_unpark,
|
.setup = cpu_stop_unpark,
|
||||||
.park = cpu_stop_park,
|
.park = cpu_stop_park,
|
||||||
.unpark = cpu_stop_unpark,
|
.pre_unpark = cpu_stop_unpark,
|
||||||
.selfparking = true,
|
.selfparking = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue