void activate_task(struct rq *rq, struct task_struct *p, int flags)
 {
-       if (task_contributes_to_load(p))
-               rq->nr_uninterruptible--;
-
        enqueue_task(rq, p, flags);
 
        p->on_rq = TASK_ON_RQ_QUEUED;
 {
        p->on_rq = (flags & DEQUEUE_SLEEP) ? 0 : TASK_ON_RQ_MIGRATING;
 
-       if (task_contributes_to_load(p))
-               rq->nr_uninterruptible++;
-
        dequeue_task(rq, p, flags);
 }
 
 
        lockdep_assert_held(&rq->lock);
 
-#ifdef CONFIG_SMP
        if (p->sched_contributes_to_load)
                rq->nr_uninterruptible--;
 
+#ifdef CONFIG_SMP
        if (wake_flags & WF_MIGRATED)
                en_flags |= ENQUEUE_MIGRATED;
 #endif
         * A similar smb_rmb() lives in try_invoke_on_locked_down_task().
         */
        smp_rmb();
-       if (p->on_rq && ttwu_remote(p, wake_flags))
+       if (READ_ONCE(p->on_rq) && ttwu_remote(p, wake_flags))
                goto unlock;
 
        if (p->in_iowait) {
        }
 
 #ifdef CONFIG_SMP
-       p->sched_contributes_to_load = !!task_contributes_to_load(p);
-       p->state = TASK_WAKING;
-
        /*
         * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
         * possible to, falsely, observe p->on_cpu == 0.
         *
         * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
         * __schedule().  See the comment for smp_mb__after_spinlock().
+        *
+        * Form a control-dep-acquire with p->on_rq == 0 above, to ensure
+        * schedule()'s deactivate_task() has 'happened' and p will no longer
+        * care about it's own p->state. See the comment in __schedule().
         */
-       smp_rmb();
+       smp_acquire__after_ctrl_dep();
+
+       /*
+        * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq
+        * == 0), which means we need to do an enqueue, change p->state to
+        * TASK_WAKING such that we can unlock p->pi_lock before doing the
+        * enqueue, such as ttwu_queue_wakelist().
+        */
+       p->state = TASK_WAKING;
 
        /*
         * If the owning (remote) CPU is still in the middle of schedule() with
 {
        struct task_struct *prev, *next;
        unsigned long *switch_count;
+       unsigned long prev_state;
        struct rq_flags rf;
        struct rq *rq;
        int cpu;
        local_irq_disable();
        rcu_note_context_switch(preempt);
 
+       /* See deactivate_task() below. */
+       prev_state = prev->state;
+
        /*
         * Make sure that signal_pending_state()->signal_pending() below
         * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
-        * done by the caller to avoid the race with signal_wake_up().
+        * done by the caller to avoid the race with signal_wake_up():
+        *
+        * __set_current_state(@state)          signal_wake_up()
+        * schedule()                             set_tsk_thread_flag(p, TIF_SIGPENDING)
+        *                                        wake_up_state(p, state)
+        *   LOCK rq->lock                          LOCK p->pi_state
+        *   smp_mb__after_spinlock()               smp_mb__after_spinlock()
+        *     if (signal_pending_state())          if (p->state & @state)
         *
-        * The membarrier system call requires a full memory barrier
+        * Also, the membarrier system call requires a full memory barrier
         * after coming from user-space, before storing to rq->curr.
         */
        rq_lock(rq, &rf);
        update_rq_clock(rq);
 
        switch_count = &prev->nivcsw;
-       if (!preempt && prev->state) {
-               if (signal_pending_state(prev->state, prev)) {
+       /*
+        * We must re-load prev->state in case ttwu_remote() changed it
+        * before we acquired rq->lock.
+        */
+       if (!preempt && prev_state && prev_state == prev->state) {
+               if (signal_pending_state(prev_state, prev)) {
                        prev->state = TASK_RUNNING;
                } else {
+                       prev->sched_contributes_to_load =
+                               (prev_state & TASK_UNINTERRUPTIBLE) &&
+                               !(prev_state & TASK_NOLOAD) &&
+                               !(prev->flags & PF_FROZEN);
+
+                       if (prev->sched_contributes_to_load)
+                               rq->nr_uninterruptible++;
+
+                       /*
+                        * __schedule()                 ttwu()
+                        *   prev_state = prev->state;    if (READ_ONCE(p->on_rq) && ...)
+                        *   LOCK rq->lock                  goto out;
+                        *   smp_mb__after_spinlock();    smp_acquire__after_ctrl_dep();
+                        *   p->on_rq = 0;                p->state = TASK_WAKING;
+                        *
+                        * After this, schedule() must not care about p->state any more.
+                        */
                        deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK);
 
                        if (prev->in_iowait) {