diff --git a/arch/sim/src/sim/up_hosttime.c b/arch/sim/src/sim/up_hosttime.c index 5b18b177c0b..03c9ed7d804 100644 --- a/arch/sim/src/sim/up_hosttime.c +++ b/arch/sim/src/sim/up_hosttime.c @@ -40,10 +40,24 @@ uint64_t host_gettime(bool rtc) { + static uint64_t start; struct timespec tp; + uint64_t current; clock_gettime(rtc ? CLOCK_REALTIME : CLOCK_MONOTONIC, &tp); - return 1000000000ull * tp.tv_sec + tp.tv_nsec; + current = 1000000000ull * tp.tv_sec + tp.tv_nsec; + + if (rtc) + { + return current; + } + + if (start == 0) + { + start = current; + } + + return current - start; } /**************************************************************************** @@ -61,17 +75,9 @@ void host_sleep(uint64_t nsec) void host_sleepuntil(uint64_t nsec) { - static uint64_t base; uint64_t now; now = host_gettime(false); - if (base == 0) - { - base = now; - } - - now -= base; - if (nsec > now + 1000) { usleep((nsec - now) / 1000); diff --git a/arch/sim/src/sim/up_oneshot.c b/arch/sim/src/sim/up_oneshot.c index fa0610fd003..c0a8f2f5fdd 100644 --- a/arch/sim/src/sim/up_oneshot.c +++ b/arch/sim/src/sim/up_oneshot.c @@ -85,7 +85,6 @@ static int sim_current(FAR struct oneshot_lowerhalf_s *lower, * Private Data ****************************************************************************/ -static struct timespec g_current; static sq_queue_t g_oneshot_list; /* Lower half operations */ @@ -102,6 +101,27 @@ static const struct oneshot_operations_s g_oneshot_ops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: sim_timer_current + * + * Description: + * Get current time from host. + * + ****************************************************************************/ + +static inline void sim_timer_current(FAR struct timespec *ts) +{ + uint64_t nsec; + time_t sec; + + nsec = host_gettime(false); + sec = nsec / NSEC_PER_SEC; + nsec -= sec * NSEC_PER_SEC; + + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + /**************************************************************************** * Name: sim_timer_update * @@ -113,16 +133,8 @@ static const struct oneshot_operations_s g_oneshot_ops = static void sim_timer_update(void) { - static const struct timespec tick = - { - .tv_sec = 0, - .tv_nsec = NSEC_PER_TICK, - }; - FAR sq_entry_t *entry; - clock_timespec_add(&g_current, &tick, &g_current); - for (entry = sq_peek(&g_oneshot_list); entry; entry = sq_next(entry)) { sim_process_tick(entry); @@ -154,7 +166,10 @@ static void sim_process_tick(sq_entry_t *entry) if (priv->callback) { - if (clock_timespec_compare(&priv->alarm, &g_current) > 0) + struct timespec current; + + sim_timer_current(¤t); + if (clock_timespec_compare(&priv->alarm, ¤t) > 0) { return; /* Alarm doesn't expire yet */ } @@ -228,10 +243,12 @@ static int sim_start(FAR struct oneshot_lowerhalf_s *lower, { FAR struct sim_oneshot_lowerhalf_s *priv = (FAR struct sim_oneshot_lowerhalf_s *)lower; + struct timespec current; DEBUGASSERT(priv != NULL && callback != NULL && ts != NULL); - clock_timespec_add(&g_current, ts, &priv->alarm); + sim_timer_current(¤t); + clock_timespec_add(¤t, ts, &priv->alarm); priv->callback = callback; priv->arg = arg; @@ -268,10 +285,12 @@ static int sim_cancel(FAR struct oneshot_lowerhalf_s *lower, { FAR struct sim_oneshot_lowerhalf_s *priv = (FAR struct sim_oneshot_lowerhalf_s *)lower; + struct timespec current; DEBUGASSERT(priv != NULL && ts != NULL); - clock_timespec_subtract(&priv->alarm, &g_current, ts); + sim_timer_current(¤t); + clock_timespec_subtract(&priv->alarm, ¤t, ts); priv->callback = NULL; priv->arg = NULL; @@ -303,7 +322,8 @@ static int sim_current(FAR struct oneshot_lowerhalf_s *lower, { DEBUGASSERT(ts != NULL); - *ts = g_current; + sim_timer_current(ts); + return OK; } @@ -417,15 +437,14 @@ void up_timer_initialize(void) void up_timer_update(void) { -#ifdef CONFIG_SIM_WALLTIME_SLEEP + static uint64_t until; /* Wait a bit so that the timing is close to the correct rate. */ - host_sleepuntil(g_current.tv_nsec + - (uint64_t)g_current.tv_sec * NSEC_PER_SEC); -#endif + until += NSEC_PER_TICK; + host_sleepuntil(until); -#ifndef CONFIG_SIM_WALLTIME_SIGNAL +#ifdef CONFIG_SIM_WALLTIME_SLEEP sim_timer_update(); #endif }