aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/stop_machine.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2015-10-08 10:51:34 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-20 04:23:54 -0400
commit5caa1c089aebcb83ccd5b79a3b88b0aa58288d05 (patch)
treefefeab98c46182094502ae2642fd8a599bb5ec0d /kernel/stop_machine.c
parent233e7f267e580fefdeb36628b7efe8bfe056d27c (diff)
stop_machine: Introduce __cpu_stop_queue_work() and cpu_stop_queue_two_works()
Preparation to simplify the review of the next change. Add two simple helpers, __cpu_stop_queue_work() and cpu_stop_queue_two_works() which simply take a bit of code from their callers. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@redhat.com> Cc: Tejun Heo <tj@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: heiko.carstens@de.ibm.com Link: http://lkml.kernel.org/r/20151008145134.GA18146@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/stop_machine.c')
-rw-r--r--kernel/stop_machine.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 6a402098d4ab..688d6b37bb59 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -73,21 +73,24 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed)
73 } 73 }
74} 74}
75 75
76static void __cpu_stop_queue_work(struct cpu_stopper *stopper,
77 struct cpu_stop_work *work)
78{
79 list_add_tail(&work->list, &stopper->works);
80 wake_up_process(stopper->thread);
81}
82
76/* queue @work to @stopper. if offline, @work is completed immediately */ 83/* queue @work to @stopper. if offline, @work is completed immediately */
77static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work) 84static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work)
78{ 85{
79 struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); 86 struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu);
80
81 unsigned long flags; 87 unsigned long flags;
82 88
83 spin_lock_irqsave(&stopper->lock, flags); 89 spin_lock_irqsave(&stopper->lock, flags);
84 90 if (stopper->enabled)
85 if (stopper->enabled) { 91 __cpu_stop_queue_work(stopper, work);
86 list_add_tail(&work->list, &stopper->works); 92 else
87 wake_up_process(stopper->thread);
88 } else
89 cpu_stop_signal_done(work->done, false); 93 cpu_stop_signal_done(work->done, false);
90
91 spin_unlock_irqrestore(&stopper->lock, flags); 94 spin_unlock_irqrestore(&stopper->lock, flags);
92} 95}
93 96
@@ -213,6 +216,16 @@ static int multi_cpu_stop(void *data)
213 return err; 216 return err;
214} 217}
215 218
219static int cpu_stop_queue_two_works(int cpu1, struct cpu_stop_work *work1,
220 int cpu2, struct cpu_stop_work *work2)
221{
222 lg_double_lock(&stop_cpus_lock, cpu1, cpu2);
223 cpu_stop_queue_work(cpu1, work1);
224 cpu_stop_queue_work(cpu2, work2);
225 lg_double_unlock(&stop_cpus_lock, cpu1, cpu2);
226
227 return 0;
228}
216/** 229/**
217 * stop_two_cpus - stops two cpus 230 * stop_two_cpus - stops two cpus
218 * @cpu1: the cpu to stop 231 * @cpu1: the cpu to stop
@@ -260,10 +273,12 @@ int stop_two_cpus(unsigned int cpu1, unsigned int cpu2, cpu_stop_fn_t fn, void *
260 return -ENOENT; 273 return -ENOENT;
261 } 274 }
262 275
263 lg_double_lock(&stop_cpus_lock, cpu1, cpu2); 276 if (cpu1 > cpu2)
264 cpu_stop_queue_work(cpu1, &work1); 277 swap(cpu1, cpu2);
265 cpu_stop_queue_work(cpu2, &work2); 278 if (cpu_stop_queue_two_works(cpu1, &work1, cpu2, &work2)) {
266 lg_double_unlock(&stop_cpus_lock, cpu1, cpu2); 279 preempt_enable();
280 return -ENOENT;
281 }
267 282
268 preempt_enable(); 283 preempt_enable();
269 284