diff options
author | Stephen Toub <stoub@microsoft.com> | 2017-10-02 15:17:58 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-02 15:17:58 -0400 |
commit | 0e8bc684c6e15591708d49a773183fb6cd9eda34 (patch) | |
tree | a7291f68977c07bfe87d97f245f5b04043022649 /src/classlibnative | |
parent | b5d08755c552961640df581ff532e87d187a4be3 (diff) | |
download | coreclr-0e8bc684c6e15591708d49a773183fb6cd9eda34.tar.gz coreclr-0e8bc684c6e15591708d49a773183fb6cd9eda34.tar.bz2 coreclr-0e8bc684c6e15591708d49a773183fb6cd9eda34.zip |
Workaround GetSystemTimePreciseAsFileTime inaccuracies (#14283)
* Workaround GetSystemTimePreciseAsFileTime inaccuracies
On misconfigured systems, GetSystemTimePreciseAsFileTime may drift quickly from GetSystemTimeAsFileTime. We want to use the former, though. As a workaround/heuristic, when checking whether we have GetSystemTimePreciseAsFileTime, invoke both and ensure they're "close", falling back to GetSystemTimeAsFileTime if it seems like the precise variant has run away.
* Update comment
Diffstat (limited to 'src/classlibnative')
-rw-r--r-- | src/classlibnative/bcltype/system.cpp | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index 4e13bd1876..11b7107a65 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -53,6 +53,33 @@ void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) if (hKernel32 != NULL) { func = (pfnGetSystemTimeAsFileTime)GetProcAddress(hKernel32, "GetSystemTimePreciseAsFileTime"); + if (func != NULL) + { + // GetSystemTimePreciseAsFileTime exists and we'd like to use it. However, on + // misconfigured systems, it's possible for the "precise" time to be inaccurate: + // https://github.com/dotnet/coreclr/issues/14187 + // If it's inaccurate, though, we expect it to be wildly inaccurate, so as a + // workaround/heuristic, we get both the "normal" and "precise" times, and as + // long as they're close, we use the precise one. This workaround can be removed + // when we better understand what's causing the drift and the issue is no longer + // a problem or can be better worked around on all targeted OSes. + + FILETIME systemTimeResult; + ::GetSystemTimeAsFileTime(&systemTimeResult); + + FILETIME preciseSystemTimeResult; + func(&preciseSystemTimeResult); + + LONG64 systemTimeLong100ns = (LONG64)((((ULONG64)systemTimeResult.dwHighDateTime) << 32) | (ULONG64)systemTimeResult.dwLowDateTime); + LONG64 preciseSystemTimeLong100ns = (LONG64)((((ULONG64)preciseSystemTimeResult.dwHighDateTime) << 32) | (ULONG64)preciseSystemTimeResult.dwLowDateTime); + + const INT32 THRESHOLD_100NS = 1000000; // 100ms + if (abs(preciseSystemTimeLong100ns - systemTimeLong100ns) > THRESHOLD_100NS) + { + // Too much difference. Don't use GetSystemTimePreciseAsFileTime. + func = NULL; + } + } } if (func == NULL) #endif |