1193323Sed//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the ManagedStatic class and llvm_shutdown(). 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "llvm/Support/ManagedStatic.h" 15193323Sed#include "llvm/Config/config.h" 16218893Sdim#include "llvm/Support/Atomic.h" 17193323Sed#include <cassert> 18193323Sedusing namespace llvm; 19193323Sed 20193323Sedstatic const ManagedStaticBase *StaticList = 0; 21193323Sed 22193323Sedvoid ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 23193323Sed void (*Deleter)(void*)) const { 24194612Sed if (llvm_is_multithreaded()) { 25194612Sed llvm_acquire_global_lock(); 26193323Sed 27193323Sed if (Ptr == 0) { 28193323Sed void* tmp = Creator ? Creator() : 0; 29193323Sed 30234353Sdim TsanHappensBefore(this); 31193323Sed sys::MemoryFence(); 32234353Sdim 33234353Sdim // This write is racy against the first read in the ManagedStatic 34234353Sdim // accessors. The race is benign because it does a second read after a 35234353Sdim // memory fence, at which point it isn't possible to get a partial value. 36234353Sdim TsanIgnoreWritesBegin(); 37193323Sed Ptr = tmp; 38234353Sdim TsanIgnoreWritesEnd(); 39193323Sed DeleterFn = Deleter; 40193323Sed 41193323Sed // Add to list of managed statics. 42193323Sed Next = StaticList; 43193323Sed StaticList = this; 44193323Sed } 45193323Sed 46194612Sed llvm_release_global_lock(); 47193323Sed } else { 48193323Sed assert(Ptr == 0 && DeleterFn == 0 && Next == 0 && 49193323Sed "Partially initialized ManagedStatic!?"); 50193323Sed Ptr = Creator ? Creator() : 0; 51193323Sed DeleterFn = Deleter; 52193323Sed 53193323Sed // Add to list of managed statics. 54193323Sed Next = StaticList; 55193323Sed StaticList = this; 56193323Sed } 57193323Sed} 58193323Sed 59193323Sedvoid ManagedStaticBase::destroy() const { 60193323Sed assert(DeleterFn && "ManagedStatic not initialized correctly!"); 61193323Sed assert(StaticList == this && 62193323Sed "Not destroyed in reverse order of construction?"); 63193323Sed // Unlink from list. 64193323Sed StaticList = Next; 65193323Sed Next = 0; 66193323Sed 67193323Sed // Destroy memory. 68193323Sed DeleterFn(Ptr); 69193323Sed 70193323Sed // Cleanup. 71193323Sed Ptr = 0; 72193323Sed DeleterFn = 0; 73193323Sed} 74193323Sed 75193323Sed/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 76193323Sedvoid llvm::llvm_shutdown() { 77193323Sed while (StaticList) 78193323Sed StaticList->destroy(); 79193323Sed 80194612Sed if (llvm_is_multithreaded()) llvm_stop_multithreaded(); 81193323Sed} 82