You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/01/10 09:30:33 UTC
(nuttx) 03/04: sched/wdog: Simplify the wdog expiration handling.
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 c69cf36b7c5a7a0f0a3d7419cb2246f91fe1dc84
Author: ouyangxiangzhen <ou...@xiaomi.com>
AuthorDate: Thu Jan 8 11:09:30 2026 +0800
sched/wdog: Simplify the wdog expiration handling.
This commit simplified the wdog expiration handling by introducing the
`g_sched_event` timer.
Signed-off-by: ouyangxiangzhen <ou...@xiaomi.com>
---
sched/sched/sched_timerexpiration.c | 157 ++++++------------------------------
sched/wdog/wd_cancel.c | 11 ++-
sched/wdog/wd_initialize.c | 4 +
sched/wdog/wd_start.c | 60 ++++----------
sched/wdog/wdog.h | 64 ++++++++++++++-
5 files changed, 113 insertions(+), 183 deletions(-)
diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c
index cd3201e8cca..ea25b6e7c16 100644
--- a/sched/sched/sched_timerexpiration.c
+++ b/sched/sched/sched_timerexpiration.c
@@ -78,8 +78,6 @@ static clock_t nxsched_cpu_scheduler(int cpu, clock_t ticks,
#endif
static clock_t nxsched_process_scheduler(clock_t ticks, clock_t elapsed,
bool noswitches);
-static clock_t nxsched_timer_process(clock_t ticks, clock_t elapsed,
- bool noswitches);
static clock_t nxsched_timer_start(clock_t ticks, clock_t interval);
/****************************************************************************
@@ -100,9 +98,9 @@ static clock_t g_timer_tick;
static atomic_t g_timer_interval;
-#ifdef CONFIG_SCHED_TICKLESS
-static unsigned int g_timernested;
-#endif
+/* Wdog timer for scheduler event. */
+
+static struct wdog_s g_sched_event;
/****************************************************************************
* Private Functions
@@ -134,7 +132,7 @@ static inline_function clock_t adjust_next_interval(clock_t interval)
return ret;
}
-static inline_function clock_t get_time_tick(void)
+static inline_function clock_t get_time_tick(void)
{
#ifdef CONFIG_SYSTEM_TIME64
return atomic64_read((FAR atomic64_t *)&g_timer_tick);
@@ -164,58 +162,25 @@ int up_timer_gettick(FAR clock_t *ticks)
}
#endif
-#ifdef CONFIG_SCHED_TICKLESS_ALARM
-static inline_function
-int nxsched_timer_tick_start(clock_t ticks, clock_t delay)
+static void nxsched_process_event(wdparm_t noswitches)
{
-# ifndef CONFIG_ALARM_ARCH
- struct timespec ts;
- clock_ticks2time(&ts, ticks + delay);
- return up_alarm_start(&ts);
-# else
- return up_alarm_tick_start(ticks + delay);
-# endif
-}
+ clock_t ticks;
+ clock_t next;
+ clock_t elapsed;
-static inline_function
-int nxsched_timer_tick_cancel(clock_t *ticks)
-{
- int ret;
-# ifndef CONFIG_ALARM_ARCH
- struct timespec ts;
- ret = up_alarm_cancel(&ts);
- *ticks = clock_time2ticks_floor(&ts);
-# else
- ret = up_alarm_tick_cancel(ticks);
-# endif
- return ret;
-}
+ /* Get the current time. */
-#else
-static inline_function
-int nxsched_timer_tick_start(clock_t ticks, clock_t delay)
-{
-# ifndef CONFIG_TIMER_ARCH
- struct timespec ts;
- clock_ticks2time(&ts, delay);
- return up_timer_start(&ts);
-# else
- return up_timer_tick_start(delay);
-# endif
-}
+ up_timer_gettick(&ticks);
-static inline_function
-int nxsched_timer_tick_cancel(clock_t *ticks)
-{
-# ifndef CONFIG_TIMER_ARCH
- struct timespec ts;
- up_timer_cancel(&ts);
-# else
- up_timer_cancel(ticks);
-# endif
- return up_timer_gettick(ticks);
+ /* Calculate the elapsed time and update clock tickbase. */
+
+ elapsed = ticks - update_time_tick(ticks);
+
+ /* Process the timer ticks and set up the next interval (or not) */
+
+ next = nxsched_process_scheduler(ticks, elapsed, (bool)noswitches);
+ nxsched_timer_start(ticks, next);
}
-#endif
/****************************************************************************
* Name: nxsched_cpu_scheduler
@@ -370,49 +335,6 @@ clock_t nxsched_process_scheduler(clock_t ticks, clock_t elapsed,
return minslice;
}
-/****************************************************************************
- * Name: nxsched_timer_process
- *
- * Description:
- * Process events on timer expiration.
- *
- * Input Parameters:
- * ticks - The number of ticks that have elapsed on the interval timer.
- * noswitches - True: Can't do context switches now.
- *
- * Returned Value:
- * The number of ticks to use when setting up the next timer. CLOCK_MAX if
- * there is no interesting event to be timed.
- *
- ****************************************************************************/
-
-static clock_t nxsched_timer_process(clock_t ticks, clock_t elapsed,
- bool noswitches)
-{
- clock_t sched_next_time;
- clock_t wdog_next_time;
-
-#ifdef CONFIG_CLOCK_TIMEKEEPING
- /* Process wall time */
-
- clock_update_wall_time();
-#endif
-
- /* Check for operations specific to scheduling policy of the currently
- * active task.
- */
-
- sched_next_time = nxsched_process_scheduler(ticks, elapsed, noswitches);
-
- /* Process watchdogs */
-
- wdog_next_time = wd_timer(ticks, noswitches);
-
- /* Select the minimum of the two times. */
-
- return MIN(sched_next_time, wdog_next_time);
-}
-
/****************************************************************************
* Name: nxsched_timer_start
*
@@ -433,27 +355,18 @@ static clock_t nxsched_timer_start(clock_t ticks, clock_t interval)
if (interval != CLOCK_MAX)
{
interval = adjust_next_interval(interval);
- nxsched_timer_tick_start(ticks, interval);
+ wd_start_abstick(&g_sched_event, ticks + interval,
+ nxsched_process_event, 0u);
+ }
+ else
+ {
+ wd_cancel(&g_sched_event);
}
atomic_set(&g_timer_interval, interval);
return interval;
}
-static inline_function
-clock_t nxsched_timer_update(clock_t ticks, bool noswitches)
-{
- clock_t elapsed;
-
- /* Calculate the elapsed time and update clock tickbase. */
-
- elapsed = ticks - update_time_tick(ticks);
-
- /* Process the timer ticks and set up the next interval (or not) */
-
- return nxsched_timer_process(ticks, elapsed, noswitches);
-}
-
/****************************************************************************
* Public Functions
****************************************************************************/
@@ -478,20 +391,12 @@ void nxsched_timer_expiration(void)
{
irqstate_t flags;
clock_t ticks;
- clock_t next;
up_timer_gettick(&ticks);
flags = enter_critical_section();
- /* Get the interval associated with last expiration */
-
- g_timernested++;
-
- next = nxsched_timer_update(ticks, false);
- nxsched_timer_start(ticks, next);
-
- g_timernested--;
+ wd_timer(ticks);
leave_critical_section(flags);
}
@@ -535,17 +440,7 @@ void nxsched_timer_expiration(void)
void nxsched_reassess_timer(void)
{
- clock_t ticks;
- clock_t next;
-
- if (!g_timernested)
- {
- /* Cancel the timer and get the current time */
-
- nxsched_timer_tick_cancel(&ticks);
- next = nxsched_timer_update(ticks, true);
- nxsched_timer_start(ticks, next);
- }
+ nxsched_process_event(1u);
}
/****************************************************************************
diff --git a/sched/wdog/wd_cancel.c b/sched/wdog/wd_cancel.c
index fafd9aa1a53..30fe9130b5c 100644
--- a/sched/wdog/wd_cancel.c
+++ b/sched/wdog/wd_cancel.c
@@ -86,14 +86,21 @@ int wd_cancel(FAR struct wdog_s *wdog)
wdog->func = NULL;
- if (first == wdog)
+ if (first == wdog && !wd_in_callback())
{
/* If the watchdog is at the head of the timer queue, then
* we will need to re-adjust the interval timer that will
* generate the next interval event.
*/
- nxsched_reassess_timer();
+ if (!list_is_empty(&g_wdactivelist))
+ {
+ wd_timer_start(wd_next_expire());
+ }
+ else
+ {
+ wd_timer_cancel();
+ }
}
ret = OK;
diff --git a/sched/wdog/wd_initialize.c b/sched/wdog/wd_initialize.c
index 563ad31c9d9..c2d18193ac3 100644
--- a/sched/wdog/wd_initialize.c
+++ b/sched/wdog/wd_initialize.c
@@ -41,6 +41,10 @@
struct list_node g_wdactivelist = LIST_INITIAL_VALUE(g_wdactivelist);
+#ifdef CONFIG_SCHED_TICKLESS
+bool g_wdtimernested;
+#endif
+
/****************************************************************************
* Public Functions
****************************************************************************/
diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c
index 0e5ce456085..f261125f8c9 100644
--- a/sched/wdog/wd_start.c
+++ b/sched/wdog/wd_start.c
@@ -104,16 +104,18 @@
*
****************************************************************************/
-static inline_function clock_t wd_expiration(clock_t ticks)
+static inline_function void wd_expiration(clock_t ticks)
{
FAR struct wdog_s *wdog;
irqstate_t flags;
wdentry_t func;
wdparm_t arg;
- clock_t ret = CLOCK_MAX;
+ clock_t next_ticks = ticks;
flags = enter_critical_section();
+ wd_set_nested(true);
+
/* Process the watchdog at the head of the list as well as any
* other watchdogs that became ready to run at this time
*/
@@ -128,7 +130,7 @@ static inline_function clock_t wd_expiration(clock_t ticks)
if (!clock_compare(wdog->expired, ticks))
{
- ret = wdog->expired - ticks;
+ next_ticks = wdog->expired;
break;
}
@@ -148,9 +150,14 @@ static inline_function clock_t wd_expiration(clock_t ticks)
CALL_FUNC(func, arg);
}
- leave_critical_section(flags);
+ wd_set_nested(false);
- return ret;
+ if (next_ticks != ticks)
+ {
+ wd_timer_start(wd_next_expire());
+ }
+
+ leave_critical_section(flags);
}
/****************************************************************************
@@ -286,6 +293,7 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks,
}
reassess |= wd_insert(wdog, ticks, wdentry, arg);
+ reassess &= !wd_in_callback();
if (reassess)
{
@@ -294,7 +302,7 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks,
* changed, then this will pick that new delay.
*/
- nxsched_reassess_timer();
+ wd_timer_start(wd_next_expire());
}
#else
UNUSED(reassess);
@@ -331,7 +339,6 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks,
* in the interval that just expired is provided. Otherwise,
* this function is called on each timer interrupt and a value of one
* is implicit.
- * noswitches - True: Can't do context switches now.
*
* Returned Value:
* If CONFIG_SCHED_TICKLESS is defined then the number of ticks for the
@@ -343,48 +350,9 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks,
*
****************************************************************************/
-#ifdef CONFIG_SCHED_TICKLESS
-clock_t wd_timer(clock_t ticks, bool noswitches)
-{
- FAR struct wdog_s *wdog;
- irqstate_t flags;
- clock_t ret;
-
- /* Check if the watchdog at the head of the list is ready to run */
-
- if (!noswitches)
- {
- ret = wd_expiration(ticks);
- }
- else
- {
- ret = CLOCK_MAX;
- flags = enter_critical_section();
-
- /* Return the delay for the next watchdog to expire */
-
- if (!list_is_empty(&g_wdactivelist))
- {
- /* Notice that if noswitches, expired - g_wdtickbase
- * may get negative value.
- */
-
- wdog = list_first_entry(&g_wdactivelist, struct wdog_s, node);
- ret = !clock_compare(wdog->expired, ticks) ?
- wdog->expired - ticks : 0u;
- }
-
- leave_critical_section(flags);
- }
-
- return ret;
-}
-
-#else
void wd_timer(clock_t ticks)
{
/* Check if there are any active watchdogs to process */
wd_expiration(ticks);
}
-#endif /* CONFIG_SCHED_TICKLESS */
diff --git a/sched/wdog/wdog.h b/sched/wdog/wdog.h
index 3993a6eb0e4..efcb61bc23a 100644
--- a/sched/wdog/wdog.h
+++ b/sched/wdog/wdog.h
@@ -36,6 +36,7 @@
#include <nuttx/clock.h>
#include <nuttx/queue.h>
#include <nuttx/wdog.h>
+#include <nuttx/arch.h>
/****************************************************************************
* Pre-processor Definitions
@@ -60,6 +61,65 @@ extern "C"
extern struct list_node g_wdactivelist;
+#ifdef CONFIG_SCHED_TICKLESS
+extern bool g_wdtimernested;
+#endif
+
+/****************************************************************************
+ * Inline functions
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_TICKLESS
+# define wd_in_callback() (g_wdtimernested)
+# define wd_set_nested(f) (g_wdtimernested = (f))
+#else
+# define wd_in_callback() (false)
+# define wd_set_nested(f)
+#endif
+
+#ifdef CONFIG_SCHED_TICKLESS
+static inline_function void wd_timer_start(clock_t next_tick)
+{
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
+# ifndef CONFIG_ALARM_ARCH
+ struct timespec ts;
+ clock_ticks2time(&ts, next_tick);
+ up_alarm_start(&ts);
+# else
+ up_alarm_tick_start(next_tick);
+# endif
+#else
+# ifndef CONFIG_TIMER_ARCH
+ struct timespec ts1;
+ struct timespec ts2;
+ clock_ticks2time(&ts1, next_tick);
+ clock_systime_timespec(&ts2);
+ clock_timespec_subtract(&ts1, &ts2, &ts1);
+ up_timer_start(&ts1);
+# else
+ up_timer_tick_start(next_tick - clock_systime_ticks());
+# endif
+#endif
+}
+static inline_function void wd_timer_cancel(void)
+{
+ struct timespec ts;
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
+ up_alarm_cancel(&ts);
+#else
+ up_timer_cancel(&ts);
+#endif
+}
+#else
+# define wd_timer_start(next_tick)
+# define wd_timer_cancel()
+#endif
+
+static inline_function clock_t wd_next_expire(void)
+{
+ return list_first_entry(&g_wdactivelist, struct wdog_s, node)->expired;
+}
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
@@ -90,11 +150,7 @@ extern struct list_node g_wdactivelist;
*
****************************************************************************/
-#ifdef CONFIG_SCHED_TICKLESS
-clock_t wd_timer(clock_t ticks, bool noswitches);
-#else
void wd_timer(clock_t ticks);
-#endif
#undef EXTERN
#ifdef __cplusplus