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 64a7049decb0671a76e7a6d1585eed8bece344df
Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com>
AuthorDate: Fri May 9 20:07:58 2025 +0800

    clock: Add clock_delay2abstick.
    
    This commit added a macro function clock_delay2abstick to calculate the
    absolute tick after the delay.
    
    Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com>
---
 include/nuttx/clock.h          | 22 ++++++++++++++++++++++
 sched/semaphore/sem_tickwait.c |  2 +-
 sched/signal/sig_timedwait.c   | 10 +---------
 sched/timer/timer_settime.c    | 15 ++-------------
 sched/wdog/wd_start.c          | 18 +-----------------
 sched/wqueue/kwork_queue.c     | 10 +---------
 6 files changed, 28 insertions(+), 49 deletions(-)

diff --git a/include/nuttx/clock.h b/include/nuttx/clock.h
index 13074e2587..8aa9f06ac0 100644
--- a/include/nuttx/clock.h
+++ b/include/nuttx/clock.h
@@ -384,6 +384,28 @@ EXTERN volatile clock_t g_system_ticks;
 #define clock_time2nsec(ts) \
   ((uint64_t)(ts)->tv_sec * NSEC_PER_SEC + (uint64_t)(ts)->tv_nsec)
 
+/* Calculate delay+1, forcing the delay into a range that we can handle.
+ *
+ * NOTE that one is added to the delay.  This is correct and must not be
+ * changed:  The contract for the use wdog_start is that the wdog will
+ * delay FOR AT LEAST as long as requested, but may delay longer due to
+ * variety of factors.  The wdog logic has no knowledge of the the phase
+ * of the system timer when it is started:  The next timer interrupt may
+ * occur immediately or may be delayed for almost a full cycle. In order
+ * to meet the contract requirement, the requested time is also always
+ * incremented by one so that the delay is always at least as long as
+ * requested.
+ *
+ * E.g. delay+1 can 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
+ * In this case we delay 1 tick, timer will be triggered at
+ * current_tick + 1, which is not enough for at least 1 tick.
+ */
+
+#define clock_delay2abstick(delay) (clock_systime_ticks() + (delay) + 1)
+
 /****************************************************************************
  * Name:  clock_timespec_add
  *
diff --git a/sched/semaphore/sem_tickwait.c b/sched/semaphore/sem_tickwait.c
index afd4aef9d4..b5c08ca4fe 100644
--- a/sched/semaphore/sem_tickwait.c
+++ b/sched/semaphore/sem_tickwait.c
@@ -150,7 +150,7 @@ out:
 
 int nxsem_tickwait_uninterruptible(FAR sem_t *sem, uint32_t delay)
 {
-  clock_t end = clock_systime_ticks() + delay + 1;
+  clock_t end = clock_delay2abstick(delay);
   int ret;
 
   for (; ; )
diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c
index dec5ea3776..d396f5577c 100644
--- a/sched/signal/sig_timedwait.c
+++ b/sched/signal/sig_timedwait.c
@@ -304,15 +304,7 @@ int nxsig_clockwait(int clockid, int flags,
 
       if ((flags & TIMER_ABSTIME) == 0)
         {
-          /* delay+1 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
-           * In this case we delay 1 tick, timer will be triggered at
-           * current_tick + 1, which is not enough for at least 1 tick.
-           */
-
-          expect = clock_systime_ticks() + clock_time2ticks(rqtp) + 1;
+          expect = clock_delay2abstick(clock_time2ticks(rqtp));
           wd_start_abstick(&rtcb->waitdog, expect,
                            nxsig_timeout, (uintptr_t)rtcb);
         }
diff --git a/sched/timer/timer_settime.c b/sched/timer/timer_settime.c
index 0c714c41a0..656807fe82 100644
--- a/sched/timer/timer_settime.c
+++ b/sched/timer/timer_settime.c
@@ -316,9 +316,7 @@ int timer_settime(timer_t timerid, int flags,
     {
       /* Calculate a delay corresponding to the absolute time in 'value' */
 
-      clock_abstime2ticks(timer->pt_clock, &value->it_value,
-                          &timer->pt_expected);
-      timer->pt_expected += clock_systime_ticks();
+      clock_abstime2ticks(timer->pt_clock, &value->it_value, &delay);
     }
   else
     {
@@ -328,18 +326,9 @@ int timer_settime(timer_t timerid, int flags,
        */
 
       delay = clock_time2ticks(&value->it_value);
-      timer->pt_expected = clock_systime_ticks() + delay;
     }
 
-  /* 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
-   * In this case we delay 1 tick, timer will be triggered at
-   * current_tick + 1, which is not enough for at least 1 tick.
-   */
-
-  timer->pt_expected += 1;
+  timer->pt_expected = clock_delay2abstick(delay);
 
   /* Then start the watchdog */
 
diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c
index 409fada383..eed0c34a83 100644
--- a/sched/wdog/wd_start.c
+++ b/sched/wdog/wd_start.c
@@ -416,23 +416,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay,
       return -EINVAL;
     }
 
-  /* Calculate delay+1, forcing the delay into a range that we can handle.
-   *
-   * NOTE that one is added to the delay.  This is correct and must not be
-   * changed:  The contract for the use wdog_start is that the wdog will
-   * delay FOR AT LEAST as long as requested, but may delay longer due to
-   * variety of factors.  The wdog logic has no knowledge of the the phase
-   * of the system timer when it is started:  The next timer interrupt may
-   * occur immediately or may be delayed for almost a full cycle. In order
-   * to meet the contract requirement, the requested time is also always
-   * incremented by one so that the delay is always at least as long as
-   * requested.
-   *
-   * There is extensive documentation about this time issue elsewhere.
-   */
-
-  return wd_start_abstick(wdog, clock_systime_ticks() + delay + 1,
-                          wdentry, arg);
+  return wd_start_abstick(wdog, clock_delay2abstick(delay), wdentry, arg);
 }
 
 /****************************************************************************
diff --git a/sched/wqueue/kwork_queue.c b/sched/wqueue/kwork_queue.c
index 1e5a8dec2b..e91c664b06 100644
--- a/sched/wqueue/kwork_queue.c
+++ b/sched/wqueue/kwork_queue.c
@@ -88,15 +88,7 @@ int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue,
       return -EINVAL;
     }
 
-  /* delay+1 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
-   * In this case we delay 1 tick, timer will be triggered at
-   * current_tick + 1, which is not enough for at least 1 tick.
-   */
-
-  expected = clock_systime_ticks() + delay + 1;
+  expected = clock_delay2abstick(delay);
 
   /* Interrupts are disabled so that this logic can be called from with
    * task logic or from interrupt handling logic.

Reply via email to