|
@@ -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;
|
|
|
|