drivers/timers: avoid 32-bit overflow in arch_timer current_usec

current_usec() returns a uint64_t, but it used TICK2USEC(timebase)
to convert scheduler ticks to microseconds. On 32-bit clock_t builds,
TICK2USEC() performs the multiplication in 32-bit arithmetic before the
result is widened.

With CONFIG_USEC_PER_TICK=10000, this wraps after about 71.6 minutes:

  UINT32_MAX / 1000000 ~= 4294 seconds

After the wrap, up_timer_gettick() can report time near zero again. This
can leave absolute watchdog timeouts, such as those used by usleep() /
clock_nanosleep(), waiting for a tick value that will not be reached until
the 32-bit scheduler counter wraps.

Cast timebase to uint64_t before multiplying by USEC_PER_TICK so
current_usec() remains monotonic across the 32-bit microsecond boundary.

Signed-off-by: Max Kriegleder <max.kriegleder@gmail.com>
This commit is contained in:
Max Kriegleder
2026-05-06 00:30:55 +02:00
committed by Alin Jerpelea
parent 990ac856b2
commit eb92f0f8c8
+2 -1
View File
@@ -114,7 +114,8 @@ static uint64_t current_usec(void)
}
while (timebase != g_timer.timebase);
return TICK2USEC(timebase) + (status.timeout - status.timeleft);
return TICK2USEC((uint64_t)timebase) +
(status.timeout - status.timeleft);
}
static void udelay_accurate(useconds_t microseconds)