summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@kernel.org>2026-07-20 16:36:55 -0700
committerPaul E. McKenney <paulmck@kernel.org>2026-07-24 16:59:24 -0700
commit2aaee3fc84e10c5949e24a8778414ade2db44a55 (patch)
tree09ca286fdebb1f405827abd141d950a47d15e9c4
parent545b3ac4c1db3c455cbe1bd1ed305e54ad87512e (diff)
downloadlinux-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.c8
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)