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 "llvm/Support/Mutex.h" 18 #include "llvm/Support/MutexGuard.h" 19 #include "llvm/Support/Threading.h" 20 #include <cassert> 21 using namespace llvm; 22 23 static const ManagedStaticBase *StaticList = nullptr; 24 static sys::Mutex *ManagedStaticMutex = nullptr; 25 LLVM_DEFINE_ONCE_FLAG(mutex_init_flag); 26 27 static void initializeMutex() { 28 ManagedStaticMutex = new sys::Mutex(); 29 } 30 31 static sys::Mutex* getManagedStaticMutex() { 32 // We need to use a function local static here, since this can get called 33 // during a static constructor and we need to guarantee that it's initialized 34 // correctly. 35 call_once(mutex_init_flag, initializeMutex); 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 MutexGuard 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 MutexGuard Lock(*getManagedStaticMutex()); 94 95 while (StaticList) 96 StaticList->destroy(); 97 } 98