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

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

commit 3eedf5f22bd283e966f50dbc2d654bb2db1bce1c
Author: ouyangxiangzhen <[email protected]>
AuthorDate: Wed Jan 28 16:26:54 2026 +0800

    sched/wdog: Simplify timer expiration for hrtimer.
    
    This commit simplified the timer expiration for hrtimer.
    
    Signed-off-by: ouyangxiangzhen <[email protected]>
---
 drivers/timers/arch_alarm.c                        |   2 +-
 sched/hrtimer/hrtimer.h                            |  13 +-
 sched/sched/CMakeLists.txt                         |   5 +-
 sched/sched/Make.defs                              |   4 +-
 sched/sched/sched_processtick.c                    |   9 +-
 ...ed_tickexpiration.c => sched_processtickless.c} |   9 +-
 sched/sched/sched_timer.c                          | 154 ---------------------
 sched/wdog/wd_cancel.c                             |   2 +-
 sched/wdog/wd_initialize.c                         |   6 +-
 sched/wdog/wd_start.c                              |  22 ++-
 sched/wdog/wdog.h                                  | 102 +++++++++-----
 11 files changed, 118 insertions(+), 210 deletions(-)

diff --git a/drivers/timers/arch_alarm.c b/drivers/timers/arch_alarm.c
index dbb44a267df..8c0140bc2a3 100644
--- a/drivers/timers/arch_alarm.c
+++ b/drivers/timers/arch_alarm.c
@@ -126,7 +126,7 @@ static void ndelay_accurate(unsigned long nanoseconds)
 static void oneshot_callback(FAR struct oneshot_lowerhalf_s *lower,
                              FAR void *arg)
 {
-#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_HRTIMER)
+#if defined(CONFIG_SCHED_TICKLESS)
   nxsched_process_timer();
 #else
   clock_t now;
diff --git a/sched/hrtimer/hrtimer.h b/sched/hrtimer/hrtimer.h
index eea66bef28e..478ff90a88a 100644
--- a/sched/hrtimer/hrtimer.h
+++ b/sched/hrtimer/hrtimer.h
@@ -145,21 +145,28 @@ void hrtimer_process(uint64_t now);
 
 static inline_function void hrtimer_reprogram(uint64_t next_expired)
 {
+  /* `hrtimer_reprogram` relies on the underlying timer being a non-periodic
+   * timer. If the underlying timer hardware is a periodic timer like
+   * systick, we cannot set the next expiration time.
+   */
+
+#ifdef CONFIG_SCHED_TICKLESS
   int ret = 0;
   struct timespec ts;
 
   clock_nsec2time(&ts, next_expired);
 
-#ifdef CONFIG_ALARM_ARCH
+#  ifdef CONFIG_ALARM_ARCH
   ret = up_alarm_start(&ts);
-#else
+#  else
   struct timespec current;
   up_timer_gettime(&current);
   clock_timespec_subtract(&ts, &current, &ts);
   ret = up_timer_start(&ts);
-#endif
+#  endif
 
   DEBUGASSERT(ret == 0);
+#endif
 }
 
 /****************************************************************************
diff --git a/sched/sched/CMakeLists.txt b/sched/sched/CMakeLists.txt
index 14c731bdcca..be709a4ecb0 100644
--- a/sched/sched/CMakeLists.txt
+++ b/sched/sched/CMakeLists.txt
@@ -48,8 +48,7 @@ set(SRCS
     sched_sysinfo.c
     sched_get_stateinfo.c
     sched_switchcontext.c
-    sched_sleep.c
-    sched_timer.c)
+    sched_sleep.c)
 
 if(DEFINED CONFIG_STACKCHECK_MARGIN)
   if(NOT CONFIG_STACKCHECK_MARGIN EQUAL -1)
@@ -98,7 +97,7 @@ if(NOT CONFIG_SCHED_CPULOAD_NONE)
 endif()
 
 if(CONFIG_SCHED_TICKLESS)
-  list(APPEND SRCS sched_tickexpiration.c)
+  list(APPEND SRCS sched_processtickless.c)
 else()
   list(APPEND SRCS sched_processtick.c)
 endif()
diff --git a/sched/sched/Make.defs b/sched/sched/Make.defs
index 3bb641e84df..1aae136ecec 100644
--- a/sched/sched/Make.defs
+++ b/sched/sched/Make.defs
@@ -30,7 +30,7 @@ CSRCS += sched_yield.c sched_rrgetinterval.c sched_foreach.c
 CSRCS += sched_lock.c sched_unlock.c sched_lockcount.c
 CSRCS += sched_idletask.c sched_self.c sched_get_stackinfo.c sched_get_tls.c
 CSRCS += sched_sysinfo.c sched_get_stateinfo.c sched_getcpu.c
-CSRCS += sched_switchcontext.c sched_sleep.c sched_timer.c
+CSRCS += sched_switchcontext.c sched_sleep.c
 
 ifneq ($(CONFIG_STACKCHECK_MARGIN),)
   ifneq ($(CONFIG_STACKCHECK_MARGIN),-1)
@@ -79,7 +79,7 @@ endif
 endif
 
 ifeq ($(CONFIG_SCHED_TICKLESS),y)
-CSRCS += sched_tickexpiration.c
+CSRCS += sched_processtickless.c
 else
 CSRCS += sched_processtick.c
 endif
diff --git a/sched/sched/sched_processtick.c b/sched/sched/sched_processtick.c
index 7457f556bd5..44d3d169a54 100644
--- a/sched/sched/sched_processtick.c
+++ b/sched/sched/sched_processtick.c
@@ -43,6 +43,7 @@
 
 #include "sched/sched.h"
 #include "wdog/wdog.h"
+#include "hrtimer/hrtimer.h"
 #include "clock/clock.h"
 
 /****************************************************************************
@@ -146,7 +147,7 @@ static inline void nxsched_process_scheduler(void)
 #endif
 
 /****************************************************************************
- * Name:  nxsched_process_tick
+ * Name:  nxsched_process_timer
  *
  * Description:
  *   This function handles system timer events.
@@ -165,7 +166,7 @@ static inline void nxsched_process_scheduler(void)
  *
  ****************************************************************************/
 
-void nxsched_process_tick(void)
+void nxsched_process_timer(void)
 {
 #ifdef CONFIG_CLOCK_TIMEKEEPING
   /* Process wall time */
@@ -185,7 +186,11 @@ void nxsched_process_tick(void)
 
   /* Process watchdogs */
 
+#ifdef CONFIG_HRTIMER
+  hrtimer_process(clock_systime_nsec());
+#else
   wd_timer(clock_systime_ticks());
+#endif
 
 #ifdef CONFIG_SYSTEMTICK_HOOK
   /* Call out to a user-provided function in order to perform board-specific,
diff --git a/sched/sched/sched_tickexpiration.c 
b/sched/sched/sched_processtickless.c
similarity index 98%
rename from sched/sched/sched_tickexpiration.c
rename to sched/sched/sched_processtickless.c
index afbc05fcad3..6778607f27a 100644
--- a/sched/sched/sched_tickexpiration.c
+++ b/sched/sched/sched_processtickless.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/sched/sched_tickexpiration.c
+ * sched/sched/sched_processtickless.c
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -39,6 +39,7 @@
 
 #include "sched/sched.h"
 #include "wdog/wdog.h"
+#include "hrtimer/hrtimer.h"
 #include "clock/clock.h"
 
 #ifdef CONFIG_CLOCK_TIMEKEEPING
@@ -362,8 +363,11 @@ static void nxsched_timer_start(clock_t ticks, clock_t 
interval)
  *
  ****************************************************************************/
 
-void nxsched_process_tick(void)
+void nxsched_process_timer(void)
 {
+#ifdef CONFIG_HRTIMER
+  hrtimer_process(clock_systime_nsec());
+#else
   irqstate_t flags;
   clock_t ticks;
 
@@ -389,6 +393,7 @@ void nxsched_process_tick(void)
   wd_timer(ticks);
 
   leave_critical_section(flags);
+#endif
 }
 
 /****************************************************************************
diff --git a/sched/sched/sched_timer.c b/sched/sched/sched_timer.c
deleted file mode 100644
index e59b60debd0..00000000000
--- a/sched/sched/sched_timer.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/****************************************************************************
- * sched/sched/sched_timer.c
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- ****************************************************************************/
-
-/****************************************************************************
- * Included Files
- ****************************************************************************/
-
-#include <nuttx/config.h>
-#include <nuttx/arch.h>
-#include <nuttx/clock.h>
-
-#include <errno.h>
-
-#include "sched/sched.h"
-#include "hrtimer/hrtimer.h"
-
-/****************************************************************************
- * Private Data
- ****************************************************************************/
-
-/* High-resolution timer used to drive the scheduler tick.
- *
- * In non-tickless mode, this timer periodically generates a scheduler
- * tick with interval NSEC_PER_TICK.
- *
- * In tickless mode, the timer is still used, but the callback does not
- * request automatic re-arming.
- */
-
-#ifdef CONFIG_HRTIMER
-static hrtimer_t g_sched_hrtimer;
-static bool g_sched_hrtimer_started = false;
-#endif
-
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
-
-/****************************************************************************
- * Name: nxsched_hrtimer_callback
- *
- * Description:
- *   High-resolution timer callback used to drive the scheduler.
- *
- *   This callback is invoked when the scheduler hrtimer expires.
- *   It advances the scheduler time base by calling
- *   nxsched_process_tick().
- *
- * Input Parameters:
- *   hrtimer - Pointer to the expired hrtimer instance
- *   expired - Expiration time in nanoseconds
- *
- * Returned Value:
- *   In non-tickless mode:
- *     Returns the next expiration interval (NSEC_PER_TICK),
- *     causing the hrtimer to be re-armed periodically.
- *
- *   In tickless mode:
- *     Returns 0 to indicate that the timer should not be
- *     automatically restarted.
- *
- ****************************************************************************/
-
-#ifdef CONFIG_HRTIMER
-static uint64_t
-nxsched_hrtimer_callback(FAR const struct hrtimer_s *hrtimer,
-                         uint64_t expired)
-{
-  UNUSED(hrtimer);
-  UNUSED(expired);
-
-  /* Advance scheduler time and process time slice expiration */
-
-  nxsched_process_tick();
-
-#ifndef CONFIG_SCHED_TICKLESS
-  /* Periodic tick mode: re-arm timer with fixed tick interval */
-
-  return NSEC_PER_TICK;
-#else
-  /* Tickless mode controls the next wakeup explicitly */
-
-  return 0;
-#endif
-}
-#endif
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
-#if defined(CONFIG_HRTIMER) && defined(CONFIG_SCHED_TICKLESS)
-int nxsched_hrtimer_tick_start(clock_t tick)
-{
-  return hrtimer_start(&g_sched_hrtimer,
-                       nxsched_hrtimer_callback,
-                       tick * NSEC_PER_TICK,
-                       HRTIMER_MODE_ABS);
-}
-#endif
-
-/****************************************************************************
- * Name: nxsched_process_timer
- *
- * Description:
- *   Process scheduler timing events.
- *
- *   If high-resolution timers are enabled, this function dispatches
- *   expired hrtimers based on the current hrtimer time.
- *
- *   Otherwise, it falls back to directly processing a scheduler tick.
- *
- ****************************************************************************/
-
-void nxsched_process_timer(void)
-{
-#ifdef CONFIG_HRTIMER
-  /* Process all expired high-resolution timers */
-
-  if (g_sched_hrtimer_started == false)
-    {
-      g_sched_hrtimer_started = true;
-      hrtimer_start(&g_sched_hrtimer,
-                    nxsched_hrtimer_callback,
-                    NSEC_PER_TICK,
-                    HRTIMER_MODE_REL);
-    }
-
-  hrtimer_process(clock_systime_nsec());
-#else
-  /* Fallback: process one scheduler tick */
-
-  nxsched_process_tick();
-#endif
-}
diff --git a/sched/wdog/wd_cancel.c b/sched/wdog/wd_cancel.c
index 30fe9130b5c..1a8202e403b 100644
--- a/sched/wdog/wd_cancel.c
+++ b/sched/wdog/wd_cancel.c
@@ -95,7 +95,7 @@ int wd_cancel(FAR struct wdog_s *wdog)
 
               if (!list_is_empty(&g_wdactivelist))
                 {
-                  wd_timer_start(wd_next_expire());
+                  wd_timer_start(wd_next_expire(), false);
                 }
               else
                 {
diff --git a/sched/wdog/wd_initialize.c b/sched/wdog/wd_initialize.c
index 779fea13a86..40cff0e6903 100644
--- a/sched/wdog/wd_initialize.c
+++ b/sched/wdog/wd_initialize.c
@@ -41,7 +41,11 @@
 
 struct list_node g_wdactivelist = LIST_INITIAL_VALUE(g_wdactivelist);
 
-#ifdef CONFIG_SCHED_TICKLESS
+#ifdef CONFIG_HRTIMER
+struct hrtimer_s g_wdtimer;
+#endif
+
+#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_HRTIMER)
 bool g_wdtimernested;
 clock_t  g_wdexpired;
 #endif
diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c
index 10e16545a30..afdfc1cdaee 100644
--- a/sched/wdog/wd_start.c
+++ b/sched/wdog/wd_start.c
@@ -104,7 +104,7 @@
  *
  ****************************************************************************/
 
-static inline_function void wd_expiration(clock_t ticks)
+static inline_function clock_t wd_expiration(clock_t ticks)
 {
   FAR struct wdog_s *wdog;
   irqstate_t         flags;
@@ -156,10 +156,12 @@ static inline_function void wd_expiration(clock_t ticks)
 
   if (next_ticks != ticks)
     {
-      wd_timer_start(next_ticks);
+      wd_timer_start(next_ticks, true);
     }
 
   leave_critical_section(flags);
+
+  return next_ticks;
 }
 
 /****************************************************************************
@@ -283,7 +285,7 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks,
 
       /* If the wdog is canceling, restarting the wdog is not allowed. */
 
-#ifdef CONFIG_SCHED_TICKLESS
+#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_HRTIMER)
       /* We need to reassess timer if the watchdog
        * list head has changed.
        */
@@ -304,7 +306,7 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t ticks,
            * changed, then this will pick that new delay.
            */
 
-          wd_timer_start(wd_next_expire());
+          wd_timer_start(wd_next_expire(), false);
         }
 #else
       UNUSED(reassess);
@@ -352,9 +354,21 @@ int wd_start_abstick(FAR struct wdog_s *wdog, clock_t 
ticks,
  *
  ****************************************************************************/
 
+#ifndef CONFIG_HRTIMER
 void wd_timer(clock_t ticks)
 {
   /* Check if there are any active watchdogs to process */
 
   wd_expiration(ticks);
 }
+#else
+uint64_t wd_timer(const hrtimer_t *timer, uint64_t expired)
+{
+  /* Check if there are any active watchdogs to process */
+
+  clock_t  tick = div_const(expired, NSEC_PER_TICK);
+  clock_t delay = wd_expiration(tick) - tick;
+  uint64_t nsec = TICK2NSEC((uint64_t)delay);
+  return nsec <= HRTIMER_MAX_DELAY ? nsec : HRTIMER_MAX_DELAY;
+}
+#endif
diff --git a/sched/wdog/wdog.h b/sched/wdog/wdog.h
index 41ed4807fa4..8303e6bb35a 100644
--- a/sched/wdog/wdog.h
+++ b/sched/wdog/wdog.h
@@ -38,6 +38,10 @@
 #include <nuttx/wdog.h>
 #include <nuttx/arch.h>
 
+#ifdef CONFIG_HRTIMER
+#  include <nuttx/hrtimer.h> 
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -61,16 +65,56 @@ extern "C"
 
 extern struct list_node g_wdactivelist;
 
-#ifdef CONFIG_SCHED_TICKLESS
+#ifdef CONFIG_HRTIMER
+extern struct hrtimer_s g_wdtimer;
+#endif
+
+#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_HRTIMER)
 extern bool g_wdtimernested;
 extern clock_t  g_wdexpired;
 #endif
 
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: wd_timer
+ *
+ * Description:
+ *   This function is called from the timer interrupt handler to determine
+ *   if it is time to execute a watchdog function.  If so, the watchdog
+ *   function will be executed in the context of the timer interrupt
+ *   handler.
+ *
+ * Input Parameters:
+ *   ticks - If CONFIG_SCHED_TICKLESS is defined then the number of 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
+ *   next delay is provided (zero if no delay).  Otherwise, this function
+ *   has no returned value.
+ *
+ * Assumptions:
+ *   Called from interrupt handler logic with interrupts disabled.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_HRTIMER
+void wd_timer(clock_t ticks);
+#else
+uint64_t wd_timer(const hrtimer_t *timer, uint64_t expired);
+#endif
+
 /****************************************************************************
  * Inline functions
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_TICKLESS
+#if defined(CONFIG_SCHED_TICKLESS) || defined(CONFIG_HRTIMER)
 #  define wd_in_callback()          (g_wdtimernested)
 #  define wd_set_nested(f)          (g_wdtimernested = (f))
 #  define wd_update_expire(expired) (g_wdexpired = (expired))
@@ -80,7 +124,22 @@ extern clock_t  g_wdexpired;
 #  define wd_update_expire(expired)
 #endif
 
-#ifdef CONFIG_SCHED_TICKLESS
+#ifdef CONFIG_HRTIMER
+static inline_function void wd_timer_start(clock_t tick, bool in_expiration)
+{
+  DEBUGASSERT((uint64_t)tick <= UINT64_MAX / NSEC_PER_TICK);
+  if (!in_expiration)
+    {
+      hrtimer_start(&g_wdtimer, wd_timer,
+                    TICK2NSEC((uint64_t)tick), HRTIMER_MODE_ABS);
+    }
+}
+
+static inline_function void wd_timer_cancel(void)
+{
+  hrtimer_cancel(&g_wdtimer);
+}
+#elif defined(CONFIG_SCHED_TICKLESS)
 static inline_function clock_t wd_adjust_next_tick(clock_t tick)
 {
   clock_t next_tick = tick;
@@ -111,13 +170,10 @@ static inline_function clock_t 
wd_adjust_next_tick(clock_t tick)
   return next_tick;
 }
 
-static inline_function void wd_timer_start(clock_t tick)
+static inline_function void wd_timer_start(clock_t tick, bool in_expiration)
 {
   clock_t next_tick = wd_adjust_next_tick(tick);
-
-#ifdef CONFIG_HRTIMER
-  nxsched_hrtimer_tick_start(tick);
-#elif defined(CONFIG_SCHED_TICKLESS_ALARM)
+#ifdef CONFIG_SCHED_TICKLESS_ALARM
   up_alarm_tick_start(next_tick);
 #else
   up_timer_tick_start(next_tick - clock_systime_ticks());
@@ -134,7 +190,7 @@ static inline_function void wd_timer_cancel(void)
 #endif
 }
 #else
-#  define wd_timer_start(next_tick)
+#  define wd_timer_start(next_tick, in_expiration)
 #  define wd_timer_cancel()
 #endif
 
@@ -161,34 +217,6 @@ static inline_function clock_t wd_get_next_expire(clock_t 
curr)
   return (sclock_t)(next - curr) <= 0 ? 0u : next;
 }
 
-/****************************************************************************
- * Name: wd_timer
- *
- * Description:
- *   This function is called from the timer interrupt handler to determine
- *   if it is time to execute a watchdog function.  If so, the watchdog
- *   function will be executed in the context of the timer interrupt
- *   handler.
- *
- * Input Parameters:
- *   ticks - If CONFIG_SCHED_TICKLESS is defined then the number of 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
- *   next delay is provided (zero if no delay).  Otherwise, this function
- *   has no returned value.
- *
- * Assumptions:
- *   Called from interrupt handler logic with interrupts disabled.
- *
- ****************************************************************************/
-
-void wd_timer(clock_t ticks);
-
 #undef EXTERN
 #ifdef __cplusplus
 }

Reply via email to