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