diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-07-03 08:30:27 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@rostedt.homelinux.com> | 2013-08-16 21:59:20 -0400 |
commit | d7b20962b88268829d40159f44bca290ebc99c87 (patch) | |
tree | 2b98db20fd64b9e4470b5862f67269cf1670c534 /kernel/stop_machine.c | |
parent | 80884bd37989c800c2821eae7878ec0406c25564 (diff) | |
download | linux-rt-d7b20962b88268829d40159f44bca290ebc99c87.tar.gz |
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: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/stop_machine.c')
-rw-r--r-- | kernel/stop_machine.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 2f194e965715..61779f820e8e 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -135,6 +135,7 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, /* static data for stop_cpus */ static DEFINE_MUTEX(stop_cpus_mutex); +static DEFINE_MUTEX(stopper_lock); static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work); static void queue_stop_cpus_work(const struct cpumask *cpumask, @@ -153,15 +154,14 @@ static void queue_stop_cpus_work(const struct cpumask *cpumask, } /* - * Disable preemption while queueing to avoid getting - * preempted by a stopper which might wait for other stoppers - * to enter @fn which can lead to deadlock. + * Make sure that all work is queued on all cpus before we + * any of the cpus can execute it. */ - preempt_disable(); + mutex_lock(&stopper_lock); for_each_cpu(cpu, cpumask) cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), &per_cpu(stop_cpus_work, cpu)); - preempt_enable(); + mutex_unlock(&stopper_lock); } static int __stop_cpus(const struct cpumask *cpumask, @@ -275,6 +275,16 @@ repeat: __set_current_state(TASK_RUNNING); + /* + * Wait until the stopper finished scheduling on all + * cpus + */ + mutex_lock(&stopper_lock); + /* + * Let other cpu threads continue as well + */ + mutex_unlock(&stopper_lock); + /* cpu stop callbacks are not allowed to sleep */ preempt_disable(); |