1f4a2713aSLionel Sambuc //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2f4a2713aSLionel Sambuc // 3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure 4f4a2713aSLionel Sambuc // 5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source 6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details. 7f4a2713aSLionel Sambuc // 8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 9f4a2713aSLionel Sambuc // 10f4a2713aSLionel Sambuc // This file implements the ManagedStatic class and llvm_shutdown(). 11f4a2713aSLionel Sambuc // 12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===// 13f4a2713aSLionel Sambuc 14f4a2713aSLionel Sambuc #include "llvm/Support/ManagedStatic.h" 15f4a2713aSLionel Sambuc #include "llvm/Config/config.h" 16f4a2713aSLionel Sambuc #include "llvm/Support/Atomic.h" 17*0a6a1f1dSLionel Sambuc #include "llvm/Support/Mutex.h" 18*0a6a1f1dSLionel Sambuc #include "llvm/Support/MutexGuard.h" 19f4a2713aSLionel Sambuc #include <cassert> 20f4a2713aSLionel Sambuc using namespace llvm; 21f4a2713aSLionel Sambuc 22*0a6a1f1dSLionel Sambuc static const ManagedStaticBase *StaticList = nullptr; 23*0a6a1f1dSLionel Sambuc getManagedStaticMutex()24*0a6a1f1dSLionel Sambucstatic sys::Mutex& getManagedStaticMutex() { 25*0a6a1f1dSLionel Sambuc // We need to use a function local static here, since this can get called 26*0a6a1f1dSLionel Sambuc // during a static constructor and we need to guarantee that it's initialized 27*0a6a1f1dSLionel Sambuc // correctly. 28*0a6a1f1dSLionel Sambuc static sys::Mutex ManagedStaticMutex; 29*0a6a1f1dSLionel Sambuc return ManagedStaticMutex; 30*0a6a1f1dSLionel Sambuc } 31f4a2713aSLionel Sambuc RegisterManagedStatic(void * (* Creator)(),void (* Deleter)(void *)) const32f4a2713aSLionel Sambucvoid ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 33f4a2713aSLionel Sambuc void (*Deleter)(void*)) const { 34*0a6a1f1dSLionel Sambuc assert(Creator); 35f4a2713aSLionel Sambuc if (llvm_is_multithreaded()) { 36*0a6a1f1dSLionel Sambuc MutexGuard Lock(getManagedStaticMutex()); 37f4a2713aSLionel Sambuc 38*0a6a1f1dSLionel Sambuc if (!Ptr) { 39*0a6a1f1dSLionel Sambuc void* tmp = Creator(); 40f4a2713aSLionel Sambuc 41f4a2713aSLionel Sambuc TsanHappensBefore(this); 42f4a2713aSLionel Sambuc sys::MemoryFence(); 43f4a2713aSLionel Sambuc 44f4a2713aSLionel Sambuc // This write is racy against the first read in the ManagedStatic 45f4a2713aSLionel Sambuc // accessors. The race is benign because it does a second read after a 46f4a2713aSLionel Sambuc // memory fence, at which point it isn't possible to get a partial value. 47f4a2713aSLionel Sambuc TsanIgnoreWritesBegin(); 48f4a2713aSLionel Sambuc Ptr = tmp; 49f4a2713aSLionel Sambuc TsanIgnoreWritesEnd(); 50f4a2713aSLionel Sambuc DeleterFn = Deleter; 51f4a2713aSLionel Sambuc 52f4a2713aSLionel Sambuc // Add to list of managed statics. 53f4a2713aSLionel Sambuc Next = StaticList; 54f4a2713aSLionel Sambuc StaticList = this; 55f4a2713aSLionel Sambuc } 56f4a2713aSLionel Sambuc } else { 57*0a6a1f1dSLionel Sambuc assert(!Ptr && !DeleterFn && !Next && 58f4a2713aSLionel Sambuc "Partially initialized ManagedStatic!?"); 59*0a6a1f1dSLionel Sambuc Ptr = Creator(); 60f4a2713aSLionel Sambuc DeleterFn = Deleter; 61f4a2713aSLionel Sambuc 62f4a2713aSLionel Sambuc // Add to list of managed statics. 63f4a2713aSLionel Sambuc Next = StaticList; 64f4a2713aSLionel Sambuc StaticList = this; 65f4a2713aSLionel Sambuc } 66f4a2713aSLionel Sambuc } 67f4a2713aSLionel Sambuc destroy() const68f4a2713aSLionel Sambucvoid ManagedStaticBase::destroy() const { 69f4a2713aSLionel Sambuc assert(DeleterFn && "ManagedStatic not initialized correctly!"); 70f4a2713aSLionel Sambuc assert(StaticList == this && 71f4a2713aSLionel Sambuc "Not destroyed in reverse order of construction?"); 72f4a2713aSLionel Sambuc // Unlink from list. 73f4a2713aSLionel Sambuc StaticList = Next; 74*0a6a1f1dSLionel Sambuc Next = nullptr; 75f4a2713aSLionel Sambuc 76f4a2713aSLionel Sambuc // Destroy memory. 77f4a2713aSLionel Sambuc DeleterFn(Ptr); 78f4a2713aSLionel Sambuc 79f4a2713aSLionel Sambuc // Cleanup. 80*0a6a1f1dSLionel Sambuc Ptr = nullptr; 81*0a6a1f1dSLionel Sambuc DeleterFn = nullptr; 82f4a2713aSLionel Sambuc } 83f4a2713aSLionel Sambuc 84f4a2713aSLionel Sambuc /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. llvm_shutdown()85f4a2713aSLionel Sambucvoid llvm::llvm_shutdown() { 86*0a6a1f1dSLionel Sambuc MutexGuard Lock(getManagedStaticMutex()); 87*0a6a1f1dSLionel Sambuc 88f4a2713aSLionel Sambuc while (StaticList) 89f4a2713aSLionel Sambuc StaticList->destroy(); 90f4a2713aSLionel Sambuc } 91