From 99efdd6a4037f34003d3b4a2615df6fa815751a3 Mon Sep 17 00:00:00 2001 From: Max Kriegleder Date: Wed, 6 May 2026 00:30:55 +0200 Subject: [PATCH] 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 --- drivers/timers/arch_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/timers/arch_timer.c b/drivers/timers/arch_timer.c index 46d1144466e4f..be343dc154cd4 100644 --- a/drivers/timers/arch_timer.c +++ b/drivers/timers/arch_timer.c @@ -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)