diff options
author | Mike Galbraith <efault@gmx.de> | 2009-10-29 06:48:30 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-03 01:25:00 -0500 |
commit | b84ff7d6f1b7f8a43414e74d972ec4c8f3361db4 (patch) | |
tree | 7e8db08b8dd7d28780f3d08466928c907e5e0440 /kernel | |
parent | 6b9de613ae9c79b637e070136585dde029578065 (diff) |
sched: Fix kthread_bind() by moving the body of kthread_bind() to sched.c
Eric Paris reported that commit
f685ceacab07d3f6c236f04803e2f2f0dbcc5afb causes boot time
PREEMPT_DEBUG complaints.
[ 4.590699] BUG: using smp_processor_id() in preemptible [00000000] code: rmmod/1314
[ 4.593043] caller is task_hot+0x86/0xd0
Since kthread_bind() messes with scheduler internals, move the
body to sched.c, and lock the runqueue.
Reported-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Mike Galbraith <efault@gmx.de>
Tested-by: Eric Paris <eparis@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <1256813310.7574.3.camel@marge.simson.net>
[ v2: fix !SMP build and clean up ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/kthread.c | 23 | ||||
-rw-r--r-- | kernel/sched.c | 32 |
2 files changed, 32 insertions, 23 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c index 5fe709982caa..ab7ae57773e1 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
@@ -150,29 +150,6 @@ struct task_struct *kthread_create(int (*threadfn)(void *data), | |||
150 | EXPORT_SYMBOL(kthread_create); | 150 | EXPORT_SYMBOL(kthread_create); |
151 | 151 | ||
152 | /** | 152 | /** |
153 | * kthread_bind - bind a just-created kthread to a cpu. | ||
154 | * @k: thread created by kthread_create(). | ||
155 | * @cpu: cpu (might not be online, must be possible) for @k to run on. | ||
156 | * | ||
157 | * Description: This function is equivalent to set_cpus_allowed(), | ||
158 | * except that @cpu doesn't need to be online, and the thread must be | ||
159 | * stopped (i.e., just returned from kthread_create()). | ||
160 | */ | ||
161 | void kthread_bind(struct task_struct *k, unsigned int cpu) | ||
162 | { | ||
163 | /* Must have done schedule() in kthread() before we set_task_cpu */ | ||
164 | if (!wait_task_inactive(k, TASK_UNINTERRUPTIBLE)) { | ||
165 | WARN_ON(1); | ||
166 | return; | ||
167 | } | ||
168 | set_task_cpu(k, cpu); | ||
169 | k->cpus_allowed = cpumask_of_cpu(cpu); | ||
170 | k->rt.nr_cpus_allowed = 1; | ||
171 | k->flags |= PF_THREAD_BOUND; | ||
172 | } | ||
173 | EXPORT_SYMBOL(kthread_bind); | ||
174 | |||
175 | /** | ||
176 | * kthread_stop - stop a thread created by kthread_create(). | 153 | * kthread_stop - stop a thread created by kthread_create(). |
177 | * @k: thread created by kthread_create(). | 154 | * @k: thread created by kthread_create(). |
178 | * | 155 | * |
diff --git a/kernel/sched.c b/kernel/sched.c index bf21adb6c9fc..5cb7d637e33a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -1996,6 +1996,38 @@ static inline void check_class_changed(struct rq *rq, struct task_struct *p, | |||
1996 | p->sched_class->prio_changed(rq, p, oldprio, running); | 1996 | p->sched_class->prio_changed(rq, p, oldprio, running); |
1997 | } | 1997 | } |
1998 | 1998 | ||
1999 | /** | ||
2000 | * kthread_bind - bind a just-created kthread to a cpu. | ||
2001 | * @k: thread created by kthread_create(). | ||
2002 | * @cpu: cpu (might not be online, must be possible) for @k to run on. | ||
2003 | * | ||
2004 | * Description: This function is equivalent to set_cpus_allowed(), | ||
2005 | * except that @cpu doesn't need to be online, and the thread must be | ||
2006 | * stopped (i.e., just returned from kthread_create()). | ||
2007 | * | ||
2008 | * Function lives here instead of kthread.c because it messes with | ||
2009 | * scheduler internals which require locking. | ||
2010 | */ | ||
2011 | void kthread_bind(struct task_struct *p, unsigned int cpu) | ||
2012 | { | ||
2013 | struct rq *rq = cpu_rq(cpu); | ||
2014 | unsigned long flags; | ||
2015 | |||
2016 | /* Must have done schedule() in kthread() before we set_task_cpu */ | ||
2017 | if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) { | ||
2018 | WARN_ON(1); | ||
2019 | return; | ||
2020 | } | ||
2021 | |||
2022 | spin_lock_irqsave(&rq->lock, flags); | ||
2023 | set_task_cpu(p, cpu); | ||
2024 | p->cpus_allowed = cpumask_of_cpu(cpu); | ||
2025 | p->rt.nr_cpus_allowed = 1; | ||
2026 | p->flags |= PF_THREAD_BOUND; | ||
2027 | spin_unlock_irqrestore(&rq->lock, flags); | ||
2028 | } | ||
2029 | EXPORT_SYMBOL(kthread_bind); | ||
2030 | |||
1999 | #ifdef CONFIG_SMP | 2031 | #ifdef CONFIG_SMP |
2000 | /* | 2032 | /* |
2001 | * Is this task likely cache-hot: | 2033 | * Is this task likely cache-hot: |