From ef41cf208868b9438e30b867cbb6868afce38af9 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 26 May 2020 20:09:56 +0100 Subject: [PATCH] u/time: Use a very large hammer to "fix" time_state --- src/xrt/auxiliary/util/u_time.cpp | 125 +++++++---------------- src/xrt/auxiliary/util/u_time.h | 19 +++- src/xrt/state_trackers/oxr/oxr_session.c | 4 +- src/xrt/state_trackers/oxr/oxr_xdev.c | 2 +- 4 files changed, 58 insertions(+), 92 deletions(-) diff --git a/src/xrt/auxiliary/util/u_time.cpp b/src/xrt/auxiliary/util/u_time.cpp index 3af10f0c1..5a803e704 100644 --- a/src/xrt/auxiliary/util/u_time.cpp +++ b/src/xrt/auxiliary/util/u_time.cpp @@ -7,61 +7,41 @@ * @ingroup aux_util */ -#include "u_time.h" #include "xrt/xrt_config_os.h" #include "xrt/xrt_compiler.h" -#include +#include "os/os_time.h" + +#include "u_time.h" + #include #include #include #include -#ifdef XRT_OS_LINUX -#include -#endif -using namespace std::chrono; - -struct MatchingTimePoints -{ - MatchingTimePoints() - { -#ifdef XRT_OS_LINUX - clock_gettime(CLOCK_MONOTONIC, &clock_monotonic); -#endif - } - system_clock::time_point sys = system_clock::now(); - steady_clock::time_point steady = steady_clock::now(); - // high_resolution_clock::time_point highRes; - -#ifdef XRT_OS_LINUX - struct timespec clock_monotonic; -#endif - - timepoint_ns - getTimestamp(time_state const &prevState); -}; +/* + * + * Structs. + * + */ struct time_state { - MatchingTimePoints lastTimePoints = {}; - timepoint_ns lastTime = {}; + // Hardcoded to one second offset. + timepoint_ns offset = 1000 * 1000 * 1000; }; -timepoint_ns -MatchingTimePoints::getTimestamp(time_state const &prevState) -{ - //! @todo right now just doing steady clock for simplicity. - //! @todo Eventually need to make the high-res clock steady. - auto elapsed = steady - prevState.lastTimePoints.steady; - return prevState.lastTime + duration_cast(elapsed).count(); -} + +/* + * + * 'Exported' functions. + * + */ extern "C" struct time_state * time_state_create() { - time_state *state = new (std::nothrow) time_state; return state; } @@ -83,24 +63,16 @@ extern "C" timepoint_ns time_state_get_now(struct time_state const *state) { assert(state != NULL); - auto now = MatchingTimePoints(); - return now.getTimestamp(*state); + return time_state_monotonic_to_ts_ns(state, os_monotonic_get_ns()); } extern "C" timepoint_ns time_state_get_now_and_update(struct time_state *state) { assert(state != NULL); - auto now = MatchingTimePoints(); - auto timestamp = now.getTimestamp(*state); - - // Update the state - state->lastTimePoints = now; - state->lastTime = timestamp; - - return timestamp; + return time_state_get_now(state); } extern "C" void @@ -110,60 +82,39 @@ time_state_to_timespec(struct time_state const *state, { assert(state != NULL); assert(out != NULL); - // Subject to some jitter, roughly up to the magnitude of the actual - // resolution difference between the used time source and the system - // clock, as well as the non-simultaneity of the calls in - // MatchingTimePoints::getNow() - auto sinceLastUpdate = nanoseconds{timestamp - state->lastTime}; - auto equivSystemTimepoint = state->lastTimePoints.sys + sinceLastUpdate; - // System clock epoch is same as unix epoch for all known - // implementations, but not strictly standard-required yet, see - // wg21.link/p0355 - auto sinceEpoch = equivSystemTimepoint.time_since_epoch(); - auto secondsSinceEpoch = duration_cast(sinceEpoch); - sinceEpoch -= secondsSinceEpoch; - out->tv_sec = secondsSinceEpoch.count(); - out->tv_nsec = duration_cast(sinceEpoch).count(); + uint64_t ns = time_state_ts_to_monotonic_ns(state, timestamp); + + out->tv_sec = ns / (1000 * 1000 * 1000); + out->tv_nsec = ns % (1000 * 1000 * 1000); } - extern "C" timepoint_ns time_state_from_timespec(struct time_state const *state, const struct timespec *timespecTime) { assert(state != NULL); assert(timespecTime != NULL); - auto sinceEpoch = - seconds{timespecTime->tv_sec} + nanoseconds{timespecTime->tv_nsec}; + uint64_t ns = 0; + ns += timespecTime->tv_nsec; + ns += timespecTime->tv_sec * 1000 * 1000 * 1000; - // System clock epoch is same as unix epoch for all known - // implementations, but not strictly standard-required yet, see - // wg21.link/p0355 - auto systemTimePoint = time_point{ - duration_cast(sinceEpoch)}; - - // duration between last update and the supplied timespec - auto sinceLastUpdate = state->lastTimePoints.sys - systemTimePoint; - - // Offset the last timestamp by that duration. - return state->lastTime + - duration_cast(sinceLastUpdate).count(); + return time_state_monotonic_to_ts_ns(state, ns); } - -timepoint_ns -time_state_from_monotonic_ns(struct time_state const *state, - uint64_t monotonic_ns) +extern "C" timepoint_ns +time_state_monotonic_to_ts_ns(struct time_state const *state, + uint64_t monotonic_ns) { assert(state != NULL); - auto sinceLastUpdate = - seconds{state->lastTimePoints.clock_monotonic.tv_sec} + - nanoseconds{state->lastTimePoints.clock_monotonic.tv_nsec} - - nanoseconds{monotonic_ns}; - // Offset the last timestamp by that duration. - return state->lastTime + - duration_cast(sinceLastUpdate).count(); + return monotonic_ns + state->offset; +} + +extern "C" uint64_t +time_state_ts_to_monotonic_ns(struct time_state const *state, + timepoint_ns timestamp) +{ + return timestamp - state->offset; } diff --git a/src/xrt/auxiliary/util/u_time.h b/src/xrt/auxiliary/util/u_time.h index 24628ae9b..7b85227ef 100644 --- a/src/xrt/auxiliary/util/u_time.h +++ b/src/xrt/auxiliary/util/u_time.h @@ -164,8 +164,23 @@ time_state_from_timespec(struct time_state const *state, * @ingroup aux_util */ timepoint_ns -time_state_from_monotonic_ns(struct time_state const *state, - uint64_t monotonic_ns); +time_state_monotonic_to_ts_ns(struct time_state const *state, + uint64_t monotonic_ns); + +/*! + * Convert a adjusted integer timestamp to an monotonic system time (such as + * from @ref aux_os_time). + * + * Should not be called simultaneously with time_state_get_now_and_update. + * + * @public @memberof time_state + * @ingroup aux_util + */ +uint64_t +time_state_ts_to_monotonic_ns(struct time_state const *state, + timepoint_ns timestamp); + + #ifdef __cplusplus } #endif diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c index 9de2a82b4..f481332fd 100644 --- a/src/xrt/state_trackers/oxr/oxr_session.c +++ b/src/xrt/state_trackers/oxr/oxr_session.c @@ -407,13 +407,13 @@ oxr_session_frame_wait(struct oxr_logger *log, frameState->shouldRender = should_render(sess->state); frameState->predictedDisplayPeriod = predicted_display_period; - frameState->predictedDisplayTime = time_state_from_monotonic_ns( + frameState->predictedDisplayTime = time_state_monotonic_to_ts_ns( sess->sys->inst->timekeeping, predicted_display_time); if (frameState->predictedDisplayTime <= 0) { return oxr_error( log, XR_ERROR_RUNTIME_FAILURE, - " time_state_from_monotonic_ns returned '%" PRIi64 "'", + " time_state_monotonic_to_ts_ns returned '%" PRIi64 "'", frameState->predictedDisplayTime); } diff --git a/src/xrt/state_trackers/oxr/oxr_xdev.c b/src/xrt/state_trackers/oxr/oxr_xdev.c index dcacfcd7f..ba1b9f752 100644 --- a/src/xrt/state_trackers/oxr/oxr_xdev.c +++ b/src/xrt/state_trackers/oxr/oxr_xdev.c @@ -129,7 +129,7 @@ oxr_xdev_get_relation_at(struct oxr_logger *log, // Always make those to base things valid. ensure_valid_position_and_orientation(&relation, offset); - *out_relation_timestamp_ns = time_state_from_monotonic_ns( + *out_relation_timestamp_ns = time_state_monotonic_to_ts_ns( inst->timekeeping, relation_timestamp_ns); *out_relation = relation;