Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 2a5b736

Browse files
authored
Workaround GetSystemTimePreciseAsFileTime inaccuracies (#14283) (#14319)
* 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
1 parent f4a3040 commit 2a5b736

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/classlibnative/bcltype/system.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,33 @@ void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
5353
if (hKernel32 != NULL)
5454
{
5555
func = (pfnGetSystemTimeAsFileTime)GetProcAddress(hKernel32, "GetSystemTimePreciseAsFileTime");
56+
if (func != NULL)
57+
{
58+
// GetSystemTimePreciseAsFileTime exists and we'd like to use it. However, on
59+
// misconfigured systems, it's possible for the "precise" time to be inaccurate:
60+
// https://github.com/dotnet/coreclr/issues/14187
61+
// If it's inaccurate, though, we expect it to be wildly inaccurate, so as a
62+
// workaround/heuristic, we get both the "normal" and "precise" times, and as
63+
// long as they're close, we use the precise one. This workaround can be removed
64+
// when we better understand what's causing the drift and the issue is no longer
65+
// a problem or can be better worked around on all targeted OSes.
66+
67+
FILETIME systemTimeResult;
68+
::GetSystemTimeAsFileTime(&systemTimeResult);
69+
70+
FILETIME preciseSystemTimeResult;
71+
func(&preciseSystemTimeResult);
72+
73+
LONG64 systemTimeLong100ns = (LONG64)((((ULONG64)systemTimeResult.dwHighDateTime) << 32) | (ULONG64)systemTimeResult.dwLowDateTime);
74+
LONG64 preciseSystemTimeLong100ns = (LONG64)((((ULONG64)preciseSystemTimeResult.dwHighDateTime) << 32) | (ULONG64)preciseSystemTimeResult.dwLowDateTime);
75+
76+
const INT32 THRESHOLD_100NS = 1000000; // 100ms
77+
if (abs(preciseSystemTimeLong100ns - systemTimeLong100ns) > THRESHOLD_100NS)
78+
{
79+
// Too much difference. Don't use GetSystemTimePreciseAsFileTime.
80+
func = NULL;
81+
}
82+
}
5683
}
5784
if (func == NULL)
5885
#endif

0 commit comments

Comments
 (0)