From 8c0fed1c229e1fe4b0fd2579df2fef5b18c2a929 Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Wed, 3 Apr 2019 05:59:17 +0800 Subject: [PATCH] [posix-app] fix alarm issue when time changed (#3728) Current posix app uses gettimeofday() to get time, which will be affected by system time changes, and results in alarm not fired. This commit uses clock_gettime() instead to avoid this issue. --- .travis/before_install.sh | 11 +------ src/posix/platform/alarm.c | 41 ++++++++++++++------------- src/posix/platform/hdlc_interface.cpp | 16 +++++------ src/posix/platform/platform-posix.h | 31 +++++++------------- src/posix/platform/radio_spinel.cpp | 17 +++++------ src/posix/platform/sim.c | 5 ++-- 6 files changed, 52 insertions(+), 69 deletions(-) diff --git a/.travis/before_install.sh b/.travis/before_install.sh index db857e79a..691e25593 100755 --- a/.travis/before_install.sh +++ b/.travis/before_install.sh @@ -64,18 +64,9 @@ cd /tmp || die } [ $BUILD_TARGET != posix-app-pty ] || { - sudo apt-get install socat expect libdbus-1-dev autoconf-archive || die + sudo apt-get install socat expect || die JOBS=$(getconf _NPROCESSORS_ONLN) ( - WPANTUND_TMPDIR=/tmp/wpantund - git clone --depth 1 https://github.com/openthread/wpantund.git $WPANTUND_TMPDIR - cd $WPANTUND_TMPDIR - ./bootstrap.sh - ./configure --prefix= --exec-prefix=/usr --disable-ncp-dummy --enable-static-link-ncp-plugin=spinel - make -j $JOBS - sudo make install - ) || die - ( LIBCOAP_TMPDIR=/tmp/libcoap mkdir $LIBCOAP_TMPDIR cd $LIBCOAP_TMPDIR diff --git a/src/posix/platform/alarm.c b/src/posix/platform/alarm.c index 8931bf572..156ce523c 100644 --- a/src/posix/platform/alarm.c +++ b/src/posix/platform/alarm.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -40,10 +41,6 @@ #include "code_utils.h" -#define MS_PER_S 1000 -#define US_PER_MS 1000 -#define US_PER_S 1000000 - static bool sIsMsRunning = false; static uint32_t sMsAlarm = 0; @@ -52,28 +49,32 @@ static bool sIsUsRunning = false; static uint32_t sUsAlarm = 0; #endif -static uint32_t sSpeedUpFactor = 1; -static struct timeval sStart; +static uint32_t sSpeedUpFactor = 1; + +#if !OPENTHREAD_POSIX_VIRTUAL_TIME +uint64_t otSysGetTime(void) +{ + struct timespec now; + + VerifyOrDie(clock_gettime(CLOCK_MONOTONIC, &now) == 0, OT_EXIT_FAILURE); + + return (uint64_t)now.tv_sec * US_PER_S + (uint64_t)now.tv_nsec / NS_PER_US; +} +#endif // !OPENTHREAD_POSIX_VIRTUAL_TIME + +static uint64_t platformAlarmGetNow(void) +{ + return otSysGetTime() * sSpeedUpFactor; +} void platformAlarmInit(uint32_t aSpeedUpFactor) { sSpeedUpFactor = aSpeedUpFactor; - otSysGetTime(&sStart); -} - -static uint64_t platformGetNow(void) -{ - struct timeval now; - - otSysGetTime(&now); - timersub(&now, &sStart, &now); - - return (uint64_t)now.tv_sec * US_PER_S * sSpeedUpFactor + (uint64_t)now.tv_usec * sSpeedUpFactor; } uint32_t otPlatAlarmMilliGetNow(void) { - return (uint32_t)(platformGetNow() / US_PER_MS); + return (uint32_t)(platformAlarmGetNow() / US_PER_MS); } void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) @@ -94,7 +95,7 @@ void otPlatAlarmMilliStop(otInstance *aInstance) #if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER uint32_t otPlatAlarmMicroGetNow(void) { - return (uint32_t)(platformGetNow()); + return (uint32_t)(otSysGetTime()); } void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) @@ -116,7 +117,7 @@ void otPlatAlarmMicroStop(otInstance *aInstance) void platformAlarmUpdateTimeout(struct timeval *aTimeout) { int64_t remaining = INT32_MAX; - uint64_t now = platformGetNow(); + uint64_t now = platformAlarmGetNow(); assert(aTimeout != NULL); diff --git a/src/posix/platform/hdlc_interface.cpp b/src/posix/platform/hdlc_interface.cpp index 3d639e90f..c21d6c330 100644 --- a/src/posix/platform/hdlc_interface.cpp +++ b/src/posix/platform/hdlc_interface.cpp @@ -256,15 +256,12 @@ otError HdlcInterface::WaitForWritable(void) { otError error = OT_ERROR_NONE; struct timeval timeout = {kMaxWaitTime / 1000, (kMaxWaitTime % 1000) * 1000}; - struct timeval end; - struct timeval now; + uint64_t now = otSysGetTime(); + uint64_t end = now + kMaxWaitTime * US_PER_MS; fd_set writeFds; fd_set errorFds; int rval; - otSysGetTime(&now); - timeradd(&now, &timeout, &end); - while (true) { FD_ZERO(&writeFds); @@ -297,11 +294,14 @@ otError HdlcInterface::WaitForWritable(void) exit(OT_EXIT_FAILURE); } - otSysGetTime(&now); + now = otSysGetTime(); - if (timercmp(&end, &now, >)) + if (end > now) { - timersub(&end, &now, &timeout); + uint64_t remain = end - now; + + timeout.tv_sec = remain / US_PER_S; + timeout.tv_usec = static_cast(remain % US_PER_S); } else { diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h index 24d280e78..09b93fe57 100644 --- a/src/posix/platform/platform-posix.h +++ b/src/posix/platform/platform-posix.h @@ -138,13 +138,10 @@ void platformAlarmProcess(otInstance *aInstance); */ int32_t platformAlarmGetNext(void); -/** - * This function returns the current alarm time. - * - * @returns The current alarm time. - * - */ -uint64_t platformAlarmGetNow(void); +#define MS_PER_S 1000 +#define US_PER_MS 1000 +#define US_PER_S 1000000 +#define NS_PER_US 1000 /** * This function advances the alarm time by @p aDelta. @@ -275,14 +272,6 @@ void otSimInit(void); */ void otSimDeinit(void); -/** - * This function gets simulation time. - * - * @param[in] aTime A pointer to a timeval receiving the current time. - * - */ -void otSimGetTime(struct timeval *aTime); - /** * This function performs simulation processing. * @@ -354,11 +343,13 @@ void otSimRadioSpinelUpdate(struct timeval *atimeout); */ void otSimRadioSpinelProcess(otInstance *aInstance, const struct Event *aEvent); -#if OPENTHREAD_POSIX_VIRTUAL_TIME -#define otSysGetTime(aTime) otSimGetTime(aTime) -#else -#define otSysGetTime(aTime) gettimeofday(aTime, NULL) -#endif +/** + * This function gets system time in microseconds without applying speed up factor. + * + * @returns System time in microseconds. + * + */ +uint64_t otSysGetTime(void); /** * This function initializes platform UDP driver. diff --git a/src/posix/platform/radio_spinel.cpp b/src/posix/platform/radio_spinel.cpp index c7cef4db5..269b38bff 100644 --- a/src/posix/platform/radio_spinel.cpp +++ b/src/posix/platform/radio_spinel.cpp @@ -923,13 +923,10 @@ otError RadioSpinel::Remove(spinel_prop_key_t aKey, const char *aFormat, ...) otError RadioSpinel::WaitResponse(void) { - struct timeval end; - struct timeval now; + uint64_t now = otSysGetTime(); + uint64_t end = now + kMaxWaitTime * US_PER_MS; struct timeval timeout = {kMaxWaitTime / 1000, (kMaxWaitTime % 1000) * 1000}; - otSysGetTime(&now); - timeradd(&now, &timeout, &end); - do { #if OPENTHREAD_POSIX_VIRTUAL_TIME @@ -997,10 +994,14 @@ otError RadioSpinel::WaitResponse(void) } #endif // OPENTHREAD_POSIX_VIRTUAL_TIME - otSysGetTime(&now); - if (timercmp(&end, &now, >)) + now = otSysGetTime(); + + if (end > now) { - timersub(&end, &now, &timeout); + uint64_t remain = end - now; + + timeout.tv_sec = remain / US_PER_S; + timeout.tv_usec = static_cast(remain % US_PER_S); } else { diff --git a/src/posix/platform/sim.c b/src/posix/platform/sim.c index 3b1d5da65..61eedc1db 100644 --- a/src/posix/platform/sim.c +++ b/src/posix/platform/sim.c @@ -198,10 +198,9 @@ void otSimProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set otSimRadioSpinelProcess(aInstance, &event); } -void otSimGetTime(struct timeval *aTime) +uint64_t otSysGetTime(void) { - aTime->tv_sec = (time_t)sNow / kUsPerSecond; - aTime->tv_usec = sNow % kUsPerSecond; + return sNow; } #endif // OPENTHREAD_POSIX_VIRTUAL_TIME