diff options
| author | Paul E. McKenney <paulmck@kernel.org> | 2026-07-20 16:36:55 -0700 |
|---|---|---|
| committer | Paul E. McKenney <paulmck@kernel.org> | 2026-07-24 16:59:24 -0700 |
| commit | 2aaee3fc84e10c5949e24a8778414ade2db44a55 (patch) | |
| tree | 09ca286fdebb1f405827abd141d950a47d15e9c4 | |
| parent | 545b3ac4c1db3c455cbe1bd1ed305e54ad87512e (diff) | |
| download | linux-next-2aaee3fc84e10c5949e24a8778414ade2db44a55.tar.gz linux-next-2aaee3fc84e10c5949e24a8778414ade2db44a55.zip | |
rcu: Mark accesses to rdp->rcu_cpu_has_work
Although the rdp->rcu_cpu_has_work field is accessed only by the
corresponding CPU, it can be accessed by both interrupt handlers via
invoke_rcu_core_kthread() and at task level via rcu_cpu_kthread().
This means that we need this_cpu_read() rather than __this_cpu_read(),
this_cpu_write() rather than __this_cpu_write(), and READ_ONCE()
rather than plain C-language loads. The exception is the boot-time
rcu_spawn_core_kthreads(), which cannot race with kthreads that have
not yet been spawned.
This commit therefore makes it so.
KCSAN located this issue.
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
| -rw-r--r-- | kernel/rcu/tree.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 390dad82675d..c9780e7c0e2a 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -2671,7 +2671,7 @@ static void rcu_do_batch(struct rcu_data *rdp) // reporting, so check time limits for them. if (rdp->rcu_cpu_kthread_status == RCU_KTHREAD_RUNNING && rcu_do_batch_check_time(count, tlimit, jlimit_check, jlimit)) { - rdp->rcu_cpu_has_work = 1; + WRITE_ONCE(rdp->rcu_cpu_has_work, 1); break; } } @@ -2931,7 +2931,7 @@ static void invoke_rcu_core_kthread(void) unsigned long flags; local_irq_save(flags); - __this_cpu_write(rcu_data.rcu_cpu_has_work, 1); + this_cpu_write(rcu_data.rcu_cpu_has_work, 1); t = __this_cpu_read(rcu_data.rcu_cpu_kthread_task); if (t != NULL && t != current) rcu_wake_cond(t, __this_cpu_read(rcu_data.rcu_cpu_kthread_status)); @@ -2958,7 +2958,7 @@ static void rcu_cpu_kthread_park(unsigned int cpu) static int rcu_cpu_kthread_should_run(unsigned int cpu) { - return __this_cpu_read(rcu_data.rcu_cpu_has_work); + return this_cpu_read(rcu_data.rcu_cpu_has_work); } /* @@ -2979,7 +2979,7 @@ static void rcu_cpu_kthread(unsigned int cpu) local_bh_disable(); *statusp = RCU_KTHREAD_RUNNING; local_irq_disable(); - work = *workp; + work = READ_ONCE(*workp); WRITE_ONCE(*workp, 0); local_irq_enable(); if (work) |
