summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/sched-migrate_enable-Use-stop_one_cpu_nowait.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/sched-migrate_enable-Use-stop_one_cpu_nowait.patch')
-rw-r--r--debian/patches-rt/sched-migrate_enable-Use-stop_one_cpu_nowait.patch112
1 files changed, 112 insertions, 0 deletions
diff --git a/debian/patches-rt/sched-migrate_enable-Use-stop_one_cpu_nowait.patch b/debian/patches-rt/sched-migrate_enable-Use-stop_one_cpu_nowait.patch
new file mode 100644
index 000000000..e75d0e306
--- /dev/null
+++ b/debian/patches-rt/sched-migrate_enable-Use-stop_one_cpu_nowait.patch
@@ -0,0 +1,112 @@
+From: Scott Wood <swood@redhat.com>
+Date: Sat, 12 Oct 2019 01:52:14 -0500
+Subject: [PATCH] sched: migrate_enable: Use stop_one_cpu_nowait()
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patches-5.4.3-rt1.tar.xz
+
+migrate_enable() can be called with current->state != TASK_RUNNING.
+Avoid clobbering the existing state by using stop_one_cpu_nowait().
+Since we're stopping the current cpu, we know that we won't get
+past __schedule() until migration_cpu_stop() has run (at least up to
+the point of migrating us to another cpu).
+
+Signed-off-by: Scott Wood <swood@redhat.com>
+[bigeasy: spin until the request has been processed]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/stop_machine.h | 2 ++
+ kernel/sched/core.c | 27 +++++++++++++++++----------
+ kernel/stop_machine.c | 7 +++++--
+ 3 files changed, 24 insertions(+), 12 deletions(-)
+
+--- a/include/linux/stop_machine.h
++++ b/include/linux/stop_machine.h
+@@ -26,6 +26,8 @@ struct cpu_stop_work {
+ cpu_stop_fn_t fn;
+ void *arg;
+ struct cpu_stop_done *done;
++ /* Did not run due to disabled stopper; for nowait debug checks */
++ bool disabled;
+ };
+
+ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg);
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -1536,6 +1536,7 @@ static struct rq *move_queued_task(struc
+ struct migration_arg {
+ struct task_struct *task;
+ int dest_cpu;
++ bool done;
+ };
+
+ /*
+@@ -1571,6 +1572,11 @@ static int migration_cpu_stop(void *data
+ struct task_struct *p = arg->task;
+ struct rq *rq = this_rq();
+ struct rq_flags rf;
++ int dest_cpu = arg->dest_cpu;
++
++ /* We don't look at arg after this point. */
++ smp_mb();
++ arg->done = true;
+
+ /*
+ * The original target CPU might have gone down and we might
+@@ -1593,9 +1599,9 @@ static int migration_cpu_stop(void *data
+ */
+ if (task_rq(p) == rq) {
+ if (task_on_rq_queued(p))
+- rq = __migrate_task(rq, &rf, p, arg->dest_cpu);
++ rq = __migrate_task(rq, &rf, p, dest_cpu);
+ else
+- p->wake_cpu = arg->dest_cpu;
++ p->wake_cpu = dest_cpu;
+ }
+ rq_unlock(rq, &rf);
+ raw_spin_unlock(&p->pi_lock);
+@@ -8144,7 +8150,8 @@ void migrate_enable(void)
+
+ WARN_ON(smp_processor_id() != cpu);
+ if (!is_cpu_allowed(p, cpu)) {
+- struct migration_arg arg = { p };
++ struct migration_arg arg = { .task = p };
++ struct cpu_stop_work work;
+ struct rq_flags rf;
+
+ rq = task_rq_lock(p, &rf);
+@@ -8152,13 +8159,13 @@ void migrate_enable(void)
+ arg.dest_cpu = select_fallback_rq(cpu, p);
+ task_rq_unlock(rq, p, &rf);
+
+- preempt_enable();
+-
+- sleeping_lock_inc();
+- stop_one_cpu(task_cpu(p), migration_cpu_stop, &arg);
+- sleeping_lock_dec();
+- return;
+-
++ stop_one_cpu_nowait(task_cpu(p), migration_cpu_stop,
++ &arg, &work);
++ __schedule(true);
++ if (!work.disabled) {
++ while (!arg.done)
++ cpu_relax();
++ }
+ }
+
+ out:
+--- a/kernel/stop_machine.c
++++ b/kernel/stop_machine.c
+@@ -86,8 +86,11 @@ static bool cpu_stop_queue_work(unsigned
+ enabled = stopper->enabled;
+ if (enabled)
+ __cpu_stop_queue_work(stopper, work, &wakeq);
+- else if (work->done)
+- cpu_stop_signal_done(work->done);
++ else {
++ work->disabled = true;
++ if (work->done)
++ cpu_stop_signal_done(work->done);
++ }
+ raw_spin_unlock_irqrestore(&stopper->lock, flags);
+
+ wake_up_q(&wakeq);