diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-13 12:49:40 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-09-13 12:49:40 -0700 |
commit | fda67514e444533b44106362baddca1cdbbba836 (patch) | |
tree | 360a9f91a90e0f8a3fa0bcd678b59f701e4c7c8a /kernel | |
parent | ee319d5834c80dce3ec17fec36ef74b716ea465d (diff) | |
parent | 135e8c9250dd5c8c9aae5984fde6f230d0cbfeaf (diff) | |
download | linux-fda67514e444533b44106362baddca1cdbbba836.tar.bz2 |
Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull scheduler fix from Ingo Molnar:
"A try_to_wake_up() memory ordering race fix causing a busy-loop in
ttwu()"
* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
sched/core: Fix a race between try_to_wake_up() and a woken up task
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/sched/core.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 2a906f20fba7..44817c640e99 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2016,6 +2016,28 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) success = 1; /* we're going to change ->state */ cpu = task_cpu(p); + /* + * Ensure we load p->on_rq _after_ p->state, otherwise it would + * be possible to, falsely, observe p->on_rq == 0 and get stuck + * in smp_cond_load_acquire() below. + * + * sched_ttwu_pending() try_to_wake_up() + * [S] p->on_rq = 1; [L] P->state + * UNLOCK rq->lock -----. + * \ + * +--- RMB + * schedule() / + * LOCK rq->lock -----' + * UNLOCK rq->lock + * + * [task p] + * [S] p->state = UNINTERRUPTIBLE [L] p->on_rq + * + * Pairs with the UNLOCK+LOCK on rq->lock from the + * last wakeup of our task and the schedule that got our task + * current. + */ + smp_rmb(); if (p->on_rq && ttwu_remote(p, wake_flags)) goto stat; |