summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/add_migrate_disable.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/add_migrate_disable.patch')
-rw-r--r--debian/patches-rt/add_migrate_disable.patch650
1 files changed, 529 insertions, 121 deletions
diff --git a/debian/patches-rt/add_migrate_disable.patch b/debian/patches-rt/add_migrate_disable.patch
index 6f618be9c..0020fc176 100644
--- a/debian/patches-rt/add_migrate_disable.patch
+++ b/debian/patches-rt/add_migrate_disable.patch
@@ -1,43 +1,67 @@
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat, 27 May 2017 19:02:06 +0200
Subject: kernel/sched/core: add migrate_disable()
-Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.2/older/patches-5.2.17-rt9.tar.xz
+Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.4/older/patches-5.4.3-rt1.tar.xz
+[bristot@redhat.com: rt: Increase/decrease the nr of migratory tasks when enabling/disabling migration
+ Link: https://lkml.kernel.org/r/e981d271cbeca975bca710e2fbcc6078c09741b0.1498482127.git.bristot@redhat.com
+]
+[swood@redhat.com: fixups and optimisations
+ Link:https://lkml.kernel.org/r/20190727055638.20443-1-swood@redhat.com
+ Link:https://lkml.kernel.org/r/20191012065214.28109-1-swood@redhat.com
+]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
- include/linux/preempt.h | 23 ++++++++
- include/linux/sched.h | 7 ++
- include/linux/smp.h | 3 +
- kernel/sched/core.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++-
- kernel/sched/debug.c | 4 +
- 5 files changed, 164 insertions(+), 2 deletions(-)
+ include/linux/preempt.h | 32 +++++++
+ include/linux/sched.h | 35 ++++++++
+ include/linux/smp.h | 3
+ init/init_task.c | 4
+ kernel/cpu.c | 42 ++++++++++
+ kernel/locking/rtmutex.c | 12 ++
+ kernel/locking/rwlock-rt.c | 18 +++-
+ kernel/rcu/tree_plugin.h | 6 +
+ kernel/sched/core.c | 181 ++++++++++++++++++++++++++++++++++++++++++++-
+ kernel/sched/debug.c | 4
+ kernel/sched/sched.h | 4
+ lib/smp_processor_id.c | 5 +
+ 12 files changed, 336 insertions(+), 10 deletions(-)
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
-@@ -191,6 +191,22 @@ do { \
+@@ -201,6 +201,31 @@ do { \
#define preemptible() (preempt_count() == 0 && !irqs_disabled())
-+#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+
+extern void migrate_disable(void);
+extern void migrate_enable(void);
+
+int __migrate_disabled(struct task_struct *p);
+
++#elif !defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
++
++extern void migrate_disable(void);
++extern void migrate_enable(void);
++static inline int __migrate_disabled(struct task_struct *p)
++{
++ return 0;
++}
++
+#else
-+#define migrate_disable() barrier()
-+#define migrate_enable() barrier()
++#define migrate_disable() preempt_disable()
++#define migrate_enable() preempt_enable()
+static inline int __migrate_disabled(struct task_struct *p)
+{
+ return 0;
+}
+#endif
+
- #ifdef CONFIG_PREEMPT
+ #ifdef CONFIG_PREEMPTION
#define preempt_enable() \
do { \
-@@ -259,6 +275,13 @@ do { \
- #define preempt_enable_notrace() barrier()
+@@ -270,6 +295,13 @@ do { \
+ #define preempt_check_resched_rt() barrier()
#define preemptible() 0
+#define migrate_disable() barrier()
@@ -52,140 +76,455 @@ Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.2/older/patches-5.
#ifdef MODULE
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
-@@ -653,6 +653,13 @@ struct task_struct {
+@@ -233,6 +233,8 @@ extern void io_schedule_finish(int token
+ extern long io_schedule_timeout(long timeout);
+ extern void io_schedule(void);
+
++int cpu_nr_pinned(int cpu);
++
+ /**
+ * struct prev_cputime - snapshot of system and user cputime
+ * @utime: time spent in user mode
+@@ -705,6 +707,20 @@ struct task_struct {
int nr_cpus_allowed;
const cpumask_t *cpus_ptr;
cpumask_t cpus_mask;
-+#if defined(CONFIG_PREEMPT_COUNT) && defined(CONFIG_SMP)
++#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+ int migrate_disable;
-+ int migrate_disable_update;
++ bool migrate_disable_scheduled;
+# ifdef CONFIG_SCHED_DEBUG
-+ int migrate_disable_atomic;
++ int pinned_on_cpu;
++# endif
++#elif !defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
++# ifdef CONFIG_SCHED_DEBUG
++ int migrate_disable;
+# endif
+#endif
++#ifdef CONFIG_PREEMPT_RT
++ int sleeping_lock;
++#endif
#ifdef CONFIG_PREEMPT_RCU
int rcu_read_lock_nesting;
+@@ -1865,6 +1881,23 @@ static __always_inline bool need_resched
+ return unlikely(tif_need_resched());
+ }
+
++#ifdef CONFIG_PREEMPT_RT
++static inline void sleeping_lock_inc(void)
++{
++ current->sleeping_lock++;
++}
++
++static inline void sleeping_lock_dec(void)
++{
++ current->sleeping_lock--;
++}
++
++#else
++
++static inline void sleeping_lock_inc(void) { }
++static inline void sleeping_lock_dec(void) { }
++#endif
++
+ /*
+ * Wrappers for p->thread_info->cpu access. No-op on UP.
+ */
+@@ -2056,4 +2089,6 @@ int sched_trace_rq_cpu(struct rq *rq);
+
+ const struct cpumask *sched_trace_rd_span(struct root_domain *rd);
+
++extern struct task_struct *takedown_cpu_task;
++
+ #endif
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
-@@ -206,6 +206,9 @@ static inline int get_boot_cpu_id(void)
- #define get_cpu() ({ preempt_disable(); smp_processor_id(); })
+@@ -222,6 +222,9 @@ static inline int get_boot_cpu_id(void)
+ #define get_cpu() ({ preempt_disable(); __smp_processor_id(); })
#define put_cpu() preempt_enable()
-+#define get_cpu_light() ({ migrate_disable(); smp_processor_id(); })
++#define get_cpu_light() ({ migrate_disable(); __smp_processor_id(); })
+#define put_cpu_light() migrate_enable()
+
/*
* Callback to arch code if there's nosmp or maxcpus=0 on the
* boot command line:
+--- a/init/init_task.c
++++ b/init/init_task.c
+@@ -73,6 +73,10 @@ struct task_struct init_task
+ .cpus_ptr = &init_task.cpus_mask,
+ .cpus_mask = CPU_MASK_ALL,
+ .nr_cpus_allowed= NR_CPUS,
++#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT) && \
++ defined(CONFIG_SCHED_DEBUG)
++ .pinned_on_cpu = -1,
++#endif
+ .mm = NULL,
+ .active_mm = &init_mm,
+ .restart_block = {
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -849,6 +849,15 @@ static int take_cpu_down(void *_param)
+ int err, cpu = smp_processor_id();
+ int ret;
+
++#ifdef CONFIG_PREEMPT_RT
++ /*
++ * If any tasks disabled migration before we got here,
++ * go back and sleep again.
++ */
++ if (cpu_nr_pinned(cpu))
++ return -EAGAIN;
++#endif
++
+ /* Ensure this CPU doesn't handle any more interrupts. */
+ err = __cpu_disable();
+ if (err < 0)
+@@ -878,6 +887,8 @@ static int take_cpu_down(void *_param)
+ return 0;
+ }
+
++struct task_struct *takedown_cpu_task;
++
+ static int takedown_cpu(unsigned int cpu)
+ {
+ struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+@@ -892,11 +903,39 @@ static int takedown_cpu(unsigned int cpu
+ */
+ irq_lock_sparse();
+
++#ifdef CONFIG_PREEMPT_RT
++ WARN_ON_ONCE(takedown_cpu_task);
++ takedown_cpu_task = current;
++
++again:
++ /*
++ * If a task pins this CPU after we pass this check, take_cpu_down
++ * will return -EAGAIN.
++ */
++ for (;;) {
++ int nr_pinned;
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ nr_pinned = cpu_nr_pinned(cpu);
++ if (nr_pinned == 0)
++ break;
++ schedule();
++ }
++ set_current_state(TASK_RUNNING);
++#endif
++
+ /*
+ * So now all preempt/rcu users must observe !cpu_active().
+ */
+ err = stop_machine_cpuslocked(take_cpu_down, NULL, cpumask_of(cpu));
++#ifdef CONFIG_PREEMPT_RT
++ if (err == -EAGAIN)
++ goto again;
++#endif
+ if (err) {
++#ifdef CONFIG_PREEMPT_RT
++ takedown_cpu_task = NULL;
++#endif
+ /* CPU refused to die */
+ irq_unlock_sparse();
+ /* Unpark the hotplug thread so we can rollback there */
+@@ -915,6 +954,9 @@ static int takedown_cpu(unsigned int cpu
+ wait_for_ap_thread(st, false);
+ BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);
+
++#ifdef CONFIG_PREEMPT_RT
++ takedown_cpu_task = NULL;
++#endif
+ /* Interrupts are moved away from the dying cpu, reenable alloc/free */
+ irq_unlock_sparse();
+
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -1140,6 +1140,7 @@ void __sched rt_spin_lock_slowunlock(str
+
+ void __lockfunc rt_spin_lock(spinlock_t *lock)
+ {
++ sleeping_lock_inc();
+ migrate_disable();
+ spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
+ rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock);
+@@ -1154,6 +1155,7 @@ void __lockfunc __rt_spin_lock(struct rt
+ #ifdef CONFIG_DEBUG_LOCK_ALLOC
+ void __lockfunc rt_spin_lock_nested(spinlock_t *lock, int subclass)
+ {
++ sleeping_lock_inc();
+ migrate_disable();
+ spin_acquire(&lock->dep_map, subclass, 0, _RET_IP_);
+ rt_spin_lock_fastlock(&lock->lock, rt_spin_lock_slowlock);
+@@ -1167,6 +1169,7 @@ void __lockfunc rt_spin_unlock(spinlock_
+ spin_release(&lock->dep_map, 1, _RET_IP_);
+ rt_spin_lock_fastunlock(&lock->lock, rt_spin_lock_slowunlock);
+ migrate_enable();
++ sleeping_lock_dec();
+ }
+ EXPORT_SYMBOL(rt_spin_unlock);
+
+@@ -1192,12 +1195,15 @@ int __lockfunc rt_spin_trylock(spinlock_
+ {
+ int ret;
+
++ sleeping_lock_inc();
+ migrate_disable();
+ ret = __rt_mutex_trylock(&lock->lock);
+- if (ret)
++ if (ret) {
+ spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
+- else
++ } else {
+ migrate_enable();
++ sleeping_lock_dec();
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL(rt_spin_trylock);
+@@ -1209,6 +1215,7 @@ int __lockfunc rt_spin_trylock_bh(spinlo
+ local_bh_disable();
+ ret = __rt_mutex_trylock(&lock->lock);
+ if (ret) {
++ sleeping_lock_inc();
+ migrate_disable();
+ spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
+ } else
+@@ -1224,6 +1231,7 @@ int __lockfunc rt_spin_trylock_irqsave(s
+ *flags = 0;
+ ret = __rt_mutex_trylock(&lock->lock);
+ if (ret) {
++ sleeping_lock_inc();
+ migrate_disable();
+ spin_acquire(&lock->dep_map, 0, 1, _RET_IP_);
+ }
+--- a/kernel/locking/rwlock-rt.c
++++ b/kernel/locking/rwlock-rt.c
+@@ -305,12 +305,15 @@ int __lockfunc rt_read_trylock(rwlock_t
+ {
+ int ret;
+
++ sleeping_lock_inc();
+ migrate_disable();
+ ret = do_read_rt_trylock(rwlock);
+- if (ret)
++ if (ret) {
+ rwlock_acquire_read(&rwlock->dep_map, 0, 1, _RET_IP_);
+- else
++ } else {
+ migrate_enable();
++ sleeping_lock_dec();
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL(rt_read_trylock);
+@@ -319,18 +322,22 @@ int __lockfunc rt_write_trylock(rwlock_t
+ {
+ int ret;
+
++ sleeping_lock_inc();
+ migrate_disable();
+ ret = do_write_rt_trylock(rwlock);
+- if (ret)
++ if (ret) {
+ rwlock_acquire(&rwlock->dep_map, 0, 1, _RET_IP_);
+- else
++ } else {
+ migrate_enable();
++ sleeping_lock_dec();
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL(rt_write_trylock);
+
+ void __lockfunc rt_read_lock(rwlock_t *rwlock)
+ {
++ sleeping_lock_inc();
+ migrate_disable();
+ rwlock_acquire_read(&rwlock->dep_map, 0, 0, _RET_IP_);
+ do_read_rt_lock(rwlock);
+@@ -339,6 +346,7 @@ EXPORT_SYMBOL(rt_read_lock);
+
+ void __lockfunc rt_write_lock(rwlock_t *rwlock)
+ {
++ sleeping_lock_inc();
+ migrate_disable();
+ rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_);
+ do_write_rt_lock(rwlock);
+@@ -350,6 +358,7 @@ void __lockfunc rt_read_unlock(rwlock_t
+ rwlock_release(&rwlock->dep_map, 1, _RET_IP_);
+ do_read_rt_unlock(rwlock);
+ migrate_enable();
++ sleeping_lock_dec();
+ }
+ EXPORT_SYMBOL(rt_read_unlock);
+
+@@ -358,6 +367,7 @@ void __lockfunc rt_write_unlock(rwlock_t
+ rwlock_release(&rwlock->dep_map, 1, _RET_IP_);
+ do_write_rt_unlock(rwlock);
+ migrate_enable();
++ sleeping_lock_dec();
+ }
+ EXPORT_SYMBOL(rt_write_unlock);
+
+--- a/kernel/rcu/tree_plugin.h
++++ b/kernel/rcu/tree_plugin.h
+@@ -287,10 +287,14 @@ void rcu_note_context_switch(bool preemp
+ struct task_struct *t = current;
+ struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
+ struct rcu_node *rnp;
++ int sleeping_l = 0;
+
+ trace_rcu_utilization(TPS("Start context switch"));
+ lockdep_assert_irqs_disabled();
+- WARN_ON_ONCE(!preempt && t->rcu_read_lock_nesting > 0);
++#if defined(CONFIG_PREEMPT_RT)
++ sleeping_l = t->sleeping_lock;
++#endif
++ WARN_ON_ONCE(!preempt && t->rcu_read_lock_nesting > 0 && !sleeping_l);
+ if (t->rcu_read_lock_nesting > 0 &&
+ !t->rcu_read_unlock_special.b.blocked) {
+
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
-@@ -1060,7 +1060,15 @@ void set_cpus_allowed_common(struct task
- p->nr_cpus_allowed = cpumask_weight(new_mask);
+@@ -1487,7 +1487,7 @@ static inline bool is_cpu_allowed(struct
+ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
+ return false;
+
+- if (is_per_cpu_kthread(p))
++ if (is_per_cpu_kthread(p) || __migrate_disabled(p))
+ return cpu_online(cpu);
+
+ return cpu_active(cpu);
+@@ -1611,9 +1611,18 @@ static int migration_cpu_stop(void *data
+ void set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask)
+ {
+ cpumask_copy(&p->cpus_mask, new_mask);
+- p->nr_cpus_allowed = cpumask_weight(new_mask);
++ if (p->cpus_ptr == &p->cpus_mask)
++ p->nr_cpus_allowed = cpumask_weight(new_mask);
}
--void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
-+#if defined(CONFIG_PREEMPT_COUNT) && defined(CONFIG_SMP)
++#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+int __migrate_disabled(struct task_struct *p)
+{
+ return p->migrate_disable;
+}
++EXPORT_SYMBOL_GPL(__migrate_disabled);
+#endif
+
-+static void __do_set_cpus_allowed_tail(struct task_struct *p,
-+ const struct cpumask *new_mask)
+ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
{
struct rq *rq = task_rq(p);
- bool queued, running;
-@@ -1089,6 +1097,20 @@ void do_set_cpus_allowed(struct task_str
- set_curr_task(rq, p);
- }
-
-+void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+#if defined(CONFIG_PREEMPT_COUNT) && defined(CONFIG_SMP)
-+ if (__migrate_disabled(p)) {
-+ lockdep_assert_held(&p->pi_lock);
-+
-+ cpumask_copy(&p->cpus_mask, new_mask);
-+ p->migrate_disable_update = 1;
-+ return;
-+ }
-+#endif
-+ __do_set_cpus_allowed_tail(p, new_mask);
-+}
-+
- /*
- * Change a given task's CPU affinity. Migrate the thread to a
- * proper CPU and schedule it away if the CPU it's executing on
-@@ -1147,9 +1169,16 @@ static int __set_cpus_allowed_ptr(struct
+@@ -1702,7 +1711,8 @@ static int __set_cpus_allowed_ptr(struct
}
/* Can the task run on the task's current CPU? If so, we're done */
- if (cpumask_test_cpu(task_cpu(p), new_mask))
-+ if (cpumask_test_cpu(task_cpu(p), new_mask) || __migrate_disabled(p))
++ if (cpumask_test_cpu(task_cpu(p), new_mask) ||
++ p->cpus_ptr != &p->cpus_mask)
goto out;
-+#if defined(CONFIG_PREEMPT_COUNT) && defined(CONFIG_SMP)
-+ if (__migrate_disabled(p)) {
-+ p->migrate_disable_update = 1;
-+ goto out;
-+ }
-+#endif
-+
- dest_cpu = cpumask_any_and(cpu_valid_mask, new_mask);
if (task_running(rq, p) || p->state == TASK_WAKING) {
- struct migration_arg arg = { p, dest_cpu };
-@@ -7086,3 +7115,99 @@ const u32 sched_prio_to_wmult[40] = {
+@@ -4027,6 +4037,8 @@ pick_next_task(struct rq *rq, struct tas
+ BUG();
+ }
+
++static void migrate_disabled_sched(struct task_struct *p);
++
+ /*
+ * __schedule() is the main scheduler function.
+ *
+@@ -4097,6 +4109,9 @@ static void __sched notrace __schedule(b
+ rq_lock(rq, &rf);
+ smp_mb__after_spinlock();
+
++ if (__migrate_disabled(prev))
++ migrate_disabled_sched(prev);
++
+ /* Promote REQ to ACT */
+ rq->clock_update_flags <<= 1;
+ update_rq_clock(rq);
+@@ -6339,6 +6354,7 @@ static void migrate_tasks(struct rq *dea
+ break;
+
+ next = __pick_migrate_task(rq);
++ WARN_ON_ONCE(__migrate_disabled(next));
+
+ /*
+ * Rules for changing task_struct::cpus_mask are holding
+@@ -8028,3 +8044,162 @@ const u32 sched_prio_to_wmult[40] = {
};
#undef CREATE_TRACE_POINTS
+
-+#if defined(CONFIG_PREEMPT_COUNT) && defined(CONFIG_SMP)
++#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+
-+void migrate_disable(void)
++static inline void
++update_nr_migratory(struct task_struct *p, long delta)
+{
-+ struct task_struct *p = current;
-+
-+ if (in_atomic() || irqs_disabled()) {
-+#ifdef CONFIG_SCHED_DEBUG
-+ p->migrate_disable_atomic++;
-+#endif
-+ return;
++ if (unlikely((p->sched_class == &rt_sched_class ||
++ p->sched_class == &dl_sched_class) &&
++ p->nr_cpus_allowed > 1)) {
++ if (p->sched_class == &rt_sched_class)
++ task_rq(p)->rt.rt_nr_migratory += delta;
++ else
++ task_rq(p)->dl.dl_nr_migratory += delta;
+ }
-+#ifdef CONFIG_SCHED_DEBUG
-+ WARN_ON_ONCE(p->migrate_disable_atomic);
-+#endif
-+
-+ if (p->migrate_disable) {
-+ p->migrate_disable++;
-+ return;
-+ }
-+
-+ preempt_disable();
-+ p->migrate_disable = 1;
++}
+
++static inline void
++migrate_disable_update_cpus_allowed(struct task_struct *p)
++{
+ p->cpus_ptr = cpumask_of(smp_processor_id());
++ update_nr_migratory(p, -1);
+ p->nr_cpus_allowed = 1;
++}
+
-+ preempt_enable();
++static inline void
++migrate_enable_update_cpus_allowed(struct task_struct *p)
++{
++ struct rq *rq;
++ struct rq_flags rf;
++
++ rq = task_rq_lock(p, &rf);
++ p->cpus_ptr = &p->cpus_mask;
++ p->nr_cpus_allowed = cpumask_weight(&p->cpus_mask);
++ update_nr_migratory(p, 1);
++ task_rq_unlock(rq, p, &rf);
+}
-+EXPORT_SYMBOL(migrate_disable);
+
-+void migrate_enable(void)
++void migrate_disable(void)
+{
-+ struct task_struct *p = current;
++ preempt_disable();
+
-+ if (in_atomic() || irqs_disabled()) {
++ if (++current->migrate_disable == 1) {
++ this_rq()->nr_pinned++;
+#ifdef CONFIG_SCHED_DEBUG
-+ p->migrate_disable_atomic--;
++ WARN_ON_ONCE(current->pinned_on_cpu >= 0);
++ current->pinned_on_cpu = smp_processor_id();
+#endif
-+ return;
+ }
+
-+#ifdef CONFIG_SCHED_DEBUG
-+ WARN_ON_ONCE(p->migrate_disable_atomic);
-+#endif
++ preempt_enable();
++}
++EXPORT_SYMBOL(migrate_disable);
++
++static void migrate_disabled_sched(struct task_struct *p)
++{
++ if (p->migrate_disable_scheduled)
++ return;
++
++ migrate_disable_update_cpus_allowed(p);
++ p->migrate_disable_scheduled = 1;
++}
++
++void migrate_enable(void)
++{
++ struct task_struct *p = current;
++ struct rq *rq = this_rq();
++ int cpu = task_cpu(p);
+
+ WARN_ON_ONCE(p->migrate_disable <= 0);
+ if (p->migrate_disable > 1) {
@@ -195,57 +534,126 @@ Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.2/older/patches-5.
+
+ preempt_disable();
+
-+ p->cpus_ptr = &p->cpus_mask;
-+ p->nr_cpus_allowed = cpumask_weight(&p->cpus_mask);
++#ifdef CONFIG_SCHED_DEBUG
++ WARN_ON_ONCE(current->pinned_on_cpu != cpu);
++ current->pinned_on_cpu = -1;
++#endif
++
++ WARN_ON_ONCE(rq->nr_pinned < 1);
++
+ p->migrate_disable = 0;
++ rq->nr_pinned--;
++ if (rq->nr_pinned == 0 && unlikely(!cpu_active(cpu)) &&
++ takedown_cpu_task)
++ wake_up_process(takedown_cpu_task);
++
++ if (!p->migrate_disable_scheduled)
++ goto out;
+
-+ if (p->migrate_disable_update) {
-+ struct rq *rq;
++ p->migrate_disable_scheduled = 0;
++
++ migrate_enable_update_cpus_allowed(p);
++
++ WARN_ON(smp_processor_id() != cpu);
++ if (!is_cpu_allowed(p, cpu)) {
++ struct migration_arg arg = { p };
+ struct rq_flags rf;
+
+ rq = task_rq_lock(p, &rf);
+ update_rq_clock(rq);
-+
-+ __do_set_cpus_allowed_tail(p, &p->cpus_mask);
++ arg.dest_cpu = select_fallback_rq(cpu, p);
+ task_rq_unlock(rq, p, &rf);
+
-+ p->migrate_disable_update = 0;
-+
-+ WARN_ON(smp_processor_id() != task_cpu(p));
-+ if (!cpumask_test_cpu(task_cpu(p), &p->cpus_mask)) {
-+ const struct cpumask *cpu_valid_mask = cpu_active_mask;
-+ struct migration_arg arg;
-+ unsigned int dest_cpu;
-+
-+ if (p->flags & PF_KTHREAD) {
-+ /*
-+ * Kernel threads are allowed on online && !active CPUs
-+ */
-+ cpu_valid_mask = cpu_online_mask;
-+ }
-+ dest_cpu = cpumask_any_and(cpu_valid_mask, &p->cpus_mask);
-+ arg.task = p;
-+ arg.dest_cpu = dest_cpu;
-+
-+ preempt_enable();
-+ stop_one_cpu(task_cpu(p), migration_cpu_stop, &arg);
-+ return;
-+ }
++ preempt_enable();
++
++ sleeping_lock_inc();
++ stop_one_cpu(task_cpu(p), migration_cpu_stop, &arg);
++ sleeping_lock_dec();
++ return;
++
+ }
++
++out:
+ preempt_enable();
+}
+EXPORT_SYMBOL(migrate_enable);
++
++int cpu_nr_pinned(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ return rq->nr_pinned;
++}
++
++#elif !defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
++static void migrate_disabled_sched(struct task_struct *p)
++{
++}
++
++void migrate_disable(void)
++{
++#ifdef CONFIG_SCHED_DEBUG
++ current->migrate_disable++;
++#endif
++ barrier();
++}
++EXPORT_SYMBOL(migrate_disable);
++
++void migrate_enable(void)
++{
++#ifdef CONFIG_SCHED_DEBUG
++ struct task_struct *p = current;
++
++ WARN_ON_ONCE(p->migrate_disable <= 0);
++ p->migrate_disable--;
++#endif
++ barrier();
++}
++EXPORT_SYMBOL(migrate_enable);
++
++#else
++static void migrate_disabled_sched(struct task_struct *p)
++{
++}
++
+#endif
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
-@@ -979,6 +979,10 @@ void proc_sched_show_task(struct task_st
+@@ -958,6 +958,10 @@ void proc_sched_show_task(struct task_st
P(dl.runtime);
P(dl.deadline);
}
-+#if defined(CONFIG_PREEMPT_COUNT) && defined(CONFIG_SMP)
++#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT_RT)
+ P(migrate_disable);
+#endif
+ P(nr_cpus_allowed);
#undef PN_SCHEDSTAT
#undef PN
#undef __PN
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -999,6 +999,10 @@ struct rq {
+ /* Must be inspected within a rcu lock section */
+ struct cpuidle_state *idle_state;
+ #endif
++
++#if defined(CONFIG_PREEMPT_RT) && defined(CONFIG_SMP)
++ int nr_pinned;
++#endif
+ };
+
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+--- a/lib/smp_processor_id.c
++++ b/lib/smp_processor_id.c
+@@ -23,6 +23,11 @@ unsigned int check_preemption_disabled(c
+ * Kernel threads bound to a single CPU can safely use
+ * smp_processor_id():
+ */
++#if defined(CONFIG_PREEMPT_RT) && (defined(CONFIG_SMP) || defined(CONFIG_SCHED_DEBUG))
++ if (current->migrate_disable)
++ goto out;
++#endif
++
+ if (current->nr_cpus_allowed == 1)
+ goto out;
+