10b57cec5SDimitry Andric //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the ManagedStatic class and llvm_shutdown(). 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Support/ManagedStatic.h" 140b57cec5SDimitry Andric #include "llvm/Config/config.h" 150b57cec5SDimitry Andric #include "llvm/Support/Threading.h" 160b57cec5SDimitry Andric #include <cassert> 178bcb0991SDimitry Andric #include <mutex> 180b57cec5SDimitry Andric using namespace llvm; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric static const ManagedStaticBase *StaticList = nullptr; 210b57cec5SDimitry Andric getManagedStaticMutex()228bcb0991SDimitry Andricstatic std::recursive_mutex *getManagedStaticMutex() { 23*fe6060f1SDimitry Andric static std::recursive_mutex m; 24*fe6060f1SDimitry Andric return &m; 250b57cec5SDimitry Andric } 260b57cec5SDimitry Andric RegisterManagedStatic(void * (* Creator)(),void (* Deleter)(void *)) const270b57cec5SDimitry Andricvoid ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 280b57cec5SDimitry Andric void (*Deleter)(void*)) const { 290b57cec5SDimitry Andric assert(Creator); 300b57cec5SDimitry Andric if (llvm_is_multithreaded()) { 318bcb0991SDimitry Andric std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex()); 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric if (!Ptr.load(std::memory_order_relaxed)) { 340b57cec5SDimitry Andric void *Tmp = Creator(); 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric Ptr.store(Tmp, std::memory_order_release); 370b57cec5SDimitry Andric DeleterFn = Deleter; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric // Add to list of managed statics. 400b57cec5SDimitry Andric Next = StaticList; 410b57cec5SDimitry Andric StaticList = this; 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric } else { 440b57cec5SDimitry Andric assert(!Ptr && !DeleterFn && !Next && 450b57cec5SDimitry Andric "Partially initialized ManagedStatic!?"); 460b57cec5SDimitry Andric Ptr = Creator(); 470b57cec5SDimitry Andric DeleterFn = Deleter; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric // Add to list of managed statics. 500b57cec5SDimitry Andric Next = StaticList; 510b57cec5SDimitry Andric StaticList = this; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric destroy() const550b57cec5SDimitry Andricvoid ManagedStaticBase::destroy() const { 560b57cec5SDimitry Andric assert(DeleterFn && "ManagedStatic not initialized correctly!"); 570b57cec5SDimitry Andric assert(StaticList == this && 580b57cec5SDimitry Andric "Not destroyed in reverse order of construction?"); 590b57cec5SDimitry Andric // Unlink from list. 600b57cec5SDimitry Andric StaticList = Next; 610b57cec5SDimitry Andric Next = nullptr; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Destroy memory. 640b57cec5SDimitry Andric DeleterFn(Ptr); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric // Cleanup. 670b57cec5SDimitry Andric Ptr = nullptr; 680b57cec5SDimitry Andric DeleterFn = nullptr; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 72*fe6060f1SDimitry Andric /// IMPORTANT: it's only safe to call llvm_shutdown() in single thread, 73*fe6060f1SDimitry Andric /// without any other threads executing LLVM APIs. 74*fe6060f1SDimitry Andric /// llvm_shutdown() should be the last use of LLVM APIs. llvm_shutdown()750b57cec5SDimitry Andricvoid llvm::llvm_shutdown() { 760b57cec5SDimitry Andric while (StaticList) 770b57cec5SDimitry Andric StaticList->destroy(); 780b57cec5SDimitry Andric } 79