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 22 static std::recursive_mutex *getManagedStaticMutex() { 23 static std::recursive_mutex m; 24 return &m; 25 } 26 27 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 28 void (*Deleter)(void*)) const { 29 assert(Creator); 30 if (llvm_is_multithreaded()) { 31 std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 32 33 if (!Ptr.load(std::memory_order_relaxed)) { 34 void *Tmp = Creator(); 35 36 Ptr.store(Tmp, std::memory_order_release); 37 DeleterFn = Deleter; 38 39 // Add to list of managed statics. 40 Next = StaticList; 41 StaticList = this; 42 } 43 } else { 44 assert(!Ptr && !DeleterFn && !Next && 45 "Partially initialized ManagedStatic!?"); 46 Ptr = Creator(); 47 DeleterFn = Deleter; 48 49 // Add to list of managed statics. 50 Next = StaticList; 51 StaticList = this; 52 } 53 } 54 55 void ManagedStaticBase::destroy() const { 56 assert(DeleterFn && "ManagedStatic not initialized correctly!"); 57 assert(StaticList == this && 58 "Not destroyed in reverse order of construction?"); 59 // Unlink from list. 60 StaticList = Next; 61 Next = nullptr; 62 63 // Destroy memory. 64 DeleterFn(Ptr); 65 66 // Cleanup. 67 Ptr = nullptr; 68 DeleterFn = nullptr; 69 } 70 71 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 72 /// IMPORTANT: it's only safe to call llvm_shutdown() in single thread, 73 /// without any other threads executing LLVM APIs. 74 /// llvm_shutdown() should be the last use of LLVM APIs. 75 void llvm::llvm_shutdown() { 76 while (StaticList) 77 StaticList->destroy(); 78 } 79