u/time: Use a very large hammer to "fix" time_state

This commit is contained in:
Jakob Bornecrantz 2020-05-26 20:09:56 +01:00
parent 18fbd3f819
commit ef41cf2088
4 changed files with 58 additions and 92 deletions

View file

@ -7,61 +7,41 @@
* @ingroup aux_util
*/
#include "u_time.h"
#include "xrt/xrt_config_os.h"
#include "xrt/xrt_compiler.h"
#include <chrono>
#include "os/os_time.h"
#include "u_time.h"
#include <new>
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#ifdef XRT_OS_LINUX
#include <sys/time.h>
#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<nanoseconds>(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<seconds>(sinceEpoch);
sinceEpoch -= secondsSinceEpoch;
out->tv_sec = secondsSinceEpoch.count();
out->tv_nsec = duration_cast<nanoseconds>(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<system_clock, nanoseconds>{
duration_cast<system_clock::duration>(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<nanoseconds>(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<nanoseconds>(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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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;