diff options
author | Con Kolivas <kernel@kolivas.org> | 2016-12-06 10:27:10 +1100 |
---|---|---|
committer | Con Kolivas <kernel@kolivas.org> | 2016-12-06 10:27:10 +1100 |
commit | 121d56cc0818366e4f405f4693b42366566674ae (patch) | |
tree | f5cb074ed58bb83068fae0f6c0b039e905543dcc | |
parent | a66d74eaf3f2c5e57721855f55a34dcb29981781 (diff) |
Fix smpboot threads failing to bring up CPUs on muqss causing boot hangs.
-rw-r--r-- | kernel/kthread.c | 30 | ||||
-rw-r--r-- | kernel/sched/MuQSS.c | 2 |
2 files changed, 30 insertions, 2 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c index be2cc1f9dd57..665e3bd9b731 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -381,6 +381,34 @@ void kthread_bind(struct task_struct *p, unsigned int cpu) } EXPORT_SYMBOL(kthread_bind); +#if defined(CONFIG_SCHED_MUQSS) && defined(CONFIG_SMP) +extern void __do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask); + +/* + * new_kthread_bind is a special variant of __kthread_bind_mask. + * For new threads to work on muqss we want to call do_set_cpus_allowed + * without the task_cpu being set and the task rescheduled until they're + * rescheduled on their own so we call __do_set_cpus_allowed directly which + * only changes the cpumask. This is particularly important for smpboot threads + * to work. + */ +static void new_kthread_bind(struct task_struct *p, unsigned int cpu) +{ + unsigned long flags; + + if (WARN_ON(!wait_task_inactive(p, TASK_UNINTERRUPTIBLE))) + return; + + /* It's safe because the task is inactive. */ + raw_spin_lock_irqsave(&p->pi_lock, flags); + __do_set_cpus_allowed(p, cpumask_of(cpu)); + p->flags |= PF_NO_SETAFFINITY; + raw_spin_unlock_irqrestore(&p->pi_lock, flags); +} +#else +#define new_kthread_bind(p, cpu) kthread_bind(p, cpu) +#endif + /** * kthread_create_on_cpu - Create a cpu bound kthread * @threadfn: the function to run until signal_pending(current). @@ -402,7 +430,7 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), cpu); if (IS_ERR(p)) return p; - kthread_bind(p, cpu); + new_kthread_bind(p, cpu); /* CPU hotplug need to bind once again when unparking the thread. */ set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags); to_kthread(p)->cpu = cpu; diff --git a/kernel/sched/MuQSS.c b/kernel/sched/MuQSS.c index 669167be45f8..18cb55ded3b7 100644 --- a/kernel/sched/MuQSS.c +++ b/kernel/sched/MuQSS.c @@ -5451,7 +5451,7 @@ void set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_ma p->nr_cpus_allowed = cpumask_weight(new_mask); } -static void __do_set_cpus_allowed(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); |