sched/tickless: Fix CLOCK_MONOTONIC always 0 by updating sched ticks

Fix the issue where clock_gettime(CLOCK_MONOTONIC) always returns 0 in
tickless mode, caused by the scheduler tick counter (g_system_ticks) not
being updated with the actual timer ticks.

1. Add clock_update_sched_ticks() function to sched/clock/clock_sched_ticks.c:
  a. This function directly sets the system tick counter to a specific value
     (vs incrementing in clock_increase_sched_ticks), with full documentation
     matching the existing code style.
  b. Uses seqlock to ensure thread-safe access to g_system_ticks.

2. Call clock_update_sched_ticks() in nxsched_process_timer() (sched_processtickless.c):

  a. Syncs the scheduler tick counter with the actual timer ticks retrieved via up_timer_gettick().

With this fix, g_system_ticks is properly updated in tickless mode,
and clock_gettime(CLOCK_MONOTONIC) returns the correct non-zero monotonic time.

Signed-off-by: chao an <anchao.archer@bytedance.com>
This commit is contained in:
chao an
2026-03-03 17:47:40 +08:00
committed by Matteo Golin
parent 1845cb05f1
commit d8b4d53444
3 changed files with 110 additions and 1 deletions

View File

@@ -70,15 +70,88 @@ extern spinlock_t g_basetime_lock;
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: clock_basetime
*
* Description:
* Get the initial time value from the best source available.
*
****************************************************************************/
int clock_basetime(FAR struct timespec *tp);
/****************************************************************************
* Name: clock_initialize
*
* Description:
* Perform one-time initialization of the timing facilities.
*
****************************************************************************/
void clock_initialize(void);
/****************************************************************************
* Name: clock_update_sched_ticks
*
* Description:
* Update the scheduler tick counter to a specific value. This function
* directly sets the system tick counter to the given value (rather than
* incrementing it), typically used for synchronizing or resetting the
* scheduler tick count to a known state.
*
* Input Parameters:
* ticks - The new value to set for the scheduler tick counter
*
* Returned Value:
* None
*
****************************************************************************/
void clock_update_sched_ticks(clock_t ticks);
/****************************************************************************
* Name: clock_increase_sched_ticks
*
* Description:
* Increment the scheduler tick counter. This function should be called
* each time the real-time clock interrupt occurs, indicating the passage
* of one or more scheduling ticks.
*
* Input Parameters:
* ticks - The number of ticks to increment (typically 1)
*
* Returned Value:
* None
*
****************************************************************************/
void clock_increase_sched_ticks(clock_t ticks);
/****************************************************************************
* Name: clock_get_sched_ticks
*
* Description:
* Return the current value of the scheduler tick counter. This counter
* only increases while the scheduler is running, and is independent of
* the real-time clock.
*
* Returned Value:
* The current number of scheduler ticks.
*
****************************************************************************/
clock_t clock_get_sched_ticks(void);
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
/****************************************************************************
* Name: cpuload_init
*
* Description:
* Initialize the CPU load measurement logic.
*
****************************************************************************/
void cpuload_init(void);
#endif

View File

@@ -46,6 +46,34 @@ static seqcount_t g_system_tick_lock = SEQLOCK_INITIALIZER;
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: clock_update_sched_ticks
*
* Description:
* Update the scheduler tick counter to a specific value. This function
* directly sets the system tick counter to the given value (rather than
* incrementing it), typically used for synchronizing or resetting the
* scheduler tick count to a known state.
*
* Input Parameters:
* ticks - The new value to set for the scheduler tick counter
*
* Returned Value:
* None
*
****************************************************************************/
void clock_update_sched_ticks(clock_t ticks)
{
irqstate_t flags;
/* Increment the per-tick scheduler counter */
flags = write_seqlock_irqsave(&g_system_tick_lock);
g_system_ticks = ticks;
write_sequnlock_irqrestore(&g_system_tick_lock, flags);
}
/****************************************************************************
* Name: clock_increase_sched_ticks
*

View File

@@ -375,13 +375,17 @@ void nxsched_process_timer(void)
{
#ifdef CONFIG_HRTIMER
uint64_t nsec = clock_systime_nsec();
clock_t ticks = NSEC2TICK(nsec);
clock_update_sched_ticks(ticks);
hrtimer_process(nsec);
# if CONFIG_RR_INTERVAL > 0
/* Workaround for SCHED_RR, see the note. */
irqstate_t flags = enter_critical_section();
nxsched_process_event(div_const(nsec, (uint32_t)NSEC_PER_TICK), true);
nxsched_process_event(ticks, true);
leave_critical_section(flags);
# endif
@@ -397,6 +401,10 @@ void nxsched_process_timer(void)
up_timer_gettick(&ticks);
/* Update sched ticks */
clock_update_sched_ticks(ticks);
#if CONFIG_RR_INTERVAL > 0
/* Workaround for SCHED_RR, see the note. */