From f6e48d53862d44798b6ae99a64d1d5c5dfaa5c2a Mon Sep 17 00:00:00 2001 From: Joel Linn Date: Mon, 2 Dec 2019 22:19:47 +0100 Subject: [PATCH] [Base] Fix Clock platform functions on POSIX. --- src/xenia/base/clock_posix.cc | 42 ++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/xenia/base/clock_posix.cc b/src/xenia/base/clock_posix.cc index f18082b0e..73a23dc76 100644 --- a/src/xenia/base/clock_posix.cc +++ b/src/xenia/base/clock_posix.cc @@ -2,45 +2,55 @@ ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** - * Copyright 2019 Ben Vanik. All rights reserved. * + * Copyright 2021 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ -#include "xenia/base/clock.h" - #include -#include + +#include "xenia/base/assert.h" +#include "xenia/base/clock.h" namespace xe { uint64_t Clock::host_tick_frequency_platform() { timespec res; - clock_getres(CLOCK_MONOTONIC_RAW, &res); + int error = clock_getres(CLOCK_MONOTONIC_RAW, &res); + assert_zero(error); + assert_zero(res.tv_sec); // Sub second resolution is required. - return uint64_t(res.tv_sec) + uint64_t(res.tv_nsec) * 1000000000ull; + // Convert nano seconds to hertz. Resolution is 1ns on most systems. + return 1000000000ull / res.tv_nsec; } uint64_t Clock::host_tick_count_platform() { - timespec res; - clock_gettime(CLOCK_MONOTONIC_RAW, &res); + timespec tp; + int error = clock_gettime(CLOCK_MONOTONIC_RAW, &tp); + assert_zero(error); - return uint64_t(res.tv_sec) + uint64_t(res.tv_nsec) * 1000000000ull; + return tp.tv_nsec + tp.tv_sec * 1000000000ull; } uint64_t Clock::QueryHostSystemTime() { - struct timeval tv; - gettimeofday(&tv, NULL); + // https://docs.microsoft.com/en-us/windows/win32/sysinfo/converting-a-time-t-value-to-a-file-time + constexpr uint64_t seconds_per_day = 3600 * 24; + // Don't forget the 89 leap days. + constexpr uint64_t seconds_1601_to_1970 = + ((369 * 365 + 89) * seconds_per_day); - uint64_t ret = tv.tv_usec; - ret /= 1000; // usec -> msec + timeval now; + int error = gettimeofday(&now, nullptr); + assert_zero(error); - ret += (tv.tv_sec * 1000); // sec -> msec - return ret; + // NT systems use 100ns intervals. + return static_cast( + (static_cast(now.tv_sec) + seconds_1601_to_1970) * 10000000ull + + now.tv_usec * 10); } uint64_t Clock::QueryHostUptimeMillis() { return host_tick_count_platform() * 1000 / host_tick_frequency_platform(); } -} // namespace xe \ No newline at end of file +} // namespace xe