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 26 static void initializeMutex() { 27 ManagedStaticMutex = new sys::Mutex(); 28 } 29 30 static sys::Mutex* getManagedStaticMutex() { 31 // We need to use a function local static here, since this can get called 32 // during a static constructor and we need to guarantee that it's initialized 33 // correctly. 34 llvm_call_once<initializeMutex>(); 35 return ManagedStaticMutex; 36 } 37 38 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 39 void (*Deleter)(void*)) const { 40 assert(Creator); 41 if (llvm_is_multithreaded()) { 42 MutexGuard Lock(*getManagedStaticMutex()); 43 44 if (!Ptr) { 45 void* tmp = Creator(); 46 47 TsanHappensBefore(this); 48 sys::MemoryFence(); 49 50 // This write is racy against the first read in the ManagedStatic 51 // accessors. The race is benign because it does a second read after a 52 // memory fence, at which point it isn't possible to get a partial value. 53 TsanIgnoreWritesBegin(); 54 Ptr = tmp; 55 TsanIgnoreWritesEnd(); 56 DeleterFn = Deleter; 57 58 // Add to list of managed statics. 59 Next = StaticList; 60 StaticList = this; 61 } 62 } else { 63 assert(!Ptr && !DeleterFn && !Next && 64 "Partially initialized ManagedStatic!?"); 65 Ptr = Creator(); 66 DeleterFn = Deleter; 67 68 // Add to list of managed statics. 69 Next = StaticList; 70 StaticList = this; 71 } 72 } 73 74 void ManagedStaticBase::destroy() const { 75 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 76 assert(StaticList == this && 77 "Not destroyed in reverse order of construction?"); 78 // Unlink from list. 79 StaticList = Next; 80 Next = nullptr; 81 82 // Destroy memory. 83 DeleterFn(Ptr); 84 85 // Cleanup. 86 Ptr = nullptr; 87 DeleterFn = nullptr; 88 } 89 90 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 91 void llvm::llvm_shutdown() { 92 { 93 MutexGuard Lock(*getManagedStaticMutex()); 94 95 while (StaticList) 96 StaticList->destroy(); 97 } 98 99 delete ManagedStaticMutex; 100 ManagedStaticMutex = nullptr; 101 } 102