sim: realize sim timer tickless

Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
ligd 2023-02-01 17:43:34 +08:00 committed by Xiang Xiao
parent d082af34f7
commit f102837fe1
4 changed files with 122 additions and 23 deletions

View File

@ -93,29 +93,40 @@ void host_sleepuntil(uint64_t nsec)
* Set up a timer to send periodic signals. * Set up a timer to send periodic signals.
* *
* Input Parameters: * Input Parameters:
* irq - a pointer where we save the host signal number for SIGALRM * nsec - timer expire time
* *
* Returned Value: * Returned Value:
* On success, (0) zero value is returned, otherwise a negative value. * On success, (0) zero value is returned, otherwise a negative value.
* *
****************************************************************************/ ****************************************************************************/
int host_settimer(int *irq) int host_settimer(uint64_t nsec)
{ {
struct itimerval it; struct itimerval it;
if (irq == NULL)
{
return -EINVAL;
}
*irq = SIGALRM;
it.it_interval.tv_sec = 0; it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = CONFIG_USEC_PER_TICK; it.it_interval.tv_usec = 0;
it.it_value = it.it_interval; it.it_value.tv_sec = nsec / 1000000000;
it.it_value.tv_usec = (nsec + 1000) / 1000;
/* Start a host timer at a rate indicated by CONFIG_USEC_PER_TICK */
return setitimer(ITIMER_REAL, &it, NULL); return setitimer(ITIMER_REAL, &it, NULL);
} }
/****************************************************************************
* Name: host_timerirq
*
* Description:
* Get timer irq
*
* Input Parameters:
* None
*
* Returned Value:
* On success, irq num returned, otherwise a negative value.
*
****************************************************************************/
int host_timerirq(void)
{
return SIGALRM;
}

View File

@ -177,7 +177,8 @@ void host_mallinfo(int *aordblks, int *uordblks);
uint64_t host_gettime(bool rtc); uint64_t host_gettime(bool rtc);
void host_sleep(uint64_t nsec); void host_sleep(uint64_t nsec);
void host_sleepuntil(uint64_t nsec); void host_sleepuntil(uint64_t nsec);
int host_settimer(int *irq); int host_timerirq(void);
int host_settimer(uint64_t nsec);
/* sim_sigdeliver.c *********************************************************/ /* sim_sigdeliver.c *********************************************************/

View File

@ -122,6 +122,52 @@ static inline void sim_timer_current(struct timespec *ts)
ts->tv_nsec = nsec; ts->tv_nsec = nsec;
} }
/****************************************************************************
* Name: sim_update_hosttimer
*
* Description:
* Ths function is called periodically to deliver the tick events to the
* NuttX simulation.
*
****************************************************************************/
#ifdef CONFIG_SIM_WALLTIME_SIGNAL
static void sim_update_hosttimer(void)
{
struct timespec *next = NULL;
struct timespec current;
sq_entry_t *entry;
uint64_t nsec;
for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(entry))
{
struct sim_oneshot_lowerhalf_s *priv =
container_of(entry, struct sim_oneshot_lowerhalf_s, link);
if (next == NULL)
{
next = &priv->alarm;
continue;
}
if (clock_timespec_compare(next, &priv->alarm) > 0)
{
next = &priv->alarm;
}
}
sim_timer_current(&current);
clock_timespec_subtract(next, &current, &current);
nsec = current.tv_sec * NSEC_PER_SEC;
nsec += current.tv_nsec;
host_settimer(nsec);
}
#else
# define sim_update_hosttimer()
#endif
/**************************************************************************** /****************************************************************************
* Name: sim_timer_update_internal * Name: sim_timer_update_internal
* *
@ -134,11 +180,18 @@ static inline void sim_timer_current(struct timespec *ts)
static void sim_timer_update_internal(void) static void sim_timer_update_internal(void)
{ {
sq_entry_t *entry; sq_entry_t *entry;
irqstate_t flags;
flags = enter_critical_section();
for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(entry)) for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(entry))
{ {
sim_process_tick(entry); sim_process_tick(entry);
} }
sim_update_hosttimer();
leave_critical_section(flags);
} }
/**************************************************************************** /****************************************************************************
@ -244,15 +297,22 @@ static int sim_start(struct oneshot_lowerhalf_s *lower,
struct sim_oneshot_lowerhalf_s *priv = struct sim_oneshot_lowerhalf_s *priv =
(struct sim_oneshot_lowerhalf_s *)lower; (struct sim_oneshot_lowerhalf_s *)lower;
struct timespec current; struct timespec current;
irqstate_t flags;
DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL); DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL);
flags = enter_critical_section();
sim_timer_current(&current); sim_timer_current(&current);
clock_timespec_add(&current, ts, &priv->alarm); clock_timespec_add(&current, ts, &priv->alarm);
priv->callback = callback; priv->callback = callback;
priv->arg = arg; priv->arg = arg;
sim_update_hosttimer();
leave_critical_section(flags);
return OK; return OK;
} }
@ -286,15 +346,25 @@ static int sim_cancel(struct oneshot_lowerhalf_s *lower,
struct sim_oneshot_lowerhalf_s *priv = struct sim_oneshot_lowerhalf_s *priv =
(struct sim_oneshot_lowerhalf_s *)lower; (struct sim_oneshot_lowerhalf_s *)lower;
struct timespec current; struct timespec current;
irqstate_t flags;
DEBUGASSERT(priv != NULL && ts != NULL); DEBUGASSERT(priv != NULL && ts != NULL);
flags = enter_critical_section();
sim_timer_current(&current); sim_timer_current(&current);
clock_timespec_subtract(&priv->alarm, &current, ts); clock_timespec_subtract(&priv->alarm, &current, ts);
priv->alarm.tv_sec = UINT_MAX;
priv->alarm.tv_nsec = NSEC_PER_SEC - 1;
sim_update_hosttimer();
priv->callback = NULL; priv->callback = NULL;
priv->arg = NULL; priv->arg = NULL;
leave_critical_section(flags);
return OK; return OK;
} }
@ -329,7 +399,7 @@ static int sim_current(struct oneshot_lowerhalf_s *lower,
#ifdef CONFIG_SIM_WALLTIME_SIGNAL #ifdef CONFIG_SIM_WALLTIME_SIGNAL
/**************************************************************************** /****************************************************************************
* Name: sim_alarm_handler * Name: sim_timer_handler
* *
* Description: * Description:
* The signal handler is called periodically and is used to deliver TICK * The signal handler is called periodically and is used to deliver TICK
@ -342,7 +412,7 @@ static int sim_current(struct oneshot_lowerhalf_s *lower,
* *
****************************************************************************/ ****************************************************************************/
static int sim_alarm_handler(int irq, void *context, void *arg) static int sim_timer_handler(int irq, void *context, void *arg)
{ {
sim_timer_update_internal(); sim_timer_update_internal();
return OK; return OK;
@ -408,14 +478,12 @@ struct oneshot_lowerhalf_s *oneshot_initialize(int chan,
void up_timer_initialize(void) void up_timer_initialize(void)
{ {
#ifdef CONFIG_SIM_WALLTIME_SIGNAL #ifdef CONFIG_SIM_WALLTIME_SIGNAL
int host_alarm_irq; int timer_irq = host_timerirq();
host_settimer(&host_alarm_irq);
/* Enable the alarm handler and attach the interrupt to the NuttX logic */ /* Enable the alarm handler and attach the interrupt to the NuttX logic */
up_enable_irq(host_alarm_irq); up_enable_irq(timer_irq);
irq_attach(host_alarm_irq, sim_alarm_handler, NULL); irq_attach(timer_irq, sim_timer_handler, NULL);
#endif #endif
up_alarm_set_lowerhalf(oneshot_initialize(0, 0)); up_alarm_set_lowerhalf(oneshot_initialize(0, 0));

View File

@ -120,14 +120,33 @@ void host_sleepuntil(uint64_t nsec)
* Set up a timer to send periodic signals. * Set up a timer to send periodic signals.
* *
* Input Parameters: * Input Parameters:
* irq - a pointer where we save the host signal number for SIGALRM * nsec - timer expire time
* *
* Returned Value: * Returned Value:
* On success, (0) zero value is returned, otherwise a negative value. * On success, (0) zero value is returned, otherwise a negative value.
* *
****************************************************************************/ ****************************************************************************/
int host_settimer(int *irq) int host_settimer(uint64_t nsec)
{ {
return -ENOSYS; return -ENOSYS;
} }
/****************************************************************************
* Name: host_timerirq
*
* Description:
* Get timer irq
*
* Input Parameters:
* None
*
* Returned Value:
* On success, irq num returned, otherwise a negative value.
*
****************************************************************************/
int host_timerirq(void)
{
return 0;
}