1771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===// 2771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// 3771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// The LLVM Compiler Infrastructure 4771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// 8771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//===----------------------------------------------------------------------===// 9771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// 10771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// This file implements the ManagedStatic class and llvm_shutdown(). 11771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner// 12771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner//===----------------------------------------------------------------------===// 13771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 14771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner#include "llvm/Support/ManagedStatic.h" 15b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson#include "llvm/Config/config.h" 161f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Atomic.h" 17cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/Mutex.h" 18cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "llvm/Support/MutexGuard.h" 19771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner#include <cassert> 20771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnerusing namespace llvm; 21771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 22dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic const ManagedStaticBase *StaticList = nullptr; 23771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 24cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesstatic sys::Mutex& getManagedStaticMutex() { 25cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // We need to use a function local static here, since this can get called 26cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // during a static constructor and we need to guarantee that it's initialized 27cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines // correctly. 28cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines static sys::Mutex ManagedStaticMutex; 29cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines return ManagedStaticMutex; 30cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines} 31cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 32b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Andersonvoid ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(), 33771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner void (*Deleter)(void*)) const { 34dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(Creator); 354c7ac18fc9e9af51ea6362871589c13263526d7aOwen Anderson if (llvm_is_multithreaded()) { 36cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines MutexGuard Lock(getManagedStaticMutex()); 37b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson 38dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (!Ptr) { 39dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines void* tmp = Creator(); 40b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson 414d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky TsanHappensBefore(this); 42b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson sys::MemoryFence(); 434d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky 444d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky // This write is racy against the first read in the ManagedStatic 454d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky // accessors. The race is benign because it does a second read after a 464d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky // memory fence, at which point it isn't possible to get a partial value. 474d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky TsanIgnoreWritesBegin(); 48b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson Ptr = tmp; 494d0a9ff36574da0c042e9bd3ae816301b392ac41Nick Lewycky TsanIgnoreWritesEnd(); 50b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson DeleterFn = Deleter; 51b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson 52b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson // Add to list of managed statics. 53b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson Next = StaticList; 54b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson StaticList = this; 55b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson } 56b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson } else { 57dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines assert(!Ptr && !DeleterFn && !Next && 5851b16f473759c1546acbf308a5d3f3e7bf3ea23cBill Wendling "Partially initialized ManagedStatic!?"); 59dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Ptr = Creator(); 60b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson DeleterFn = Deleter; 61771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 62b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson // Add to list of managed statics. 63b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson Next = StaticList; 64b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson StaticList = this; 65b4d97b78dfd0d14a788fa3cb876f67a9e666b99bOwen Anderson } 66771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner} 67771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 68771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattnervoid ManagedStaticBase::destroy() const { 69d283566319a5bec8bfa2223580d92c86e01af13bChris Lattner assert(DeleterFn && "ManagedStatic not initialized correctly!"); 70771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner assert(StaticList == this && 71771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner "Not destroyed in reverse order of construction?"); 72771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner // Unlink from list. 73771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner StaticList = Next; 74dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Next = nullptr; 75771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 76771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner // Destroy memory. 77771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner DeleterFn(Ptr); 78771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 79771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner // Cleanup. 80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines Ptr = nullptr; 81dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines DeleterFn = nullptr; 82771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner} 83771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner 84771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. 85151880b020e33e12a0286612ec450051bd16f8e8Chris Lattnervoid llvm::llvm_shutdown() { 86cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines MutexGuard Lock(getManagedStaticMutex()); 87cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines 88771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner while (StaticList) 89771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner StaticList->destroy(); 90771cbf30bc1ff025316d1a80aeb5102375c1598eChris Lattner} 91