1 //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the ManagedStatic class and llvm_shutdown(). 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Support/ManagedStatic.h" 14 #include "llvm/Config/config.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 static llvm::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 llvm::call_once(mutex_init_flag, initializeMutex); 32 return ManagedStaticMutex; 33 } 34 35 #else 36 37 // SwiftShader: from https://reviews.llvm.org/D83372 getManagedStaticMutex()38static std::recursive_mutex *getManagedStaticMutex() { 39 static std::recursive_mutex m; 40 return &m; 41 } 42 43 #endif 44 RegisterManagedStatic(void * (* Creator)(),void (* Deleter)(void *)) const45void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 46 void (*Deleter)(void*)) const { 47 assert(Creator); 48 if (llvm_is_multithreaded()) { 49 std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 50 51 if (!Ptr.load(std::memory_order_relaxed)) { 52 void *Tmp = Creator(); 53 54 Ptr.store(Tmp, std::memory_order_release); 55 DeleterFn = Deleter; 56 57 // Add to list of managed statics. 58 Next = StaticList; 59 StaticList = this; 60 } 61 } else { 62 assert(!Ptr && !DeleterFn && !Next && 63 "Partially initialized ManagedStatic!?"); 64 Ptr = Creator(); 65 DeleterFn = Deleter; 66 67 // Add to list of managed statics. 68 Next = StaticList; 69 StaticList = this; 70 } 71 } 72 destroy() const73void ManagedStaticBase::destroy() const { 74 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 75 assert(StaticList == this && 76 "Not destroyed in reverse order of construction?"); 77 // Unlink from list. 78 StaticList = Next; 79 Next = nullptr; 80 81 // Destroy memory. 82 DeleterFn(Ptr); 83 84 // Cleanup. 85 Ptr = nullptr; 86 DeleterFn = nullptr; 87 } 88 89 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. llvm_shutdown()90void llvm::llvm_shutdown() { 91 // SwiftShader: from https://reviews.llvm.org/D83372 92 // This may be called after the mutex is destroyed. Instead of fixing this, 93 // don't bother locking the mutex, and require llvm_shutdown to be called from 94 // exactly one thread. 95 // std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 96 97 while (StaticList) 98 StaticList->destroy(); 99 } 100