]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rcu: Mark loads from rcu_state.n_online_cpus
authorPaul E. McKenney <paulmck@kernel.org>
Fri, 8 Mar 2024 04:14:55 +0000 (20:14 -0800)
committerUladzislau Rezki (Sony) <urezki@gmail.com>
Mon, 15 Apr 2024 14:48:26 +0000 (16:48 +0200)
The rcu_state.n_online_cpus value is only ever updated by CPU-hotplug
operations, which are serialized.  However, this value is read locklessly.
This commit therefore marks those reads.  While in the area, it also
adds ASSERT_EXCLUSIVE_WRITER() calls just in case parallel CPU hotplug
becomes a thing.

Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Uladzislau Rezki (Sony) <urezki@gmail.com>
kernel/rcu/tree.c
kernel/rcu/tree_stall.h

index 559f2d0d271f41f995a5f00b44ca39f097ba5d2b..7149b2d5cdd69a8f94a65af14ac3e52e46a1404a 100644 (file)
@@ -4328,7 +4328,7 @@ EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online);
 // whether spinlocks may be acquired safely.
 static bool rcu_init_invoked(void)
 {
-       return !!rcu_state.n_online_cpus;
+       return !!READ_ONCE(rcu_state.n_online_cpus);
 }
 
 /*
@@ -4538,6 +4538,7 @@ int rcutree_prepare_cpu(unsigned int cpu)
        raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
        rcu_spawn_rnp_kthreads(rnp);
        rcu_spawn_cpu_nocb_kthread(cpu);
+       ASSERT_EXCLUSIVE_WRITER(rcu_state.n_online_cpus);
        WRITE_ONCE(rcu_state.n_online_cpus, rcu_state.n_online_cpus + 1);
 
        return 0;
@@ -4806,6 +4807,7 @@ void rcutree_migrate_callbacks(int cpu)
  */
 int rcutree_dead_cpu(unsigned int cpu)
 {
+       ASSERT_EXCLUSIVE_WRITER(rcu_state.n_online_cpus);
        WRITE_ONCE(rcu_state.n_online_cpus, rcu_state.n_online_cpus - 1);
        // Stop-machine done, so allow nohz_full to disable tick.
        tick_dep_clear(TICK_DEP_BIT_RCU);
index 62b2c4858028553a5fcd73c596ef5be3fd21d03e..8a2edf6a1ef5815481ecc1dac58693f2b2d84d23 100644 (file)
@@ -628,7 +628,8 @@ static void print_other_cpu_stall(unsigned long gp_seq, unsigned long gps)
                totqlen += rcu_get_n_cbs_cpu(cpu);
        pr_err("\t(detected by %d, t=%ld jiffies, g=%ld, q=%lu ncpus=%d)\n",
               smp_processor_id(), (long)(jiffies - gps),
-              (long)rcu_seq_current(&rcu_state.gp_seq), totqlen, rcu_state.n_online_cpus);
+              (long)rcu_seq_current(&rcu_state.gp_seq), totqlen,
+              data_race(rcu_state.n_online_cpus)); // Diagnostic read
        if (ndetected) {
                rcu_dump_cpu_stacks();
 
@@ -689,7 +690,8 @@ static void print_cpu_stall(unsigned long gps)
                totqlen += rcu_get_n_cbs_cpu(cpu);
        pr_err("\t(t=%lu jiffies g=%ld q=%lu ncpus=%d)\n",
                jiffies - gps,
-               (long)rcu_seq_current(&rcu_state.gp_seq), totqlen, rcu_state.n_online_cpus);
+               (long)rcu_seq_current(&rcu_state.gp_seq), totqlen,
+               data_race(rcu_state.n_online_cpus)); // Diagnostic read
 
        rcu_check_gp_kthread_expired_fqs_timer();
        rcu_check_gp_kthread_starvation();