rcu: Avoid data-race in rcu_gp_fqs_check_wake()
[platform/kernel/linux-rpi.git] / kernel / rcu / tree_plugin.h
index 2defc7f..2707794 100644 (file)
@@ -220,7 +220,7 @@ static void rcu_preempt_ctxt_queue(struct rcu_node *rnp, struct rcu_data *rdp)
         * blocked tasks.
         */
        if (!rnp->gp_tasks && (blkd_state & RCU_GP_BLKD)) {
-               rnp->gp_tasks = &t->rcu_node_entry;
+               WRITE_ONCE(rnp->gp_tasks, &t->rcu_node_entry);
                WARN_ON_ONCE(rnp->completedqs == rnp->gp_seq);
        }
        if (!rnp->exp_tasks && (blkd_state & RCU_EXP_BLKD))
@@ -340,7 +340,7 @@ EXPORT_SYMBOL_GPL(rcu_note_context_switch);
  */
 static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp)
 {
-       return rnp->gp_tasks != NULL;
+       return READ_ONCE(rnp->gp_tasks) != NULL;
 }
 
 /* Bias and limit values for ->rcu_read_lock_nesting. */
@@ -493,7 +493,7 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)
                trace_rcu_unlock_preempted_task(TPS("rcu_preempt"),
                                                rnp->gp_seq, t->pid);
                if (&t->rcu_node_entry == rnp->gp_tasks)
-                       rnp->gp_tasks = np;
+                       WRITE_ONCE(rnp->gp_tasks, np);
                if (&t->rcu_node_entry == rnp->exp_tasks)
                        rnp->exp_tasks = np;
                if (IS_ENABLED(CONFIG_RCU_BOOST)) {
@@ -663,7 +663,7 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)
                dump_blkd_tasks(rnp, 10);
        if (rcu_preempt_has_tasks(rnp) &&
            (rnp->qsmaskinit || rnp->wait_blkd_tasks)) {
-               rnp->gp_tasks = rnp->blkd_tasks.next;
+               WRITE_ONCE(rnp->gp_tasks, rnp->blkd_tasks.next);
                t = container_of(rnp->gp_tasks, struct task_struct,
                                 rcu_node_entry);
                trace_rcu_unlock_preempted_task(TPS("rcu_preempt-GPS"),
@@ -757,7 +757,8 @@ dump_blkd_tasks(struct rcu_node *rnp, int ncheck)
                pr_info("%s: %d:%d ->qsmask %#lx ->qsmaskinit %#lx ->qsmaskinitnext %#lx\n",
                        __func__, rnp1->grplo, rnp1->grphi, rnp1->qsmask, rnp1->qsmaskinit, rnp1->qsmaskinitnext);
        pr_info("%s: ->gp_tasks %p ->boost_tasks %p ->exp_tasks %p\n",
-               __func__, rnp->gp_tasks, rnp->boost_tasks, rnp->exp_tasks);
+               __func__, READ_ONCE(rnp->gp_tasks), rnp->boost_tasks,
+               rnp->exp_tasks);
        pr_info("%s: ->blkd_tasks", __func__);
        i = 0;
        list_for_each(lhp, &rnp->blkd_tasks) {
@@ -1946,7 +1947,7 @@ static void nocb_gp_wait(struct rcu_data *my_rdp)
        int __maybe_unused cpu = my_rdp->cpu;
        unsigned long cur_gp_seq;
        unsigned long flags;
-       bool gotcbs;
+       bool gotcbs = false;
        unsigned long j = jiffies;
        bool needwait_gp = false; // This prevents actual uninitialized use.
        bool needwake;