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/Support/Threading.h" 16 #include <cassert> 17 #include <mutex> 18 using namespace llvm; 19 20 static const ManagedStaticBase *StaticList = nullptr; 21 static std::recursive_mutex *ManagedStaticMutex = nullptr; 22 LLVM_DEFINE_ONCE_FLAG(mutex_init_flag); 23 24 #if 0 25 26 static void initializeMutex() { 27 ManagedStaticMutex = new std::recursive_mutex(); 28 } 29 30 static std::recursive_mutex* getManagedStaticMutex() { 31 // We need to use a function local static here, since this can get called 32 // during a static constructor and we need to guarantee that it's initialized 33 // correctly. 34 llvm::call_once(mutex_init_flag, initializeMutex); 35 return ManagedStaticMutex; 36 } 37 38 #else 39 40 // SwiftShader: from https://reviews.llvm.org/D83372 getManagedStaticMutex()41static std::recursive_mutex *getManagedStaticMutex() { 42 static std::recursive_mutex m; 43 return &m; 44 } 45 46 #endif 47 RegisterManagedStatic(void * (* Creator)(),void (* Deleter)(void *)) const48void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 49 void (*Deleter)(void*)) const { 50 assert(Creator); 51 std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 52 53 if (!Ptr.load(std::memory_order_relaxed)) { 54 void *Tmp = Creator(); 55 56 Ptr.store(Tmp, std::memory_order_release); 57 DeleterFn = Deleter; 58 59 // Add to list of managed statics. 60 Next = StaticList; 61 StaticList = this; 62 } 63 } 64 destroy() const65void ManagedStaticBase::destroy() const { 66 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 67 assert(StaticList == this && 68 "Not destroyed in reverse order of construction?"); 69 // Unlink from list. 70 StaticList = Next; 71 Next = nullptr; 72 73 // Destroy memory. 74 DeleterFn(Ptr); 75 76 // Cleanup. 77 Ptr = nullptr; 78 DeleterFn = nullptr; 79 } 80 81 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. llvm_shutdown()82void llvm::llvm_shutdown() { 83 // SwiftShader: from https://reviews.llvm.org/D83372 84 // This may be called after the mutex is destroyed. Instead of fixing this, 85 // don't bother locking the mutex, and require llvm_shutdown to be called from 86 // exactly one thread. 87 // std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 88 89 while (StaticList) 90 StaticList->destroy(); 91 } 92