This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 2e8583f7590ce2f428856a12b74b27584e4881af Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> AuthorDate: Fri May 9 14:55:10 2025 +0800 clock: Fix timing error. This commit resolves a timing error caused by the round-up behavior in clock_time2ticks. In rare cases, this could lead to a two-tick increment within a single tick interval. To fix this, we introduced clock_time2ticks_floor, which guarantees the correct semantics for obtaining current system ticks. Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> --- include/nuttx/clock.h | 4 ++++ include/nuttx/timers/oneshot.h | 2 +- sched/clock/clock_systime_ticks.c | 2 +- sched/sched/sched_timerexpiration.c | 8 ++++---- sched/timer/timer_settime.c | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/include/nuttx/clock.h b/include/nuttx/clock.h index cb1aa81483..13074e2587 100644 --- a/include/nuttx/clock.h +++ b/include/nuttx/clock.h @@ -353,6 +353,10 @@ EXTERN volatile clock_t g_system_ticks; #define clock_time2ticks(ts) \ ((clock_t)(ts)->tv_sec * TICK_PER_SEC + NSEC2TICK((uint32_t)(ts)->tv_nsec)) +#define clock_time2ticks_floor(ts) \ + ((clock_t)(ts)->tv_sec * TICK_PER_SEC + \ + div_const((uint32_t)(ts)->tv_nsec, NSEC_PER_TICK)) + #define clock_usec2time(ts, usec) \ do \ { \ diff --git a/include/nuttx/timers/oneshot.h b/include/nuttx/timers/oneshot.h index 8c313a87be..a9d09d8ed1 100644 --- a/include/nuttx/timers/oneshot.h +++ b/include/nuttx/timers/oneshot.h @@ -395,7 +395,7 @@ int oneshot_tick_current(FAR struct oneshot_lowerhalf_s *lower, } ret = lower->ops->current(lower, &ts); - *ticks = clock_time2ticks(&ts); + *ticks = clock_time2ticks_floor(&ts); return ret; } diff --git a/sched/clock/clock_systime_ticks.c b/sched/clock/clock_systime_ticks.c index a99d8e1040..5a377353e6 100644 --- a/sched/clock/clock_systime_ticks.c +++ b/sched/clock/clock_systime_ticks.c @@ -84,7 +84,7 @@ clock_t clock_systime_ticks(void) }; clock_systime_timespec(&ts); - return clock_time2ticks(&ts); + return clock_time2ticks_floor(&ts); #elif defined(CONFIG_ALARM_ARCH) || \ defined(CONFIG_TIMER_ARCH) || \ defined(CONFIG_SCHED_TICKLESS) diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c index b28180c26a..c6ff34fecb 100644 --- a/sched/sched/sched_timerexpiration.c +++ b/sched/sched/sched_timerexpiration.c @@ -130,7 +130,7 @@ int up_timer_gettick(FAR clock_t *ticks) struct timespec ts; int ret; ret = up_timer_gettime(&ts); - *ticks = clock_time2ticks(&ts); + *ticks = clock_time2ticks_floor(&ts); return ret; } #endif @@ -149,7 +149,7 @@ int up_alarm_tick_cancel(FAR clock_t *ticks) struct timespec ts; int ret; ret = up_alarm_cancel(&ts); - *ticks = clock_time2ticks(&ts); + *ticks = clock_time2ticks_floor(&ts); return ret; } # else @@ -165,7 +165,7 @@ int up_timer_tick_cancel(FAR clock_t *ticks) struct timespec ts; int ret; ret = up_timer_cancel(&ts); - *ticks = clock_time2ticks(&ts); + *ticks = clock_time2ticks_floor(&ts); return ret; } # endif @@ -494,7 +494,7 @@ void nxsched_alarm_expiration(FAR const struct timespec *ts) DEBUGASSERT(ts); - ticks = clock_time2ticks(ts); + ticks = clock_time2ticks_floor(ts); nxsched_alarm_tick_expiration(ticks); } #endif diff --git a/sched/timer/timer_settime.c b/sched/timer/timer_settime.c index f287ac492c..0c714c41a0 100644 --- a/sched/timer/timer_settime.c +++ b/sched/timer/timer_settime.c @@ -331,7 +331,7 @@ int timer_settime(timer_t timerid, int flags, timer->pt_expected = clock_systime_ticks() + delay; } - /* delay+1 is to prevent the insufficient sleep time if we are + /* This is to prevent the insufficient sleep time if we are * currently near the boundary to the next tick. * | current_tick | current_tick + 1 | current_tick + 2 | .... | * | ^ Here we get the current tick