Commit f9d9cfe4 authored by Ingo Molnar's avatar Ingo Molnar Committed by Thomas Gleixner

stop_machine: convert stop_machine_run() to PREEMPT_RT

Instead of playing with non-preemption, introduce explicit
startup serialization. This is more robust and cleaner as
well.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 0dc6c39e
...@@ -40,6 +40,8 @@ static atomic_t thread_ack; ...@@ -40,6 +40,8 @@ static atomic_t thread_ack;
static DEFINE_MUTEX(lock); static DEFINE_MUTEX(lock);
/* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */ /* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */
static DEFINE_MUTEX(setup_lock); static DEFINE_MUTEX(setup_lock);
/* do not start up until all worklets have been placed: */
static DEFINE_MUTEX(startup_lock);
/* Users of stop_machine. */ /* Users of stop_machine. */
static int refcount; static int refcount;
static struct workqueue_struct *stop_machine_wq; static struct workqueue_struct *stop_machine_wq;
...@@ -71,6 +73,15 @@ static void stop_cpu(struct work_struct *unused) ...@@ -71,6 +73,15 @@ static void stop_cpu(struct work_struct *unused)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
int err; int err;
/*
* Wait for the startup loop to finish:
*/
mutex_lock(&startup_lock);
/*
* Let other threads continue too:
*/
mutex_unlock(&startup_lock);
if (!active_cpus) { if (!active_cpus) {
if (cpu == cpumask_first(cpu_online_mask)) if (cpu == cpumask_first(cpu_online_mask))
smdata = &active; smdata = &active;
...@@ -166,16 +177,21 @@ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus) ...@@ -166,16 +177,21 @@ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
set_state(STOPMACHINE_PREPARE); set_state(STOPMACHINE_PREPARE);
/* Schedule the stop_cpu work on all cpus: hold this CPU so one /*
* doesn't hit this CPU until we're ready. */ * Schedule the stop_cpu work on all cpus before allowing any
get_cpu(); * of the CPUs to execute it:
*/
mutex_lock(&startup_lock);
for_each_online_cpu(i) { for_each_online_cpu(i) {
sm_work = per_cpu_ptr(stop_machine_work, i); sm_work = per_cpu_ptr(stop_machine_work, i);
INIT_WORK(sm_work, stop_cpu); INIT_WORK(sm_work, stop_cpu);
queue_work_on(i, stop_machine_wq, sm_work); queue_work_on(i, stop_machine_wq, sm_work);
} }
/* This will release the thread on our CPU. */
put_cpu(); /* This will release the thread on all CPUs: */
mutex_unlock(&startup_lock);
flush_workqueue(stop_machine_wq); flush_workqueue(stop_machine_wq);
ret = active.fnret; ret = active.fnret;
mutex_unlock(&lock); mutex_unlock(&lock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment