[PATCH] sched/loadavg: Use READ_ONCE/WRITE_ONCE for calc_load_idx

From: Hui Su

Date: Tue Oct 13 2026 - 10:46:41 EST


The NO_HZ fold path reads calc_load_idx locklessly from
calc_load_write_idx(), while calc_global_nohz() updates it from the
jiffies_lock-serialized global load path.

Commit caeb5882979b ("sched/loadavg: Use {READ,WRITE}_ONCE() for sample
window") marked the lockless accesses to calc_load_update. calc_load_idx
participates in the same cross-CPU protocol, ordered by the existing
smp_wmb()/smp_rmb() pair, but its accesses remain plain C accesses.

Mark the lockless read and publisher access with READ_ONCE() and
WRITE_ONCE(). KCSAN otherwise observes the concurrent access:

BUG: KCSAN: data-race in calc_global_load / calc_load_nohz_fold

write by interrupt on cpu 3:
calc_global_load+0x392/0x420
tick_do_update_jiffies64+0x171/0x1e0

read by task 0 on cpu 5:
calc_load_nohz_fold+0x7a/0x110
calc_load_nohz_start+0x26/0x30

value changed: 0x00000033 -> 0x00000034

Keep the existing memory ordering and writer serialization unchanged.
calc_load_read_idx() is only used from the jiffies_lock-serialized
global load path and does not need an accessor.

Fixes: 5167e8d5417b ("sched/nohz: Rewrite and fix load-avg computation -- again")
Signed-off-by: Hui Su <sh_def@xxxxxxx>
---
kernel/sched/loadavg.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c
index b601e0243d0e..f87059e0e251 100644
--- a/kernel/sched/loadavg.c
+++ b/kernel/sched/loadavg.c
@@ -209,7 +209,7 @@ static int calc_load_idx;

static inline int calc_load_write_idx(void)
{
- int idx = calc_load_idx;
+ int idx = READ_ONCE(calc_load_idx);

/*
* See calc_global_nohz(), if we observe the new index, we also
@@ -333,7 +333,7 @@ static void calc_global_nohz(void)
* index, this avoids a double flip messing things up.
*/
smp_wmb();
- calc_load_idx++;
+ WRITE_ONCE(calc_load_idx, READ_ONCE(calc_load_idx) + 1);
}
#else /* !CONFIG_NO_HZ_COMMON: */

--
2.55.0