sim: realize sim timer tickless
Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit is contained in:
parent
d082af34f7
commit
f102837fe1
@ -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;
|
||||||
|
}
|
||||||
|
@ -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 *********************************************************/
|
||||||
|
|
||||||
|
@ -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(¤t);
|
||||||
|
clock_timespec_subtract(next, ¤t, ¤t);
|
||||||
|
|
||||||
|
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(¤t);
|
sim_timer_current(¤t);
|
||||||
clock_timespec_add(¤t, ts, &priv->alarm);
|
clock_timespec_add(¤t, 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(¤t);
|
sim_timer_current(¤t);
|
||||||
clock_timespec_subtract(&priv->alarm, ¤t, ts);
|
clock_timespec_subtract(&priv->alarm, ¤t, 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));
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user