From 34442a2fd81a5d781abcfa373a77cc3d4e29910a Mon Sep 17 00:00:00 2001 From: ouyangxiangzhen Date: Thu, 25 Dec 2025 10:10:20 +0800 Subject: [PATCH 1/2] sched: Simplify the interval adjustment in nxsched_timer_start. This commit simplified the interval adjustment in nxsched_timer_start. Signed-off-by: ouyangxiangzhen --- sched/sched/sched_timerexpiration.c | 47 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c index 546fb9f246b48..a231b4ed36e18 100644 --- a/sched/sched/sched_timerexpiration.c +++ b/sched/sched/sched_timerexpiration.c @@ -108,6 +108,32 @@ static unsigned int g_timernested; * Private Functions ****************************************************************************/ +static inline_function clock_t adjust_next_interval(clock_t interval) +{ + clock_t ret = interval; + +#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP + ret = MIN(ret, g_oneshot_maxticks); +#endif + + /* Normally, timer event cannot triggered on exact time due to the + * existence of interrupt latency. + * Assuming that the interrupt latency is distributed within + * [Best-Case Execution Time, Worst-Case Execution Time], + * we can set the timer adjustment value to the BCET to reduce the latency. + * After the adjustment, the timer interrupt latency will be + * [0, WCET - BCET]. + * Please use this carefully, if the timer adjustment value is not the + * best-case interrupt latency, it will immediately fired another timer + * interrupt, which may result in a much larger timer interrupt latency. + */ + + ret = ret <= (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK) ? 0 : + ret - (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK); + + return ret; +} + static inline_function clock_t get_time_tick(void) { #ifdef CONFIG_SYSTEM_TIME64 @@ -390,26 +416,7 @@ static clock_t nxsched_timer_start(clock_t ticks, clock_t interval) if (interval != CLOCK_MAX) { -#ifdef CONFIG_SCHED_TICKLESS_LIMIT_MAX_SLEEP - interval = MIN(interval, g_oneshot_maxticks); -#endif - - /* Normally, timer event cannot triggered on exact time - * due to the existence of interrupt latency. - * Assuming that the interrupt latency is distributed within - * [Best-Case Execution Time, Worst-Case Execution Time], - * we can set the timer adjustment value to the BCET to - * reduce the latency. - * After the adjustment, the timer interrupt latency will be - * [0, WCET - BCET]. - * Please use this carefully, if the timer adjustment value is not - * the best-case interrupt latency, it will immediately fired - * another timer interrupt, which may result in a much larger timer - * interrupt latency. - */ - - interval = interval <= (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK) ? 0 : - interval - (CONFIG_TIMER_ADJUST_USEC / USEC_PER_TICK); + interval = adjust_next_interval(interval); #ifdef CONFIG_SCHED_TICKLESS_ALARM /* Convert the delay to a time in the future (with respect From 0609fb512200e5618ac505271186bbdb1e1adc78 Mon Sep 17 00:00:00 2001 From: ouyangxiangzhen Date: Tue, 23 Dec 2025 16:42:13 +0800 Subject: [PATCH 2/2] sched: Simplify the timer_start/cancel in sched_timerexpiration. This commit simplified the timer_start/cancel in sched_timerexpiration. Signed-off-by: ouyangxiangzhen --- drivers/timers/Kconfig | 2 - drivers/timers/arch_alarm.c | 16 ++++- include/nuttx/arch.h | 16 +---- sched/Kconfig | 20 ------ sched/sched/sched_timerexpiration.c | 103 +++++++++++++--------------- 5 files changed, 65 insertions(+), 92 deletions(-) diff --git a/drivers/timers/Kconfig b/drivers/timers/Kconfig index 8916a22594396..9dcf3c11387ef 100644 --- a/drivers/timers/Kconfig +++ b/drivers/timers/Kconfig @@ -107,7 +107,6 @@ config TIMER_ARCH select ARCH_HAVE_TICKLESS select ARCH_HAVE_TIMEKEEPING select SCHED_TICKLESS_LIMIT_MAX_SLEEP if SCHED_TICKLESS - select SCHED_TICKLESS_TICK_ARGUMENT if SCHED_TICKLESS ---help--- Implement timer arch API on top of timer driver interface. @@ -147,7 +146,6 @@ config ALARM_ARCH select ARCH_HAVE_TIMEKEEPING select SCHED_TICKLESS_ALARM if SCHED_TICKLESS select SCHED_TICKLESS_LIMIT_MAX_SLEEP if SCHED_TICKLESS - select SCHED_TICKLESS_TICK_ARGUMENT if SCHED_TICKLESS ---help--- Implement alarm arch API on top of oneshot driver interface. diff --git a/drivers/timers/arch_alarm.c b/drivers/timers/arch_alarm.c index 46b2c60d06e40..4f04e0d44b66b 100644 --- a/drivers/timers/arch_alarm.c +++ b/drivers/timers/arch_alarm.c @@ -330,6 +330,18 @@ int weak_function up_timer_gettime(struct timespec *ts) ****************************************************************************/ #ifdef CONFIG_SCHED_TICKLESS +int weak_function up_alarm_cancel(FAR struct timespec *ts) +{ + int ret = -EAGAIN; + + if (g_oneshot_lower != NULL) + { + ret = ONESHOT_CANCEL(g_oneshot_lower, ts); + } + + return ret; +} + int weak_function up_alarm_tick_cancel(FAR clock_t *ticks) { int ret = -EAGAIN; @@ -368,7 +380,8 @@ int weak_function up_alarm_tick_cancel(FAR clock_t *ticks) * ****************************************************************************/ -int weak_function up_alarm_start(const struct timespec *ts) +#ifdef CONFIG_SCHED_TICKLESS +int weak_function up_alarm_start(FAR const struct timespec *ts) { int ret = -EAGAIN; @@ -380,7 +393,6 @@ int weak_function up_alarm_start(const struct timespec *ts) return ret; } -#ifdef CONFIG_SCHED_TICKLESS int weak_function up_alarm_tick_start(clock_t ticks) { int ret = -EAGAIN; diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 031c160a783eb..788b4219909fb 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -2002,11 +2002,8 @@ void up_timer_getmask(FAR clock_t *mask); ****************************************************************************/ #if defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM) -# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT int up_alarm_cancel(FAR struct timespec *ts); -# else int up_alarm_tick_cancel(FAR clock_t *ticks); -# endif #endif /**************************************************************************** @@ -2034,12 +2031,9 @@ int up_alarm_tick_cancel(FAR clock_t *ticks); * ****************************************************************************/ -int up_alarm_start(FAR const struct timespec *ts); - #if defined(CONFIG_SCHED_TICKLESS) && defined(CONFIG_SCHED_TICKLESS_ALARM) -# ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT +int up_alarm_start(FAR const struct timespec *ts); int up_alarm_tick_start(clock_t ticks); -# endif #endif /**************************************************************************** @@ -2079,11 +2073,8 @@ int up_alarm_tick_start(clock_t ticks); ****************************************************************************/ #if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM) -# ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT int up_timer_cancel(FAR struct timespec *ts); -# else int up_timer_tick_cancel(FAR clock_t *ticks); -# endif #endif /**************************************************************************** @@ -2111,12 +2102,9 @@ int up_timer_tick_cancel(FAR clock_t *ticks); * ****************************************************************************/ -int up_timer_start(FAR const struct timespec *ts); - #if defined(CONFIG_SCHED_TICKLESS) && !defined(CONFIG_SCHED_TICKLESS_ALARM) -# ifdef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT +int up_timer_start(FAR const struct timespec *ts); int up_timer_tick_start(clock_t ticks); -# endif #endif /**************************************************************************** diff --git a/sched/Kconfig b/sched/Kconfig index 5370be5e5fa1d..e4c021265c815 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -73,26 +73,6 @@ config SCHED_TICKLESS if SCHED_TICKLESS -config SCHED_TICKLESS_TICK_ARGUMENT - bool "Scheduler use tick argument" - default n - ---help--- - Enables use of tick argument in scheduler. If enabled, then the - board-specific logic must provide the following functions: - - int up_timer_gettick(FAR clock_t *ticks); - - If SCHED_TICKLESS_ALARM is enabled, then these additional interfaces are - expected: - - int up_alarm_tick_cancel(FAR clock_t *ticks); - int up_alarm_tick_start(clock_t ticks); - - Otherwise, these additional interfaces are expected: - - int up_timer_tick_cancel(FAR clock_t *ticks); - int up_timer_tick_start(clock_t ticks); - config SCHED_TICKLESS_ALARM bool "Tickless alarm" default n diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c index a231b4ed36e18..cd3201e8cca0c 100644 --- a/sched/sched/sched_timerexpiration.c +++ b/sched/sched/sched_timerexpiration.c @@ -152,7 +152,8 @@ static inline_function clock_t update_time_tick(clock_t tick) #endif } -#if !defined(CONFIG_SCHED_TICKLESS_TICK_ARGUMENT) && !defined(CONFIG_CLOCK_TIMEKEEPING) +#if !defined(CONFIG_CLOCK_TIMEKEEPING) && !defined(CONFIG_ALARM_ARCH) && \ + !defined(CONFIG_TIMER_ARCH) int up_timer_gettick(FAR clock_t *ticks) { struct timespec ts; @@ -163,40 +164,57 @@ int up_timer_gettick(FAR clock_t *ticks) } #endif -#ifndef CONFIG_SCHED_TICKLESS_TICK_ARGUMENT -# ifdef CONFIG_SCHED_TICKLESS_ALARM -int up_alarm_tick_start(clock_t ticks) +#ifdef CONFIG_SCHED_TICKLESS_ALARM +static inline_function +int nxsched_timer_tick_start(clock_t ticks, clock_t delay) { +# ifndef CONFIG_ALARM_ARCH struct timespec ts; - clock_ticks2time(&ts, ticks); + clock_ticks2time(&ts, ticks + delay); return up_alarm_start(&ts); +# else + return up_alarm_tick_start(ticks + delay); +# endif } -int up_alarm_tick_cancel(FAR clock_t *ticks) +static inline_function +int nxsched_timer_tick_cancel(clock_t *ticks) { + int ret; +# ifndef CONFIG_ALARM_ARCH struct timespec ts; - int ret; - ret = up_alarm_cancel(&ts); + ret = up_alarm_cancel(&ts); *ticks = clock_time2ticks_floor(&ts); +# else + ret = up_alarm_tick_cancel(ticks); +# endif return ret; } -# else -int up_timer_tick_start(clock_t ticks) + +#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, ticks); + clock_ticks2time(&ts, delay); return up_timer_start(&ts); +# else + return up_timer_tick_start(delay); +# endif } -int up_timer_tick_cancel(FAR clock_t *ticks) +static inline_function +int nxsched_timer_tick_cancel(clock_t *ticks) { +# ifndef CONFIG_TIMER_ARCH struct timespec ts; - int ret; - ret = up_timer_cancel(&ts); - *ticks = clock_time2ticks_floor(&ts); - return ret; -} + up_timer_cancel(&ts); +# else + up_timer_cancel(ticks); # endif + return up_timer_gettick(ticks); +} #endif /**************************************************************************** @@ -412,29 +430,10 @@ static clock_t nxsched_timer_process(clock_t ticks, clock_t elapsed, static clock_t nxsched_timer_start(clock_t ticks, clock_t interval) { - int ret; - if (interval != CLOCK_MAX) { interval = adjust_next_interval(interval); - -#ifdef CONFIG_SCHED_TICKLESS_ALARM - /* Convert the delay to a time in the future (with respect - * to the time when last stopped the timer). - */ - - ret = up_alarm_tick_start(ticks + interval); -#else - /* [Re-]start the interval timer */ - - ret = up_timer_tick_start(interval); -#endif - - if (ret < 0) - { - serr("ERROR: up_timer_start/up_alarm_start failed: %d\n", ret); - UNUSED(ret); - } + nxsched_timer_tick_start(ticks, interval); } atomic_set(&g_timer_interval, interval); @@ -444,7 +443,6 @@ static clock_t nxsched_timer_start(clock_t ticks, clock_t interval) static inline_function clock_t nxsched_timer_update(clock_t ticks, bool noswitches) { - clock_t nexttime; clock_t elapsed; /* Calculate the elapsed time and update clock tickbase. */ @@ -453,9 +451,7 @@ clock_t nxsched_timer_update(clock_t ticks, bool noswitches) /* Process the timer ticks and set up the next interval (or not) */ - nexttime = nxsched_timer_process(ticks, elapsed, noswitches); - - return nxsched_timer_start(ticks, nexttime); + return nxsched_timer_process(ticks, elapsed, noswitches); } /**************************************************************************** @@ -480,16 +476,20 @@ clock_t nxsched_timer_update(clock_t ticks, bool noswitches) void nxsched_timer_expiration(void) { + irqstate_t flags; clock_t ticks; - irqstate_t flags = enter_critical_section(); + clock_t next; + + up_timer_gettick(&ticks); + + flags = enter_critical_section(); /* Get the interval associated with last expiration */ g_timernested++; - up_timer_gettick(&ticks); - - nxsched_timer_update(ticks, false); + next = nxsched_timer_update(ticks, false); + nxsched_timer_start(ticks, next); g_timernested--; @@ -536,20 +536,15 @@ 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 */ -#ifdef CONFIG_SCHED_TICKLESS_ALARM - up_alarm_tick_cancel(&ticks); -#else - clock_t elapsed; - up_timer_gettick(&ticks); - up_timer_tick_cancel(&elapsed); -#endif - - nxsched_timer_update(ticks, true); + nxsched_timer_tick_cancel(&ticks); + next = nxsched_timer_update(ticks, true); + nxsched_timer_start(ticks, next); } }