[QUESTION] sched/clock: Potential timestamp jump due to inter-CPU counter skew?
From: Zhang Qiao
Date: Mon Oct 26 2026 - 02:54:55 EST
Hi all,
While reading kernel/time/sched_clock.c, I had a question about counter
synchronization requirements across CPUs.
update_sched_clock() updates the shared epoch_cyc using a counter value read on
the CPU performing the update. Other CPUs subsequently call sched_clock() and
subtract this shared epoch from the counter value they read:
cyc = (rd->read_sched_clock() - rd->epoch_cyc) & rd->sched_clock_mask;
res = rd->epoch_ns + cyc_to_ns(cyc, rd->mult, rd->shift);
If CPU1 observes a new epoch_cyc published by CPU0, but its subsequent counter
read returns a value strictly less than that epoch (assuming no normal counter
wrap-around), the unsigned subtraction would underflow. After masking, this
produces a very large delta and potentially causes sched_clock() to return an
incorrect, massive timestamp.
For example, consider this hypothetical sequence:
1. CPU0 reads the counter and gets 1000.
2. CPU0 completes the epoch update, publishing {epoch_cyc = 1000, epoch_ns = N}.
3. CPU1 observes the new epoch, but its subsequent counter read returns 993.
Assuming a 56-bit counter mask, CPU1 would calculate:
(993 - 1000) & ((1ULL << 56) - 1) = 2^56 - 7
Although the counter read on CPU1 is only seven ticks behind the epoch, the
calculated delta is close to a full counter period. Passing this delta to
cyc_to_ns() could cause a multiplication overflow or yield a completely
incorrect timestamp.
This scenario assumes the inter-CPU counter skew exceeds the time it takes for
CPU0 to publish the new epoch and CPU1 to observe it and read its own counter.
(All values in this example are hypothetical).
My questions are:
1. Are there hardware or architecture specifications (e.g., ARM64 architected
timers, RISC-V) requiring counters on all CPUs—including those on different
dies/sockets—to be perfectly synchronized? If skew is permitted, is there a
specified maximum allowed skew?
2. If the sequence above is theoretically possible, does generic sched_clock()
already have a mechanism to handle a counter read that lags behind the shared
epoch_cyc?
Any comments or suggestions are welcome.
Best regards,
Zhang Qiao