// Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // _timespec64 functions for system time #include #include #include "awint.hpp" namespace { constexpr long _Nsec_per_sec = 1000000000L; constexpr long _Nsec_per_msec = 1000000L; constexpr int _Msec_per_sec = 1000; void _timespec64_normalize(_timespec64* xt) { // adjust so that 0 <= tv_nsec < 1 000 000 000 while (xt->tv_nsec < 0) { // normalize target time xt->tv_sec -= 1; xt->tv_nsec += _Nsec_per_sec; } while (_Nsec_per_sec <= xt->tv_nsec) { // normalize target time xt->tv_sec += 1; xt->tv_nsec -= _Nsec_per_sec; } } // return _timespec64 object holding difference between xt and now, treating negative difference as 0 _timespec64 _timespec64_diff(const _timespec64* xt, const _timespec64* now) { _timespec64 diff = *xt; _timespec64_normalize(&diff); if (diff.tv_nsec < now->tv_nsec) { // avoid underflow diff.tv_sec -= now->tv_sec + 1; diff.tv_nsec += _Nsec_per_sec - now->tv_nsec; } else { // no underflow diff.tv_sec -= now->tv_sec; diff.tv_nsec -= now->tv_nsec; } if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec <= 0)) { // time is zero diff.tv_sec = 0; diff.tv_nsec = 0; } return diff; } } // namespace extern "C" { _CRTIMP2_PURE long long __cdecl _Xtime_get_ticks() noexcept { // get system time in 100-nanosecond intervals since the epoch constexpr long long _Epoch = 0x19DB1DED53E8000LL; FILETIME ft; GetSystemTimePreciseAsFileTime(&ft); return ((static_cast(ft.dwHighDateTime)) << 32) + static_cast(ft.dwLowDateTime) - _Epoch; } // Used by several src files, but not dllexported. void _Timespec64_get_sys(_timespec64* xt) noexcept { // get system time with nanosecond resolution constexpr long _Nsec100_per_sec = _Nsec_per_sec / 100; unsigned long long now = _Xtime_get_ticks(); xt->tv_sec = static_cast<__time64_t>(now / _Nsec100_per_sec); xt->tv_nsec = static_cast(now % _Nsec100_per_sec) * 100; } // convert time to milliseconds _CRTIMP2_PURE long __cdecl _Xtime_diff_to_millis2(const _timespec64* xt1, const _timespec64* xt2) noexcept { _timespec64 diff = _timespec64_diff(xt1, xt2); return static_cast(diff.tv_sec * _Msec_per_sec + (diff.tv_nsec + _Nsec_per_msec - 1) / _Nsec_per_msec); } // TRANSITION, ABI: preserved for binary compatibility _CRTIMP2_PURE long __cdecl _Xtime_diff_to_millis(const _timespec64* xt) noexcept { // convert time to milliseconds _timespec64 now; _Timespec64_get_sys(&now); return _Xtime_diff_to_millis2(xt, &now); } // TRANSITION, ABI: preserved for binary compatibility _CRTIMP2_PURE int __cdecl xtime_get(_timespec64* xt, int type) noexcept { // get current time if (type != TIME_UTC || xt == nullptr) { type = 0; } else { _Timespec64_get_sys(xt); } return type; } _CRTIMP2_PURE long long __cdecl _Query_perf_counter() noexcept { // get current value of performance counter LARGE_INTEGER li; QueryPerformanceCounter(&li); // always succeeds return li.QuadPart; } _CRTIMP2_PURE long long __cdecl _Query_perf_frequency() noexcept { // get frequency of performance counter static std::atomic freq_cached{0}; long long freq = freq_cached.load(std::memory_order_relaxed); if (freq == 0) { LARGE_INTEGER li; QueryPerformanceFrequency(&li); // always succeeds freq = li.QuadPart; // doesn't change after system boot freq_cached.store(freq, std::memory_order_relaxed); } return freq; } } // extern "C" /* * This file is derived from software bearing the following * restrictions: * * (c) Copyright William E. Kempf 2001 * * Permission to use, copy, modify, distribute and sell this * software and its documentation for any purpose is hereby * granted without fee, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation. William E. Kempf makes no representations * about the suitability of this software for any purpose. * It is provided "as is" without express or implied warranty. */