The comments in the chrono header just says
// wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
But which does it actually use (ie what precision can I expect)? The implementation calls _Xtime_get_ticks
, but that function is opaque.
long long _Xtime_get_ticks()
{ /* get system time in 100-nanosecond intervals since the epoch */
FILETIME ft;
__crtGetSystemTimePreciseAsFileTime(&ft);
return ((((long long)ft.dwHighDateTime) << 32)
+ (long long)ft.dwLowDateTime - EPOCH);
}
The CRT calls GetSystemTimePreciseAsFileTime
when available and GetSystemTimeAsFileTime
otherwise. GetSystemTimePreciseAsFileTime
gives you the highest possible level of precision (<1us) .
Sometime during the initialization of the runtime, a function named initialize_pointers
gets called which basically does the following (decompiled and simplified):
HMODULE hModule = GetModuleHandleW(L"kernel32.dll");
__encodedKERNEL32Functions[0] = (void *)GetProcAddress(hModule, "FlsAlloc");
__encodedKERNEL32Functions[1] = (void *)GetProcAddress(hModule, "FlsFree");
__encodedKERNEL32Functions[2] = (void *)GetProcAddress(hModule, "FlsGetValue");
__encodedKERNEL32Functions[3] = (void *)GetProcAddress(hModule, "FlsSetValue");
...
__encodedKERNEL32Functions[24] = (void *)GetProcAddress(hModule, "GetSystemTimePreciseAsFileTime");
...
On a system with Windows 8 or newer __encodedKERNEL32Functions[24]
will be non-zero.
It then comes down to this:
std::chrono::system_clock::now()
-> _Xtime_get_ticks
-> __crtGetSystemTimePreciseAsFileTime(FILETIME *)
void __crtGetSystemTimePreciseAsFileTime(FILETIME *lpSystemTimeAsFileTime)
{
void (*f)(FILETIME *) = (void (*)(FILETIME *))__encodedKERNEL32Functions[24];
if (f) // if GetSystemTimePreciseAsFileTime exists
f(lpSystemTimeAsFileTime); // call it
else
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
}
At least this is (approximately) how it's implemented in the 14.16.27024.1 version of msvcp140.dll and msvcp140d.dll .
All of this is of course undocumented and subject to change.
If you need to use GetSystemTimePreciseAsFileTime
you should write your own clock and not rely on implementation details.
Let's do some research here. First, let's find " _Xtime_get_ticks
" in the Visual C++ runtime library:
C:\Windows\SysWOW64>dumpbin /exports msvcp140.dll|findstr /I "Xtime"
1483 5CA 0000B5D0 _Xtime_diff_to_millis
1484 5CB 0000B610 _Xtime_diff_to_millis2
1485 5CC 0000B650 _Xtime_get_ticks
1515 5EA 0000B730 xtime_get
Then, I use dumpbin /disasm msvcp140.dll
with msvcp140.i386.pdb
file in the same directory:
__Xtime_get_ticks:
1000B650: ... boilerplate ...
1000B659: E8 22 50 02 00 call ___crtGetSystemTimePreciseAsFileTime
There is no call
instruction for GetSystemTimeAsFileTime
anywhere in this disassembled function, so it seems clear that GetSystemTimePreciseAsFileTime
is indeed the only function that is called for the underlying implementation.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.