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 Andric static void initializeMutex() {
273ca95b02SDimitry Andric   ManagedStaticMutex = new sys::Mutex();
283ca95b02SDimitry Andric }
293ca95b02SDimitry Andric 
getManagedStaticMutex()303ca95b02SDimitry Andric static 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 Divacky void 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 Divacky void 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 Divacky void llvm::llvm_shutdown() {
813ca95b02SDimitry Andric   MutexGuard Lock(*getManagedStaticMutex());
8291bc56edSDimitry Andric 
83f22ef01cSRoman Divacky   while (StaticList)
84f22ef01cSRoman Divacky     StaticList->destroy();
85f22ef01cSRoman Divacky }
86