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.
*
* Input Parameters:
* irq - a pointer where we save the host signal number for SIGALRM
* nsec - timer expire time
*
* Returned 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;
if (irq == NULL)
{
return -EINVAL;
}
*irq = SIGALRM;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = CONFIG_USEC_PER_TICK;
it.it_value = it.it_interval;
/* Start a host timer at a rate indicated by CONFIG_USEC_PER_TICK */
it.it_interval.tv_usec = 0;
it.it_value.tv_sec = nsec / 1000000000;
it.it_value.tv_usec = (nsec + 1000) / 1000;
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);
void host_sleep(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 *********************************************************/

View File

@ -122,6 +122,52 @@ static inline void sim_timer_current(struct timespec *ts)
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
*
@ -134,11 +180,18 @@ static inline void sim_timer_current(struct timespec *ts)
static void sim_timer_update_internal(void)
{
sq_entry_t *entry;
irqstate_t flags;
flags = enter_critical_section();
for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(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 *)lower;
struct timespec current;
irqstate_t flags;
DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL);
flags = enter_critical_section();
sim_timer_current(&current);
clock_timespec_add(&current, ts, &priv->alarm);
priv->callback = callback;
priv->arg = arg;
sim_update_hosttimer();
leave_critical_section(flags);
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 *)lower;
struct timespec current;
irqstate_t flags;
DEBUGASSERT(priv != NULL && ts != NULL);
flags = enter_critical_section();
sim_timer_current(&current);
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->arg = NULL;
leave_critical_section(flags);
return OK;
}
@ -329,7 +399,7 @@ static int sim_current(struct oneshot_lowerhalf_s *lower,
#ifdef CONFIG_SIM_WALLTIME_SIGNAL
/****************************************************************************
* Name: sim_alarm_handler
* Name: sim_timer_handler
*
* Description:
* 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();
return OK;
@ -408,14 +478,12 @@ struct oneshot_lowerhalf_s *oneshot_initialize(int chan,
void up_timer_initialize(void)
{
#ifdef CONFIG_SIM_WALLTIME_SIGNAL
int host_alarm_irq;
host_settimer(&host_alarm_irq);
int timer_irq = host_timerirq();
/* Enable the alarm handler and attach the interrupt to the NuttX logic */
up_enable_irq(host_alarm_irq);
irq_attach(host_alarm_irq, sim_alarm_handler, NULL);
up_enable_irq(timer_irq);
irq_attach(timer_irq, sim_timer_handler, NULL);
#endif
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.
*
* Input Parameters:
* irq - a pointer where we save the host signal number for SIGALRM
* nsec - timer expire time
*
* Returned 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;
}
/****************************************************************************
* 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;
}