summaryrefslogtreecommitdiff
path: root/kernel/stop_machine.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-07-03 13:30:27 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-10 00:19:13 (GMT)
commit0beecd3a9e60f7d0aabbd36b40785ac40bd7913f (patch)
treed2e4063977f2ded2c5fe5c9d78e4ab8b0f2cc4a5 /kernel/stop_machine.c
parenta6e1de1a21be70d251a0d2e017b062141c58bc85 (diff)
downloadlinux-fsl-qoriq-0beecd3a9e60f7d0aabbd36b40785ac40bd7913f.tar.xz
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.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index c09f295..51f8088 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -137,6 +137,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,
@@ -155,14 +156,13 @@ 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(cpu, &per_cpu(stop_cpus_work, cpu));
- preempt_enable();
+ mutex_unlock(&stopper_lock);
}
static int __stop_cpus(const struct cpumask *cpumask,
@@ -279,6 +279,16 @@ repeat:
struct cpu_stop_done *done = work->done;
char ksym_buf[KSYM_NAME_LEN] __maybe_unused;
+ /*
+ * 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();