[Support] Fix a race initializing a static local in MSVC
authorReid Kleckner <reid@kleckner.net>
Thu, 11 Jun 2015 22:22:45 +0000 (22:22 +0000)
committerReid Kleckner <reid@kleckner.net>
Thu, 11 Jun 2015 22:22:45 +0000 (22:22 +0000)
static local initialization isn't thread safe with MSVC and a race was
reported in PR23817. We can't use std::atomic because it's not trivially
constructible, so instead do some lame volatile global integer
manipulation.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239566 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/Windows/Memory.inc

index ae8371abf5b340689c5a0af526b2f1fed924ce0a..4b2ff2e2d3241149243c1659952e0b827b11c475 100644 (file)
@@ -78,7 +78,15 @@ MemoryBlock Memory::allocateMappedMemory(size_t NumBytes,
   // While we'd be happy to allocate single pages, the Windows allocation
   // granularity may be larger than a single page (in practice, it is 64K)
   // so mapping less than that will create an unreachable fragment of memory.
-  static const size_t Granularity = getAllocationGranularity();
+  // Avoid using one-time initialization of static locals here, since they
+  // aren't thread safe with MSVC.
+  static volatile size_t GranularityCached;
+  size_t Granularity = GranularityCached;
+  if (Granularity == 0) {
+    Granularity = getAllocationGranularity();
+    GranularityCached = Granularity;
+  }
+
   const size_t NumBlocks = (NumBytes+Granularity-1)/Granularity;
 
   uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +