Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1202737 > unrolled thread
| Started by | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| First post | 2015-08-07 16:30 +0200 |
| Last post | 2015-08-07 17:40 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() Peter Zijlstra <peterz@infradead.org> - 2015-08-07 16:30 +0200
Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() Tejun Heo <tj@kernel.org> - 2015-08-07 17:20 +0200
Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() Tejun Heo <tj@kernel.org> - 2015-08-07 17:40 +0200
Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() Peter Zijlstra <peterz@infradead.org> - 2015-08-07 18:10 +0200
Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() Tejun Heo <tj@kernel.org> - 2015-08-07 18:20 +0200
Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() Peter Zijlstra <peterz@infradead.org> - 2015-08-07 17:40 +0200
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2015-08-07 16:30 +0200 |
| Subject | Re: [RFC][PATCH 1/4] sched: Fix a race between __kthread_bind() and sched_setaffinity() |
| Message-ID | <pUQOJ-24b-9@gated-at.bofh.it> |
On Fri, May 15, 2015 at 11:56:53AM -0400, Tejun Heo wrote:
> On Fri, May 15, 2015 at 05:43:34PM +0200, Peter Zijlstra wrote:
> > Because sched_setscheduler() checks p->flags & PF_NO_SETAFFINITY
> > without locks, a caller might observe an old value and race with the
> > set_cpus_allowed_ptr() call from __kthread_bind() and effectively undo
> > it.
> >
> > __kthread_bind()
> > do_set_cpus_allowed()
> > <SYSCALL>
> > sched_setaffinity()
> > if (p->flags & PF_NO_SETAFFINITIY)
> > set_cpus_allowed_ptr()
> > p->flags |= PF_NO_SETAFFINITY
> >
> > Fix the issue by putting everything under the regular scheduler locks.
> >
> > This also closes a hole in the serialization of
> > task_struct::{nr_,}cpus_allowed.
> >
> > Cc: Tejun Heo <tj@kernel.org>
> > Cc: Oleg Nesterov <oleg@redhat.com>
> > Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
>
> For workqueue part,
>
> Acked-by: Tejun Heo <tj@kernel.org>
Sorry be being very late on this, got sidetracked with other bits.
This threw up a warning on testing:
[ 2.443944] WARNING: CPU: 0 PID: 10 at kernel/kthread.c:333 __kthread_bind_mask+0x34/0x6e()
[ 2.446978] Modules linked in:
[ 2.448359] CPU: 0 PID: 10 Comm: khelper Not tainted 4.1.0-rc6-00314-g6455666 #4
[ 2.450990] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014
[ 2.454132] 0000000000000009 ffff88000f643d68 ffffffff81a3df14 0000000000000b02
[ 2.470295] 0000000000000000 ffff88000f643da8 ffffffff810f308f 000000000f643da8
[ 2.503291] ffffffff8110d116 ffff88000f55d580 ffff88000f5240c0 ffff88000f4936e0
[ 2.506510] Call Trace:
[ 2.520770] [<ffffffff81a3df14>] dump_stack+0x4c/0x65
[ 2.522479] [<ffffffff810f308f>] warn_slowpath_common+0xa1/0xbb
[ 2.524334] [<ffffffff8110d116>] ? __kthread_bind_mask+0x34/0x6e
[ 2.526219] [<ffffffff810f314c>] warn_slowpath_null+0x1a/0x1c
[ 2.528069] [<ffffffff8110d116>] __kthread_bind_mask+0x34/0x6e
[ 2.529925] [<ffffffff8110d381>] kthread_bind_mask+0x13/0x15
[ 2.531738] [<ffffffff8110679d>] worker_attach_to_pool+0x39/0x7c
[ 2.546650] [<ffffffff8110866b>] rescuer_thread+0x130/0x318
[ 2.548484] [<ffffffff8110853b>] ? cancel_delayed_work_sync+0x15/0x15
[ 2.550411] [<ffffffff8110853b>] ? cancel_delayed_work_sync+0x15/0x15
[ 2.552207] [<ffffffff8110cd0f>] kthread+0xf8/0x100
[ 2.553864] [<ffffffff8110cc17>] ? kthread_create_on_node+0x184/0x184
[ 2.555795] [<ffffffff81a457c2>] ret_from_fork+0x42/0x70
[ 2.557538] [<ffffffff8110cc17>] ? kthread_create_on_node+0x184/0x184
[ 2.572520] ---[ end trace 362b92c9255ab666 ]---
Which is the rescue thread attaching itself to a pool that needs help,
and obviously the rescue thread isn't new so kthread_bind doesn't work
right.
The best I could come up with is something like the below on top; does
that work for you? I'll go give it some runtime.
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1622,11 +1622,15 @@ static struct worker *alloc_worker(int n
* cpu-[un]hotplugs.
*/
static void worker_attach_to_pool(struct worker *worker,
- struct worker_pool *pool)
+ struct worker_pool *pool,
+ bool new)
{
mutex_lock(&pool->attach_mutex);
- kthread_bind_mask(worker->task, pool->attrs->cpumask);
+ if (new)
+ kthread_bind_mask(worker->task, pool->attrs->cpumask);
+ else
+ set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
/*
* The pool->attach_mutex ensures %POOL_DISASSOCIATED remains
@@ -1712,7 +1716,7 @@ static struct worker *create_worker(stru
set_user_nice(worker->task, pool->attrs->nice);
/* successful, attach the worker to the pool */
- worker_attach_to_pool(worker, pool);
+ worker_attach_to_pool(worker, pool, true);
/* start the newly created worker */
spin_lock_irq(&pool->lock);
@@ -2241,7 +2245,7 @@ static int rescuer_thread(void *__rescue
spin_unlock_irq(&wq_mayday_lock);
- worker_attach_to_pool(rescuer, pool);
+ worker_attach_to_pool(rescuer, pool, false);
spin_lock_irq(&pool->lock);
rescuer->pool = pool;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-08-07 17:20 +0200 |
| Message-ID | <pURB8-3iS-13@gated-at.bofh.it> |
| In reply to | #1202737 |
On Fri, Aug 07, 2015 at 04:27:08PM +0200, Peter Zijlstra wrote:
> Which is the rescue thread attaching itself to a pool that needs help,
> and obviously the rescue thread isn't new so kthread_bind doesn't work
> right.
>
> The best I could come up with is something like the below on top; does
> that work for you? I'll go give it some runtime.
>
> --- a/kernel/workqueue.c
> +++ b/kernel/workqueue.c
> @@ -1622,11 +1622,15 @@ static struct worker *alloc_worker(int n
> * cpu-[un]hotplugs.
> */
> static void worker_attach_to_pool(struct worker *worker,
> - struct worker_pool *pool)
> + struct worker_pool *pool,
> + bool new)
> {
> mutex_lock(&pool->attach_mutex);
>
> - kthread_bind_mask(worker->task, pool->attrs->cpumask);
> + if (new)
> + kthread_bind_mask(worker->task, pool->attrs->cpumask);
> + else
> + set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
>
> /*
> * The pool->attach_mutex ensures %POOL_DISASSOCIATED remains
> @@ -1712,7 +1716,7 @@ static struct worker *create_worker(stru
> set_user_nice(worker->task, pool->attrs->nice);
>
> /* successful, attach the worker to the pool */
> - worker_attach_to_pool(worker, pool);
> + worker_attach_to_pool(worker, pool, true);
>
> /* start the newly created worker */
> spin_lock_irq(&pool->lock);
> @@ -2241,7 +2245,7 @@ static int rescuer_thread(void *__rescue
>
> spin_unlock_irq(&wq_mayday_lock);
>
> - worker_attach_to_pool(rescuer, pool);
> + worker_attach_to_pool(rescuer, pool, false);
Hmmm... the race condition didn't exist for workqueue in the first
place, right? As long as the flag is set before the affinity is
configured, there's no race condition. I think the code was better
before. Can't we just revert workqueue.c part?
Thanks.
--
tejun
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-08-07 17:40 +0200 |
| Message-ID | <pURUt-3H0-3@gated-at.bofh.it> |
| In reply to | #1202808 |
Hello, On Fri, Aug 07, 2015 at 05:29:56PM +0200, Peter Zijlstra wrote: > Even if we were to strictly order those stores you could have (note > there is no matching barrier, as there is only the one load, so ordering > cannot help): > > __kthread_bind() > <SYSCALL> > sched_setaffinity() > if (p->flags & PF_NO_SETAFFINITY) /* false-not-taken */ > p->flags |= PF_NO_SETAFFINITY; > smp_wmb(); > do_set_cpus_allowed(); > set_cpus_allowed_ptr() > > > I think the code was better before. Can't we just revert workqueue.c > > part? > > I agree that the new argument isn't pretty, but I cannot see how > workqueues would not be affected by this. So, the problem there is that __kthread_bind() doesn't grab the same lock that the syscall side grabs but workqueue used set_cpus_allowed_ptr() which goes through the rq locking, so as long as the check on syscall side is movied inside rq lock, it should be fine. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2015-08-07 18:10 +0200 |
| Message-ID | <pUSnv-4uf-5@gated-at.bofh.it> |
| In reply to | #1202826 |
On Fri, Aug 07, 2015 at 11:38:28AM -0400, Tejun Heo wrote:
> Hello,
>
> On Fri, Aug 07, 2015 at 05:29:56PM +0200, Peter Zijlstra wrote:
> > Even if we were to strictly order those stores you could have (note
> > there is no matching barrier, as there is only the one load, so ordering
> > cannot help):
> >
> > __kthread_bind()
> > <SYSCALL>
> > sched_setaffinity()
> > if (p->flags & PF_NO_SETAFFINITY) /* false-not-taken */
> > p->flags |= PF_NO_SETAFFINITY;
> > smp_wmb();
> > do_set_cpus_allowed();
> > set_cpus_allowed_ptr()
> >
> > > I think the code was better before. Can't we just revert workqueue.c
> > > part?
> >
> > I agree that the new argument isn't pretty, but I cannot see how
> > workqueues would not be affected by this.
>
> So, the problem there is that __kthread_bind() doesn't grab the same
> lock that the syscall side grabs but workqueue used
> set_cpus_allowed_ptr() which goes through the rq locking, so as long
> as the check on syscall side is movied inside rq lock, it should be
> fine.
Currently neither site uses any lock, and that is what the patch fixes
(it uses the per-task ->pi_lock instead of the rq->lock, but that is
immaterial).
What matters though is that you now must hold a scheduler lock while
setting PF_NO_SETAFFINITY. In order to avoid spreading that knowledge
around I've taught kthread_bind*() about this and made the workqueue
code use that API (rather than having the workqueue code take scheduler
locks).
Hmm.. a better solution. Have the worker thread creation call
kthread_bind_mask() before attach_to_pool() and have attach_to_pool()
keep using set_cpus_allowed_ptr(). Less ugly.
---
Subject: sched: Fix a race between __kthread_bind() and sched_setaffinity()
From: Peter Zijlstra <peterz@infradead.org>
Date: Fri, 15 May 2015 17:43:34 +0200
Because sched_setscheduler() checks p->flags & PF_NO_SETAFFINITY
without locks, a caller might observe an old value and race with the
set_cpus_allowed_ptr() call from __kthread_bind() and effectively undo
it.
__kthread_bind()
do_set_cpus_allowed()
<SYSCALL>
sched_setaffinity()
if (p->flags & PF_NO_SETAFFINITIY)
set_cpus_allowed_ptr()
p->flags |= PF_NO_SETAFFINITY
Fix the issue by putting everything under the regular scheduler locks.
This also closes a hole in the serialization of
task_struct::{nr_,}cpus_allowed.
Cc: riel@redhat.com
Cc: dedekind1@gmail.com
Cc: mgorman@suse.de
Cc: rostedt@goodmis.org
Cc: juri.lelli@arm.com
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: mingo@kernel.org
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20150515154833.545640346@infradead.org
---
include/linux/kthread.h | 1 +
include/linux/sched.h | 7 -------
kernel/kthread.c | 20 +++++++++++++++++---
kernel/sched/core.c | 36 ++++++++++++++++++++++++++++++++----
kernel/workqueue.c | 6 ++----
5 files changed, 52 insertions(+), 18 deletions(-)
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -38,6 +38,7 @@ struct task_struct *kthread_create_on_cp
})
void kthread_bind(struct task_struct *k, unsigned int cpu);
+void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask);
int kthread_stop(struct task_struct *k);
bool kthread_should_stop(void);
bool kthread_should_park(void);
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2215,13 +2215,6 @@ static inline void calc_load_enter_idle(
static inline void calc_load_exit_idle(void) { }
#endif /* CONFIG_NO_HZ_COMMON */
-#ifndef CONFIG_CPUMASK_OFFSTACK
-static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
-{
- return set_cpus_allowed_ptr(p, &new_mask);
-}
-#endif
-
/*
* Do not use outside of architecture code which knows its limitations.
*
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -325,16 +325,30 @@ struct task_struct *kthread_create_on_no
}
EXPORT_SYMBOL(kthread_create_on_node);
-static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state)
+static void __kthread_bind_mask(struct task_struct *p, const struct cpumask *mask, long state)
{
- /* Must have done schedule() in kthread() before we set_task_cpu */
+ unsigned long flags;
+
if (!wait_task_inactive(p, state)) {
WARN_ON(1);
return;
}
+
/* It's safe because the task is inactive. */
- do_set_cpus_allowed(p, cpumask_of(cpu));
+ raw_spin_lock_irqsave(&p->pi_lock, flags);
+ do_set_cpus_allowed(p, mask);
p->flags |= PF_NO_SETAFFINITY;
+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+}
+
+static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state)
+{
+ __kthread_bind_mask(p, cpumask_of(cpu), state);
+}
+
+void kthread_bind_mask(struct task_struct *p, const struct cpumask *mask)
+{
+ __kthread_bind_mask(p, mask, TASK_UNINTERRUPTIBLE);
}
/**
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1151,6 +1151,8 @@ static int migration_cpu_stop(void *data
void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
{
+ lockdep_assert_held(&p->pi_lock);
+
if (p->sched_class->set_cpus_allowed)
p->sched_class->set_cpus_allowed(p, new_mask);
@@ -1167,7 +1169,8 @@ void do_set_cpus_allowed(struct task_str
* task must not exit() & deallocate itself prematurely. The
* call is not atomic; no spinlocks may be held.
*/
-int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
+static int __set_cpus_allowed_ptr(struct task_struct *p,
+ const struct cpumask *new_mask, bool check)
{
unsigned long flags;
struct rq *rq;
@@ -1176,6 +1179,15 @@ int set_cpus_allowed_ptr(struct task_str
rq = task_rq_lock(p, &flags);
+ /*
+ * Must re-check here, to close a race against __kthread_bind(),
+ * sched_setaffinity() is not guaranteed to observe the flag.
+ */
+ if (check && (p->flags & PF_NO_SETAFFINITY)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
if (cpumask_equal(&p->cpus_allowed, new_mask))
goto out;
@@ -1212,6 +1224,11 @@ int set_cpus_allowed_ptr(struct task_str
return ret;
}
+
+int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
+{
+ return __set_cpus_allowed_ptr(p, new_mask, false);
+}
EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
@@ -1593,6 +1610,15 @@ static void update_avg(u64 *avg, u64 sam
s64 diff = sample - *avg;
*avg += diff >> 3;
}
+
+#else
+
+static inline int __set_cpus_allowed_ptr(struct task_struct *p,
+ const struct cpumask *new_mask, bool check)
+{
+ return set_cpus_allowed_ptr(p, new_mask);
+}
+
#endif /* CONFIG_SMP */
static void
@@ -4338,7 +4364,7 @@ long sched_setaffinity(pid_t pid, const
}
#endif
again:
- retval = set_cpus_allowed_ptr(p, new_mask);
+ retval = __set_cpus_allowed_ptr(p, new_mask, true);
if (!retval) {
cpuset_cpus_allowed(p, cpus_allowed);
@@ -4863,7 +4889,8 @@ void init_idle(struct task_struct *idle,
struct rq *rq = cpu_rq(cpu);
unsigned long flags;
- raw_spin_lock_irqsave(&rq->lock, flags);
+ raw_spin_lock_irqsave(&idle->pi_lock, flags);
+ raw_spin_lock(&rq->lock);
__sched_fork(0, idle);
idle->state = TASK_RUNNING;
@@ -4889,7 +4916,8 @@ void init_idle(struct task_struct *idle,
#if defined(CONFIG_SMP)
idle->on_cpu = 1;
#endif
- raw_spin_unlock_irqrestore(&rq->lock, flags);
+ raw_spin_unlock(&rq->lock);
+ raw_spin_unlock_irqrestore(&idle->pi_lock, flags);
/* Set the preempt count _outside_ the spinlocks! */
init_idle_preempt_count(idle, cpu);
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1714,9 +1714,7 @@ static struct worker *create_worker(stru
goto fail;
set_user_nice(worker->task, pool->attrs->nice);
-
- /* prevent userland from meddling with cpumask of workqueue workers */
- worker->task->flags |= PF_NO_SETAFFINITY;
+ kthread_bind_mask(worker->task, pool->attrs->cpumask);
/* successful, attach the worker to the pool */
worker_attach_to_pool(worker, pool);
@@ -3856,7 +3854,7 @@ struct workqueue_struct *__alloc_workque
}
wq->rescuer = rescuer;
- rescuer->task->flags |= PF_NO_SETAFFINITY;
+ kthread_bind_mask(rescuer->task, cpu_possible_mask);
wake_up_process(rescuer->task);
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Tejun Heo <tj@kernel.org> |
|---|---|
| Date | 2015-08-07 18:20 +0200 |
| Message-ID | <pUSxc-4FO-19@gated-at.bofh.it> |
| In reply to | #1202848 |
Hello, Peter. On Fri, Aug 07, 2015 at 05:59:54PM +0200, Peter Zijlstra wrote: > > So, the problem there is that __kthread_bind() doesn't grab the same > > lock that the syscall side grabs but workqueue used > > set_cpus_allowed_ptr() which goes through the rq locking, so as long > > as the check on syscall side is movied inside rq lock, it should be > > fine. > > Currently neither site uses any lock, and that is what the patch fixes > (it uses the per-task ->pi_lock instead of the rq->lock, but that is > immaterial). Yeap, the testing on the syscall side should definitely be moved inside rq->lock. > What matters though is that you now must hold a scheduler lock while > setting PF_NO_SETAFFINITY. In order to avoid spreading that knowledge > around I've taught kthread_bind*() about this and made the workqueue > code use that API (rather than having the workqueue code take scheduler > locks). So, as long as PF_NO_SETAFFINITY is set before the task sets its affinity to its target holding the rq lock, it should still be safe. > Hmm.. a better solution. Have the worker thread creation call > kthread_bind_mask() before attach_to_pool() and have attach_to_pool() > keep using set_cpus_allowed_ptr(). Less ugly. Yeah, that works too. About the same effect. Thanks. -- tejun -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Peter Zijlstra <peterz@infradead.org> |
|---|---|
| Date | 2015-08-07 17:40 +0200 |
| Message-ID | <pURUu-3H0-5@gated-at.bofh.it> |
| In reply to | #1202808 |
On Fri, Aug 07, 2015 at 11:16:08AM -0400, Tejun Heo wrote:
> On Fri, Aug 07, 2015 at 04:27:08PM +0200, Peter Zijlstra wrote:
> > Which is the rescue thread attaching itself to a pool that needs help,
> > and obviously the rescue thread isn't new so kthread_bind doesn't work
> > right.
> >
> > The best I could come up with is something like the below on top; does
> > that work for you? I'll go give it some runtime.
> >
> > --- a/kernel/workqueue.c
> > +++ b/kernel/workqueue.c
> > @@ -1622,11 +1622,15 @@ static struct worker *alloc_worker(int n
> > * cpu-[un]hotplugs.
> > */
> > static void worker_attach_to_pool(struct worker *worker,
> > - struct worker_pool *pool)
> > + struct worker_pool *pool,
> > + bool new)
> > {
> > mutex_lock(&pool->attach_mutex);
> >
> > - kthread_bind_mask(worker->task, pool->attrs->cpumask);
> > + if (new)
> > + kthread_bind_mask(worker->task, pool->attrs->cpumask);
> > + else
> > + set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask);
> >
> > /*
> > * The pool->attach_mutex ensures %POOL_DISASSOCIATED remains
> > @@ -1712,7 +1716,7 @@ static struct worker *create_worker(stru
> > set_user_nice(worker->task, pool->attrs->nice);
> >
> > /* successful, attach the worker to the pool */
> > - worker_attach_to_pool(worker, pool);
> > + worker_attach_to_pool(worker, pool, true);
> >
> > /* start the newly created worker */
> > spin_lock_irq(&pool->lock);
> > @@ -2241,7 +2245,7 @@ static int rescuer_thread(void *__rescue
> >
> > spin_unlock_irq(&wq_mayday_lock);
> >
> > - worker_attach_to_pool(rescuer, pool);
> > + worker_attach_to_pool(rescuer, pool, false);
>
> Hmmm... the race condition didn't exist for workqueue in the first
> place, right?
No, I think workqueues are susceptible just the same as everybody else.
By the time we call __kthread_bind() the task exists and is visible to
userspace.
__kthread_bind()
do_set_cpus_allowed()
<SYSCALL>
sched_setaffinity()
if (p->flags & PF_NO_SETAFFINITIY) /* false-not-taken */
set_cpus_allowed_ptr()
p->flags |= PF_NO_SETAFFINITY
> As long as the flag is set before the affinity is configured, there's
> no race condition.
Even if we were to strictly order those stores you could have (note
there is no matching barrier, as there is only the one load, so ordering
cannot help):
__kthread_bind()
<SYSCALL>
sched_setaffinity()
if (p->flags & PF_NO_SETAFFINITY) /* false-not-taken */
p->flags |= PF_NO_SETAFFINITY;
smp_wmb();
do_set_cpus_allowed();
set_cpus_allowed_ptr()
> I think the code was better before. Can't we just revert workqueue.c
> part?
I agree that the new argument isn't pretty, but I cannot see how
workqueues would not be affected by this.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web