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