Reactos
at listview 102 lines 3.3 kB view raw
1// 2// time.cpp 3// 4// Copyright (c) Microsoft Corporation. All rights reserved. 5// 6// The timespec_get() and time() families of functions, which get the current 7// system time as a timespec and a time_t, respectively. 8// 9#include <corecrt_internal_time.h> 10 11 12using get_system_time_function_type = void(WINAPI *)(LPFILETIME); 13 14template <get_system_time_function_type GetSystemTimeFunction, typename TimeSpecType> 15_Success_(return != 0) 16static int __cdecl common_timespec_get(TimeSpecType* const ts, int const base) throw() 17{ 18 typedef decltype(ts->tv_sec) time_type; 19 typedef __crt_time_time_t_traits<time_type> time_traits; 20 21 _VALIDATE_RETURN(ts != nullptr, EINVAL, 0); 22 23 if (base != TIME_UTC) 24 { 25 return 0; 26 } 27 28 __crt_filetime_union system_time{}; 29 GetSystemTimeFunction(&system_time._filetime); 30 31 __time64_t const filetime_scale{10 * 1000 * 1000}; // 100ns units 32 33 __time64_t const epoch_time{static_cast<__time64_t>(system_time._scalar) - _EPOCH_BIAS}; 34 35 __time64_t const seconds {epoch_time / filetime_scale}; 36 __time64_t const nanoseconds{epoch_time % filetime_scale * 100}; 37 38 if (seconds > static_cast<__time64_t>(time_traits::max_time_t)) 39 { 40 return 0; 41 } 42 43 ts->tv_sec = static_cast<time_type>(seconds); 44 ts->tv_nsec = static_cast<long>(nanoseconds); 45 return base; 46} 47 48extern "C" int __cdecl _timespec32_get(_timespec32* const ts, int const base) 49{ 50 return common_timespec_get<__acrt_GetSystemTimePreciseAsFileTime>(ts, base); 51} 52 53extern "C" int __cdecl _timespec64_get(_timespec64* const ts, int const base) 54{ 55 return common_timespec_get<__acrt_GetSystemTimePreciseAsFileTime>(ts, base); 56} 57 58 59 60// Gets the current system time and converts it to a time_t value. If 'result' 61// is non-null, the time is stored in '*result'. The time is also returned 62// (even if 'result' is null). 63template <typename TimeType> 64static TimeType __cdecl common_time(TimeType* const result) throw() 65{ 66 typedef __crt_time_time_t_traits<TimeType> time_traits; 67 68 typename time_traits::timespec_type ts{}; 69 70 // The resolution of time() is in seconds, so we can afford to use 71 // a less precise, but faster method of getting the time. 72 // GetSystemTimePreciseAsFileTime uses QueryPerformanceCounter which 73 // needs to be virtualized on some systems in order to be accurate, which can 74 // be significantly slower than calling GetSystemTimeAsFileTime. 75 // For example, hypervisors will virtualize QPC calls in order to take into 76 // account virtual machine live migration. 77 // Note that calling the less precise API is still observable because the tick 78 // count may update +/- 15ms, but this should not affect common use of time(). 79 // See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/acquiring-high-resolution-time-stamps 80 // for more details. 81 if (common_timespec_get<GetSystemTimeAsFileTime>(&ts, TIME_UTC) != TIME_UTC) 82 { 83 ts.tv_sec = static_cast<TimeType>(-1); 84 } 85 86 if (result) 87 { 88 *result = ts.tv_sec; 89 } 90 91 return ts.tv_sec; 92} 93 94extern "C" __time32_t __cdecl _time32(__time32_t* const result) 95{ 96 return common_time(result); 97} 98 99extern "C" __time64_t __cdecl _time64(__time64_t* const result) 100{ 101 return common_time(result); 102}