1f22ef01cSRoman Divacky //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2f22ef01cSRoman Divacky // 3f22ef01cSRoman Divacky // The LLVM Compiler Infrastructure 4f22ef01cSRoman Divacky // 5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source 6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details. 7f22ef01cSRoman Divacky // 8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 9f22ef01cSRoman Divacky // 10f22ef01cSRoman Divacky // This file implements the ManagedStatic class and llvm_shutdown(). 11f22ef01cSRoman Divacky // 12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===// 13f22ef01cSRoman Divacky 14f22ef01cSRoman Divacky #include "llvm/Support/ManagedStatic.h" 15f22ef01cSRoman Divacky #include "llvm/Config/config.h" 1691bc56edSDimitry Andric #include "llvm/Support/Mutex.h" 1791bc56edSDimitry Andric #include "llvm/Support/MutexGuard.h" 183ca95b02SDimitry Andric #include "llvm/Support/Threading.h" 19f22ef01cSRoman Divacky #include <cassert> 20f22ef01cSRoman Divacky using namespace llvm; 21f22ef01cSRoman Divacky 2291bc56edSDimitry Andric static const ManagedStaticBase *StaticList = nullptr; 233ca95b02SDimitry Andric static sys::Mutex *ManagedStaticMutex = nullptr; 247a7e6055SDimitry Andric static llvm::once_flag mutex_init_flag; 2591bc56edSDimitry Andric initializeMutex()263ca95b02SDimitry Andricstatic void initializeMutex() { 273ca95b02SDimitry Andric ManagedStaticMutex = new sys::Mutex(); 283ca95b02SDimitry Andric } 293ca95b02SDimitry Andric getManagedStaticMutex()303ca95b02SDimitry Andricstatic sys::Mutex* getManagedStaticMutex() { 313ca95b02SDimitry Andric llvm::call_once(mutex_init_flag, initializeMutex); 3291bc56edSDimitry Andric return ManagedStaticMutex; 3391bc56edSDimitry Andric } 34f22ef01cSRoman Divacky RegisterManagedStatic(void * (* Creator)(),void (* Deleter)(void *)) const35f22ef01cSRoman Divackyvoid ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 36f22ef01cSRoman Divacky void (*Deleter)(void*)) const { 3791bc56edSDimitry Andric assert(Creator); 38f22ef01cSRoman Divacky if (llvm_is_multithreaded()) { 393ca95b02SDimitry Andric MutexGuard Lock(*getManagedStaticMutex()); 40f22ef01cSRoman Divacky 413ca95b02SDimitry Andric if (!Ptr.load(std::memory_order_relaxed)) { 423ca95b02SDimitry Andric void *Tmp = Creator(); 43f22ef01cSRoman Divacky 443ca95b02SDimitry Andric Ptr.store(Tmp, std::memory_order_release); 45f22ef01cSRoman Divacky DeleterFn = Deleter; 46f22ef01cSRoman Divacky 47f22ef01cSRoman Divacky // Add to list of managed statics. 48f22ef01cSRoman Divacky Next = StaticList; 49f22ef01cSRoman Divacky StaticList = this; 50f22ef01cSRoman Divacky } 51f22ef01cSRoman Divacky } else { 5291bc56edSDimitry Andric assert(!Ptr && !DeleterFn && !Next && 53f22ef01cSRoman Divacky "Partially initialized ManagedStatic!?"); 5491bc56edSDimitry Andric Ptr = Creator(); 55f22ef01cSRoman Divacky DeleterFn = Deleter; 56f22ef01cSRoman Divacky 57f22ef01cSRoman Divacky // Add to list of managed statics. 58f22ef01cSRoman Divacky Next = StaticList; 59f22ef01cSRoman Divacky StaticList = this; 60f22ef01cSRoman Divacky } 61f22ef01cSRoman Divacky } 62f22ef01cSRoman Divacky destroy() const63f22ef01cSRoman Divackyvoid ManagedStaticBase::destroy() const { 64f22ef01cSRoman Divacky assert(DeleterFn && "ManagedStatic not initialized correctly!"); 65f22ef01cSRoman Divacky assert(StaticList == this && 66f22ef01cSRoman Divacky "Not destroyed in reverse order of construction?"); 67f22ef01cSRoman Divacky // Unlink from list. 68f22ef01cSRoman Divacky StaticList = Next; 6991bc56edSDimitry Andric Next = nullptr; 70f22ef01cSRoman Divacky 71f22ef01cSRoman Divacky // Destroy memory. 72f22ef01cSRoman Divacky DeleterFn(Ptr); 73f22ef01cSRoman Divacky 74f22ef01cSRoman Divacky // Cleanup. 7591bc56edSDimitry Andric Ptr = nullptr; 7691bc56edSDimitry Andric DeleterFn = nullptr; 77f22ef01cSRoman Divacky } 78f22ef01cSRoman Divacky 79f22ef01cSRoman Divacky /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. llvm_shutdown()80f22ef01cSRoman Divackyvoid llvm::llvm_shutdown() { 813ca95b02SDimitry Andric MutexGuard Lock(*getManagedStaticMutex()); 8291bc56edSDimitry Andric 83f22ef01cSRoman Divacky while (StaticList) 84f22ef01cSRoman Divacky StaticList->destroy(); 85f22ef01cSRoman Divacky } 86