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 static void initializeMutex() { 25 ManagedStaticMutex = new std::recursive_mutex(); 26 } 27 28 static std::recursive_mutex *getManagedStaticMutex() { 29 llvm::call_once(mutex_init_flag, initializeMutex); 30 return ManagedStaticMutex; 31 } 32 33 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 34 void (*Deleter)(void*)) const { 35 assert(Creator); 36 if (llvm_is_multithreaded()) { 37 std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 38 39 if (!Ptr.load(std::memory_order_relaxed)) { 40 void *Tmp = Creator(); 41 42 Ptr.store(Tmp, std::memory_order_release); 43 DeleterFn = Deleter; 44 45 // Add to list of managed statics. 46 Next = StaticList; 47 StaticList = this; 48 } 49 } else { 50 assert(!Ptr && !DeleterFn && !Next && 51 "Partially initialized ManagedStatic!?"); 52 Ptr = Creator(); 53 DeleterFn = Deleter; 54 55 // Add to list of managed statics. 56 Next = StaticList; 57 StaticList = this; 58 } 59 } 60 61 void ManagedStaticBase::destroy() const { 62 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 63 assert(StaticList == this && 64 "Not destroyed in reverse order of construction?"); 65 // Unlink from list. 66 StaticList = Next; 67 Next = nullptr; 68 69 // Destroy memory. 70 DeleterFn(Ptr); 71 72 // Cleanup. 73 Ptr = nullptr; 74 DeleterFn = nullptr; 75 } 76 77 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 78 void llvm::llvm_shutdown() { 79 std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 80 81 while (StaticList) 82 StaticList->destroy(); 83 } 84