summaryrefslogtreecommitdiffstats
path: root/stop_machine-convert-stop_machine_run-to-PREEMPT_RT.patch
blob: 211a025c9a8adafdd868fe4b913a663db2ac347c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
From 19f56bcae5b8955b0882f0f63a2d0f916563fd39 Mon Sep 17 00:00:00 2001
From: Ingo Molnar <mingo@elte.hu>
Date: Fri, 3 Jul 2009 08:30:27 -0500
Subject: [PATCH] stop_machine: convert stop_machine_run() to PREEMPT_RT

commit f9d9cfe4fa444b93238d7c3cf07af2dd85b151e8 in tip.

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>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 kernel/stop_machine.c |   26 +++++++++++++++++++++-----
 1 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 9bb9fb1..72592cc 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -40,6 +40,8 @@ static atomic_t thread_ack;
 static DEFINE_MUTEX(lock);
 /* setup_lock protects refcount, stop_machine_wq and stop_machine_work. */
 static DEFINE_MUTEX(setup_lock);
+/* do not start up until all worklets have been placed: */
+static DEFINE_MUTEX(startup_lock);
 /* Users of stop_machine. */
 static int refcount;
 static struct workqueue_struct *stop_machine_wq;
@@ -71,6 +73,15 @@ static void stop_cpu(struct work_struct *unused)
 	int cpu = smp_processor_id();
 	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 (cpu == cpumask_first(cpu_online_mask))
 			smdata = &active;
@@ -166,16 +177,21 @@ int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
 
 	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. */
-	get_cpu();
+	/*
+	 * Schedule the stop_cpu work on all cpus before allowing any
+	 * of the CPUs to execute it:
+	 */
+	mutex_lock(&startup_lock);
+
 	for_each_online_cpu(i) {
 		sm_work = per_cpu_ptr(stop_machine_work, i);
 		INIT_WORK(sm_work, stop_cpu);
 		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);
 	ret = active.fnret;
 	mutex_unlock(&lock);
-- 
1.7.0.4