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

Reply via email to