Fix race condition in g_pfnGetSystemTimeAsFileTime initialization (dotnet/coreclr...
authorJan Kotas <jkotas@microsoft.com>
Fri, 8 Feb 2019 02:35:15 +0000 (18:35 -0800)
committerGitHub <noreply@github.com>
Fri, 8 Feb 2019 02:35:15 +0000 (18:35 -0800)
Multiple threads initializing g_pfnGetSystemTimeAsFileTime at the same time can end up with different conclusions. Make the result consistent.

Commit migrated from https://github.com/dotnet/coreclr/commit/b1f73285236049c8e922ff6652e2a917db89454f

src/coreclr/src/classlibnative/bcltype/system.cpp

index 944cda0..37c8b11 100644 (file)
@@ -31,6 +31,7 @@
 #include "array.h"
 #include "eepolicy.h"
 
+#ifndef FEATURE_PAL
 typedef void(WINAPI *pfnGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTime);
 extern pfnGetSystemTimeAsFileTime g_pfnGetSystemTimeAsFileTime;
 
@@ -38,7 +39,6 @@ void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
 {
     pfnGetSystemTimeAsFileTime func = NULL;
 
-#ifndef FEATURE_PAL
     HMODULE hKernel32 = WszLoadLibrary(W("kernel32.dll"));
     if (hKernel32 != NULL)
     {
@@ -72,23 +72,28 @@ void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
         }
     }
     if (func == NULL)
-#endif
     {
         func = &::GetSystemTimeAsFileTime;
     }
 
-    g_pfnGetSystemTimeAsFileTime = func;
-    func(lpSystemTimeAsFileTime);
+    InterlockedCompareExchangeT(&g_pfnGetSystemTimeAsFileTime, func, &InitializeGetSystemTimeAsFileTime);
+
+    g_pfnGetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
 }
 
 pfnGetSystemTimeAsFileTime g_pfnGetSystemTimeAsFileTime = &InitializeGetSystemTimeAsFileTime;
+#endif // FEATURE_PAL
 
 FCIMPL0(INT64, SystemNative::__GetSystemTimeAsFileTime)
 {
     FCALL_CONTRACT;
 
     INT64 timestamp;
+#ifndef FEATURE_PAL
     g_pfnGetSystemTimeAsFileTime((FILETIME*)&timestamp);
+#else
+    GetSystemTimeAsFileTime((FILETIME*)&timestamp);
+#endif
 
 #if BIGENDIAN
     timestamp = (INT64)(((UINT64)timestamp >> 32) | ((UINT64)timestamp << 32));