This is an automated email from the ASF dual-hosted git repository.

jerpelea pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 947856efe0eb24988880cfdd69eeb8e0635cd8c5
Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com>
AuthorDate: Fri May 16 16:07:05 2025 +0800

    sched/wdog: Add max delay tick limitation.
    
    This commit changed the type of the delay ticks to the unsigned, which can 
reduce the useless branch conditions
    Besides, this commit added max delay tick limitation to fix incorrect 
timing behavior if we delay SCLOCK_MAX in the SMP build.
    
    Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com>
---
 Documentation/reference/os/time_clock.rst |  2 +-
 include/nuttx/wdog.h                      | 19 ++++++++++++++++---
 sched/wdog/wd_start.c                     |  8 ++++----
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/Documentation/reference/os/time_clock.rst 
b/Documentation/reference/os/time_clock.rst
index 573d5476f4..c9b53defad 100644
--- a/Documentation/reference/os/time_clock.rst
+++ b/Documentation/reference/os/time_clock.rst
@@ -494,7 +494,7 @@ with NuttX tasks.
 - :c:func:`wd_gettime`
 - Watchdog Timer Callback
 
-.. c:function:: int wd_start(FAR struct wdog_s *wdog, int delay, \
+.. c:function:: int wd_start(FAR struct wdog_s *wdog, clock_t delay, \
                  wdentry_t wdentry, wdparm_t arg)
 
   This function adds a watchdog to the timer queue.
diff --git a/include/nuttx/wdog.h b/include/nuttx/wdog.h
index 7ea0a60278..2e36047e34 100644
--- a/include/nuttx/wdog.h
+++ b/include/nuttx/wdog.h
@@ -39,7 +39,20 @@
  ****************************************************************************/
 
 #define WDOG_ISACTIVE(w)   ((w)->func != NULL)
-#define WDOG_MAX_DELAY     ((CLOCK_MAX) / 2 - 1)
+
+/* The maximum delay tick are supposed to be CLOCK_MAX >> 1.
+ * However, if there are expired wdog timers in the wdog queue,
+ * clock_compare might be incorrect when the delay is CLOCK_MAX >> 1.
+ * e.g. Current tick is 123, and there is an expired wdog timer with the
+ * expired ticks 100. If we insert a wdog timer with delay CLOCK_MAX >> 1,
+ * Then clock_compare(100, 123 + CLOCK_MAX >> 1) will return false, leading
+ * to the new wdog timer queued before the expired wdog timer.
+ * So we limited the delay to CLOCK_MAX >> 2, which is 2^30 - 1 or 2^62 - 1.
+ * Assuming all expired wdog timer can be processed within WDOG_MAX_DELAY
+ * ticks, this ensure the correct enqueue of the wdog timer.
+ */
+
+#define WDOG_MAX_DELAY     (CLOCK_MAX >> 2)
 
 /****************************************************************************
  * Public Type Declarations
@@ -141,7 +154,7 @@ extern "C"
  *
  ****************************************************************************/
 
-int wd_start(FAR struct wdog_s *wdog, sclock_t delay,
+int wd_start(FAR struct wdog_s *wdog, clock_t delay,
              wdentry_t wdentry, wdparm_t arg);
 
 /****************************************************************************
@@ -307,7 +320,7 @@ static inline int wd_start_realtime(FAR struct wdog_s *wdog,
  *
  ****************************************************************************/
 
-int wd_start_period(FAR struct wdog_period_s *wdog, sclock_t delay,
+int wd_start_period(FAR struct wdog_period_s *wdog, clock_t delay,
                     clock_t period, wdentry_t wdentry, wdparm_t arg);
 
 /****************************************************************************
diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c
index eed0c34a83..147f3c7a26 100644
--- a/sched/wdog/wd_start.c
+++ b/sched/wdog/wd_start.c
@@ -406,12 +406,12 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t 
ticks,
  *
  ****************************************************************************/
 
-int wd_start(FAR struct wdog_s *wdog, sclock_t delay,
+int wd_start(FAR struct wdog_s *wdog, clock_t delay,
              wdentry_t wdentry, wdparm_t arg)
 {
-  /* Verify the wdog and setup parameters */
+  /* Ensure delay is within the range the wdog can handle. */
 
-  if (delay < 0)
+  if (delay > WDOG_MAX_DELAY)
     {
       return -EINVAL;
     }
@@ -444,7 +444,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay,
  *
  ****************************************************************************/
 
-int wd_start_period(FAR struct wdog_period_s *wdog, sclock_t delay,
+int wd_start_period(FAR struct wdog_period_s *wdog, clock_t delay,
                     clock_t period, wdentry_t wdentry, wdparm_t arg)
 {
   if (!wdog || !period || !wdentry)

Reply via email to