Back to Ponyc

`ponyint_cpu_tick()` counter width ↔ `ponyint_cpu_tick_diff()` mask (`src/libponyrt/sched/cpu.c`)

.known-couplings/cpu-tick-width.md

0.66.01022 B
Original Source

ponyint_cpu_tick() counter width ↔ ponyint_cpu_tick_diff() mask (src/libponyrt/sched/cpu.c)

On AArch32 with a readable PMU, ponyint_cpu_tick() returns ((uint64_t)pmccntr) << 6 — a 38-bit value that wraps every couple of minutes; every other platform path is an effectively non-wrapping 64-bit value. ponyint_cpu_tick_diff() masks the elapsed-tick subtraction at PONY_CPU_TICK_BITS so it stays correct across that wrap. Two things must stay in step with the pmccntr return: (1) the #if guard on PONY_CPU_TICK_BITS must be byte-identical to the one selecting the pmccntr path (PLATFORM_IS_ARM && !__APPLE__ && !PLATFORM_IS_WINDOWS && ARMV6), and (2) the 38 must equal the counter's bit width (32-bit pmccntr plus the << 6). Drift in either masks diffs at the wrong width, so the scheduler misreads elapsed time — and only on 32-bit ARM, so x86/CI never sees it. Both ends carry comments pointing at each other. Run: make test-core (plus the CpuTickDiff suite in libponyrt.tests).