LLVM API Documentation
00001 //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the ManagedStatic class and llvm_shutdown(). 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/Support/ManagedStatic.h" 00015 #include "llvm/Config/config.h" 00016 #include "llvm/Support/Atomic.h" 00017 #include "llvm/Support/Mutex.h" 00018 #include "llvm/Support/MutexGuard.h" 00019 #include <cassert> 00020 using namespace llvm; 00021 00022 static const ManagedStaticBase *StaticList = nullptr; 00023 00024 static sys::Mutex& getManagedStaticMutex() { 00025 // We need to use a function local static here, since this can get called 00026 // during a static constructor and we need to guarantee that it's initialized 00027 // correctly. 00028 static sys::Mutex ManagedStaticMutex; 00029 return ManagedStaticMutex; 00030 } 00031 00032 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 00033 void (*Deleter)(void*)) const { 00034 assert(Creator); 00035 if (llvm_is_multithreaded()) { 00036 MutexGuard Lock(getManagedStaticMutex()); 00037 00038 if (!Ptr) { 00039 void* tmp = Creator(); 00040 00041 TsanHappensBefore(this); 00042 sys::MemoryFence(); 00043 00044 // This write is racy against the first read in the ManagedStatic 00045 // accessors. The race is benign because it does a second read after a 00046 // memory fence, at which point it isn't possible to get a partial value. 00047 TsanIgnoreWritesBegin(); 00048 Ptr = tmp; 00049 TsanIgnoreWritesEnd(); 00050 DeleterFn = Deleter; 00051 00052 // Add to list of managed statics. 00053 Next = StaticList; 00054 StaticList = this; 00055 } 00056 } else { 00057 assert(!Ptr && !DeleterFn && !Next && 00058 "Partially initialized ManagedStatic!?"); 00059 Ptr = Creator(); 00060 DeleterFn = Deleter; 00061 00062 // Add to list of managed statics. 00063 Next = StaticList; 00064 StaticList = this; 00065 } 00066 } 00067 00068 void ManagedStaticBase::destroy() const { 00069 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 00070 assert(StaticList == this && 00071 "Not destroyed in reverse order of construction?"); 00072 // Unlink from list. 00073 StaticList = Next; 00074 Next = nullptr; 00075 00076 // Destroy memory. 00077 DeleterFn(Ptr); 00078 00079 // Cleanup. 00080 Ptr = nullptr; 00081 DeleterFn = nullptr; 00082 } 00083 00084 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 00085 void llvm::llvm_shutdown() { 00086 MutexGuard Lock(getManagedStaticMutex()); 00087 00088 while (StaticList) 00089 StaticList->destroy(); 00090 }