From feefb7dd3591f17412d2c4f10d7dc3f83fa1d876 Mon Sep 17 00:00:00 2001 From: Akaiwa Wataru Date: Thu, 28 Nov 2024 23:23:37 +0900 Subject: [PATCH] kernel/sched: correct k_sleep() return value calculation Fix the issue: https://github.com/zephyrproject-rtos/zephyr/issues/79863 The expected_wakeup_ticks and sys_clock_tick_get_32() are uint32_t values, and may wrap around individually. If the expected_wakeup_ticks has a wraparound and sys_clock_tick_get_32() doesn't, so expected_wakeup_ticks < sys_clock_tick_get_32(), the API return value will be corrupted. The API return value, that is the remaining time, should be calculated in 32bit-unsigned-integer manner, and any wraparound will be treated properly. Signed-off-by: Akaiwa Wataru --- kernel/sched.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 4105ebaa3ebc2f..3323adb05e2733 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -1117,7 +1117,11 @@ static int32_t z_tick_sleep(k_ticks_t ticks) __ASSERT(!z_is_thread_state_set(arch_current_thread(), _THREAD_SUSPENDED), ""); - ticks = (k_ticks_t)expected_wakeup_ticks - sys_clock_tick_get_32(); + /* We require a 32 bit unsigned subtraction to care a wraparound */ + uint32_t left_ticks = expected_wakeup_ticks - sys_clock_tick_get_32(); + + /* To handle a negative value correctly, once type-cast it to signed 32 bit */ + ticks = (k_ticks_t)(int32_t)left_ticks; if (ticks > 0) { return ticks; }