mirror of
https://github.com/apache/nuttx.git
synced 2026-03-23 14:05:12 +08:00
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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user