diff --git a/Documentation/reference/os/time_clock.rst b/Documentation/reference/os/time_clock.rst index 573d5476f49..c9b53defad5 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 7ea0a602781..2e36047e341 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 eed0c34a839..147f3c7a269 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)