summaryrefslogtreecommitdiff
path: root/src/classlibnative
diff options
context:
space:
mode:
authorStephen Toub <stoub@microsoft.com>2017-10-02 15:17:58 -0400
committerGitHub <noreply@github.com>2017-10-02 15:17:58 -0400
commit0e8bc684c6e15591708d49a773183fb6cd9eda34 (patch)
treea7291f68977c07bfe87d97f245f5b04043022649 /src/classlibnative
parentb5d08755c552961640df581ff532e87d187a4be3 (diff)
downloadcoreclr-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.cpp27
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