简体   繁体   中英

What clock does the Visual Studio 2017 CRT implementation of std::chrono::system_time use?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM