[posix] use real time signal for microsecond timer (#5122)

This commit is contained in:
Yakun Xu
2020-06-19 16:12:55 -07:00
committed by GitHub
parent b66ac5d907
commit 8248c3d9df
11 changed files with 160 additions and 35 deletions
+2
View File
@@ -396,6 +396,7 @@ LOCAL_CPPFLAGS := \
$(NULL)
LOCAL_LDLIBS := \
-lrt \
-lutil
LOCAL_SRC_FILES := \
@@ -481,6 +482,7 @@ LOCAL_SRC_FILES := \
$(NULL)
LOCAL_LDLIBS := \
-lrt \
-lutil
LOCAL_STATIC_LIBRARIES = libopenthread-ncp ot-core
+13 -17
View File
@@ -36,13 +36,7 @@
#include "utils/code_utils.h"
#ifndef __linux__
#define __linux__ 0
#endif
// linux microsecond timer
#if __linux__
#ifdef __linux__
#include <signal.h>
#include <time.h>
@@ -67,6 +61,12 @@ timer_t sMicroTimer;
#define DEFAULT_TIMEOUT 10 // seconds
#ifdef CLOCK_MONOTONIC_RAW
#define OT_SIMULATION_CLOCK_ID CLOCK_MONOTONIC_RAW
#else
#define OT_SIMULATION_CLOCK_ID CLOCK_MONOTONIC
#endif
static bool sIsMsRunning = false;
static uint32_t sMsAlarm = 0;
@@ -75,7 +75,7 @@ static uint32_t sUsAlarm = 0;
static uint32_t sSpeedUpFactor = 1;
#if __linux__
#ifdef __linux__
static void microTimerHandler(int aSignal, siginfo_t *aSignalInfo, void *aUserContext)
{
assert(aSignal == OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL);
@@ -90,7 +90,7 @@ void platformAlarmInit(uint32_t aSpeedUpFactor)
{
sSpeedUpFactor = aSpeedUpFactor;
#if __linux__
#ifdef __linux__
{
struct sigaction sa;
@@ -110,7 +110,7 @@ void platformAlarmInit(uint32_t aSpeedUpFactor)
sev.sigev_signo = OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL;
sev.sigev_value.sival_ptr = &sMicroTimer;
if (-1 == timer_create(CLOCK_REALTIME, &sev, &sMicroTimer))
if (-1 == timer_create(CLOCK_MONOTONIC, &sev, &sMicroTimer))
{
perror("timer_create");
exit(EXIT_FAILURE);
@@ -125,11 +125,7 @@ uint64_t platformGetNow(void)
struct timespec now;
int err;
#ifdef CLOCK_MONOTONIC_RAW
err = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
#else
err = clock_gettime(CLOCK_MONOTONIC, &now);
#endif
err = clock_gettime(OT_SIMULATION_CLOCK_ID, &now);
VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
@@ -181,7 +177,7 @@ void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
sUsAlarm = aT0 + aDt;
sIsUsRunning = true;
#if __linux__
#ifdef __linux__
{
struct itimerspec its;
uint32_t diff = sUsAlarm - otPlatAlarmMicroGetNow();
@@ -207,7 +203,7 @@ void otPlatAlarmMicroStop(otInstance *aInstance)
sIsUsRunning = false;
#if __linux__
#ifdef __linux__
{
struct itimerspec its = {{0, 0}, {0, 0}};
+2 -2
View File
@@ -49,7 +49,7 @@ readonly VIRTUAL_TIME="${VIRTUAL_TIME:-1}"
build_simulation()
{
local version="$1"
local options=("-DOT_THREAD_VERSION=${version}")
local options=("-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
if [[ ${version} == "1.2" ]]; then
options+=("-DOT_DUA=ON")
@@ -82,7 +82,7 @@ build_simulation()
build_posix()
{
local version="$1"
local options=("-DOT_THREAD_VERSION=${version}")
local options=("-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
if [[ ${version} == "1.2" ]]; then
options+=("-DOT_DUA=ON")
+6
View File
@@ -60,6 +60,12 @@ LDADD_COMMON = \
-lutil \
$(NULL)
if OPENTHREAD_TARGET_LINUX
LDADD_COMMON += \
-lrt \
$(NULL)
endif
if OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
LDADD_COMMON += \
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
+23
View File
@@ -113,6 +113,7 @@ enum
OT_POSIX_OPT_SHORT_MAX = 128,
OT_POSIX_OPT_RADIO_VERSION,
OT_POSIX_OPT_REAL_TIME_SIGNAL,
};
static const struct option kOptions[] = {{"debug-level", required_argument, NULL, OT_POSIX_OPT_DEBUG_LEVEL},
@@ -120,6 +121,7 @@ static const struct option kOptions[] = {{"debug-level", required_argument, NULL
{"help", no_argument, NULL, OT_POSIX_OPT_HELP},
{"interface-name", required_argument, NULL, OT_POSIX_OPT_INTERFACE_NAME},
{"radio-version", no_argument, NULL, OT_POSIX_OPT_RADIO_VERSION},
{"real-time-signal", required_argument, NULL, OT_POSIX_OPT_REAL_TIME_SIGNAL},
{"time-speed", required_argument, NULL, OT_POSIX_OPT_TIME_SPEED},
{"verbose", no_argument, NULL, OT_POSIX_OPT_VERBOSE},
{0, 0, 0, 0}};
@@ -138,6 +140,12 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
" -s --time-speed factor Time speed up factor.\n"
" -v --verbose Also log to stderr.\n",
aProgramName);
#ifdef __linux__
fprintf(aStream,
" --real-time-signal (Linux only) The real-time signal number for microsecond timer.\n"
" Use +N for relative value to SIGRTMIN, and use N for absolute value.\n");
#endif
fprintf(aStream, "%s", otSysGetRadioUrlHelpString());
exit(aExitCode);
}
@@ -148,6 +156,9 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
aConfig->mPlatformConfig.mSpeedUpFactor = 1;
aConfig->mLogLevel = OT_LOG_LEVEL_CRIT;
#ifdef __linux__
aConfig->mPlatformConfig.mRealTimeSignal = SIGRTMIN;
#endif
optind = 1;
@@ -194,6 +205,18 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
case OT_POSIX_OPT_RADIO_VERSION:
aConfig->mPrintRadioVersion = true;
break;
#ifdef __linux__
case OT_POSIX_OPT_REAL_TIME_SIGNAL:
if (optarg[0] == '+')
{
aConfig->mPlatformConfig.mRealTimeSignal = SIGRTMIN + atoi(&optarg[1]);
}
else
{
aConfig->mPlatformConfig.mRealTimeSignal = atoi(optarg);
}
break;
#endif // __linux__
case '?':
PrintUsage(aArgVector[0], stderr, OT_EXIT_INVALID_ARGUMENTS);
break;
+8 -1
View File
@@ -83,7 +83,14 @@ set_target_properties(
CXX_STANDARD 11
)
target_link_libraries(openthread-posix PUBLIC openthread-platform PRIVATE ot-config util)
target_link_libraries(openthread-posix
PUBLIC
openthread-platform
PRIVATE
ot-config
util
$<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:rt>
)
target_compile_definitions(openthread-posix
PUBLIC
+93 -6
View File
@@ -50,16 +50,38 @@ static uint32_t sUsAlarm = 0;
static uint32_t sSpeedUpFactor = 1;
#ifdef __linux__
#include <signal.h>
#include <time.h>
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
static timer_t sMicroTimer;
static int sRealTimeSignal = 0;
static void microTimerHandler(int aSignal, siginfo_t *aSignalInfo, void *aUserContext)
{
assert(aSignal == sRealTimeSignal);
assert(aSignalInfo->si_value.sival_ptr == &sMicroTimer);
OT_UNUSED_VARIABLE(aSignal);
OT_UNUSED_VARIABLE(aSignalInfo);
OT_UNUSED_VARIABLE(aUserContext);
}
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
#endif // __linux__
#ifdef CLOCK_MONOTONIC_RAW
#define OT_POSIX_CLOCK_ID CLOCK_MONOTONIC_RAW
#else
#define OT_POSIX_CLOCK_ID CLOCK_MONOTONIC
#endif
#if !OPENTHREAD_POSIX_VIRTUAL_TIME
uint64_t otPlatTimeGet(void)
{
struct timespec now;
#ifdef CLOCK_MONOTONIC_RAW
VerifyOrDie(clock_gettime(CLOCK_MONOTONIC_RAW, &now) == 0, OT_EXIT_FAILURE);
#else
VerifyOrDie(clock_gettime(CLOCK_MONOTONIC, &now) == 0, OT_EXIT_FAILURE);
#endif
VerifyOrDie(clock_gettime(OT_POSIX_CLOCK_ID, &now) == 0, OT_EXIT_FAILURE);
return (uint64_t)now.tv_sec * US_PER_S + (uint64_t)now.tv_nsec / NS_PER_US;
}
@@ -70,9 +92,43 @@ static uint64_t platformAlarmGetNow(void)
return otPlatTimeGet() * sSpeedUpFactor;
}
void platformAlarmInit(uint32_t aSpeedUpFactor)
void platformAlarmInit(uint32_t aSpeedUpFactor, int aRealTimeSignal)
{
sSpeedUpFactor = aSpeedUpFactor;
if (aRealTimeSignal == 0)
{
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
otLogWarnPlat("Real time signal not enabled, microsecond timers may be inaccurate!");
#endif
}
#ifdef __linux__
else if (aRealTimeSignal >= SIGRTMIN && aRealTimeSignal <= SIGRTMAX)
{
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
struct sigaction sa;
struct sigevent sev;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = microTimerHandler;
sigemptyset(&sa.sa_mask);
VerifyOrDie(sigaction(aRealTimeSignal, &sa, NULL) != -1, OT_EXIT_ERROR_ERRNO);
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = aRealTimeSignal;
sev.sigev_value.sival_ptr = &sMicroTimer;
VerifyOrDie(timer_create(CLOCK_MONOTONIC, &sev, &sMicroTimer) != -1, OT_EXIT_ERROR_ERRNO);
sRealTimeSignal = aRealTimeSignal;
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
}
#endif // __linux__
else
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
}
uint32_t otPlatAlarmMilliGetNow(void)
@@ -107,6 +163,25 @@ void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
sUsAlarm = aT0 + aDt;
sIsUsRunning = true;
#ifdef __linux__
if (sRealTimeSignal != 0)
{
struct itimerspec its;
uint32_t diff = sUsAlarm - otPlatAlarmMicroGetNow();
its.it_value.tv_sec = diff / US_PER_S;
its.it_value.tv_nsec = (diff % US_PER_S) * NS_PER_US;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
if (-1 == timer_settime(sMicroTimer, 0, &its, NULL))
{
otLogWarnPlat("Failed to update microsecond timer: %s", strerror(errno));
}
}
#endif // __linux__
}
void otPlatAlarmMicroStop(otInstance *aInstance)
@@ -114,6 +189,18 @@ void otPlatAlarmMicroStop(otInstance *aInstance)
OT_UNUSED_VARIABLE(aInstance);
sIsUsRunning = false;
#ifdef __linux__
if (sRealTimeSignal != 0)
{
struct itimerspec its = {{0, 0}, {0, 0}};
if (-1 == timer_settime(sMicroTimer, 0, &its, NULL))
{
otLogWarnPlat("Failed to stop microsecond timer: %s", strerror(errno));
}
}
#endif // __linux__
}
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
@@ -76,9 +76,10 @@ typedef struct otPosixRadioArguments otPosixRadioArguments;
*/
typedef struct otPlatformConfig
{
uint32_t mSpeedUpFactor; ///< Speed up factor.
const char *mInterfaceName; ///< Thread network interface name.
const char *mRadioUrl; ///< Radio url.
const char *mInterfaceName; ///< Thread network interface name.
const char *mRadioUrl; ///< Radio url.
int mRealTimeSignal; ///< The real-time signal for microsecond timer.
uint32_t mSpeedUpFactor; ///< Speed up factor.
} otPlatformConfig;
/**
+4 -1
View File
@@ -106,8 +106,11 @@ extern uint64_t gNodeId;
/**
* This function initializes the alarm service used by OpenThread.
*
* @param[in] aSpeedUpFactor The speed up factor.
* @param[in] aRealTimeSignal The real time signal for microsecond alarms.
*
*/
void platformAlarmInit(uint32_t aSpeedUpFactor);
void platformAlarmInit(uint32_t aSpeedUpFactor, int aRealTimeSignal);
/**
* This function retrieves the time remaining until the alarm fires.
+1 -1
View File
@@ -57,7 +57,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
#endif
VerifyOrDie(args.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
platformAlarmInit(aPlatformConfig->mSpeedUpFactor);
platformAlarmInit(aPlatformConfig->mSpeedUpFactor, aPlatformConfig->mRealTimeSignal);
platformRadioInit(&args);
platformRandomInit();
+4 -4
View File
@@ -108,7 +108,7 @@ class Node:
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
if 'RADIO_DEVICE' in os.environ:
cmd += ' -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
cmd += ' --real-time-signal=+1 -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
os.environ['RADIO_DEVICE'], nodeid)
else:
cmd += ' %d' % nodeid
@@ -123,7 +123,7 @@ class Node:
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
if 'RADIO_DEVICE_1_1' in os.environ:
cmd += ' -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
cmd += ' --real-time-signal=+1 -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
os.environ['RADIO_DEVICE_1_1'], nodeid)
else:
cmd += ' %d' % nodeid
@@ -151,7 +151,7 @@ class Node:
# If Thread version of node matches the testing environment version.
if self.version == self.env_version:
if 'RADIO_DEVICE' in os.environ:
args = ' spinel+hdlc+uart://%s?forkpty-arg=%d' % (
args = ' --real-time-signal=+1 spinel+hdlc+uart://%s?forkpty-arg=%d' % (
os.environ['RADIO_DEVICE'], nodeid)
else:
args = ''
@@ -190,7 +190,7 @@ class Node:
# Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability.
elif self.version == '1.1':
if 'RADIO_DEVICE_1_1' in os.environ:
args = ' spinel+hdlc+uart://%s?forkpty-arg=%d' % (
args = ' --real-time-signal=+1 spinel+hdlc+uart://%s?forkpty-arg=%d' % (
os.environ['RADIO_DEVICE_1_1'], nodeid)
else:
args = ''