1 //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the ManagedStatic class and llvm_shutdown(). 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Support/ManagedStatic.h" 15 #include "llvm/Config/config.h" 16 #include "llvm/Support/Atomic.h" 17 #include <cassert> 18 #include <mutex> 19 using namespace llvm; 20 21 static const ManagedStaticBase *StaticList = nullptr; 22 23 // ManagedStatics can get created during execution of static constructors. As a 24 // result, we cannot use a global static std::mutex object for the lock since it 25 // may not have been constructed. Instead, we do a call-once initialization of 26 // a pointer to a mutex. 27 static std::once_flag MutexInitializationFlag; 28 static std::recursive_mutex* ManagedStaticMutex = nullptr; 29 30 // Not all supported platforms (in particular VS2012) have thread-safe function 31 // static initialization, so roll our own. 32 static std::recursive_mutex& GetManagedStaticMutex() { 33 std::call_once(MutexInitializationFlag, 34 []() { ManagedStaticMutex = new std::recursive_mutex(); } ); 35 36 return *ManagedStaticMutex; 37 } 38 39 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 40 void (*Deleter)(void*)) const { 41 assert(Creator); 42 if (llvm_is_multithreaded()) { 43 std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex()); 44 45 if (!Ptr) { 46 void* tmp = Creator(); 47 48 TsanHappensBefore(this); 49 sys::MemoryFence(); 50 51 // This write is racy against the first read in the ManagedStatic 52 // accessors. The race is benign because it does a second read after a 53 // memory fence, at which point it isn't possible to get a partial value. 54 TsanIgnoreWritesBegin(); 55 Ptr = tmp; 56 TsanIgnoreWritesEnd(); 57 DeleterFn = Deleter; 58 59 // Add to list of managed statics. 60 Next = StaticList; 61 StaticList = this; 62 } 63 } else { 64 assert(!Ptr && !DeleterFn && !Next && 65 "Partially initialized ManagedStatic!?"); 66 Ptr = Creator(); 67 DeleterFn = Deleter; 68 69 // Add to list of managed statics. 70 Next = StaticList; 71 StaticList = this; 72 } 73 } 74 75 void ManagedStaticBase::destroy() const { 76 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 77 assert(StaticList == this && 78 "Not destroyed in reverse order of construction?"); 79 // Unlink from list. 80 StaticList = Next; 81 Next = nullptr; 82 83 // Destroy memory. 84 DeleterFn(Ptr); 85 86 // Cleanup. 87 Ptr = nullptr; 88 DeleterFn = nullptr; 89 } 90 91 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 92 void llvm::llvm_shutdown() { 93 std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex()); 94 95 while (StaticList) 96 StaticList->destroy(); 97 } 98