ManagedStatic.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
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> 20using namespace llvm; 21 22static const ManagedStaticBase *StaticList = nullptr; 23 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 32void 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 68void 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. 85void llvm::llvm_shutdown() { 86 MutexGuard Lock(getManagedStaticMutex()); 87 88 while (StaticList) 89 StaticList->destroy(); 90} 91