Home | History | Annotate | Download | only in Support
      1 //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the ManagedStatic class and llvm_shutdown().
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Support/ManagedStatic.h"
     15 #include "llvm/Config/config.h"
     16 #include "llvm/Support/Mutex.h"
     17 #include "llvm/Support/MutexGuard.h"
     18 #include "llvm/Support/Threading.h"
     19 #include <cassert>
     20 using namespace llvm;
     21 
     22 static const ManagedStaticBase *StaticList = nullptr;
     23 static sys::Mutex *ManagedStaticMutex = nullptr;
     24 LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
     25 
     26 static void initializeMutex() {
     27   ManagedStaticMutex = new sys::Mutex();
     28 }
     29 
     30 static sys::Mutex* getManagedStaticMutex() {
     31   // We need to use a function local static here, since this can get called
     32   // during a static constructor and we need to guarantee that it's initialized
     33   // correctly.
     34   llvm::call_once(mutex_init_flag, initializeMutex);
     35   return ManagedStaticMutex;
     36 }
     37 
     38 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
     39                                               void (*Deleter)(void*)) const {
     40   assert(Creator);
     41   if (llvm_is_multithreaded()) {
     42     MutexGuard Lock(*getManagedStaticMutex());
     43 
     44     if (!Ptr.load(std::memory_order_relaxed)) {
     45       void *Tmp = Creator();
     46 
     47       Ptr.store(Tmp, std::memory_order_release);
     48       DeleterFn = Deleter;
     49 
     50       // Add to list of managed statics.
     51       Next = StaticList;
     52       StaticList = this;
     53     }
     54   } else {
     55     assert(!Ptr && !DeleterFn && !Next &&
     56            "Partially initialized ManagedStatic!?");
     57     Ptr = Creator();
     58     DeleterFn = Deleter;
     59 
     60     // Add to list of managed statics.
     61     Next = StaticList;
     62     StaticList = this;
     63   }
     64 }
     65 
     66 void ManagedStaticBase::destroy() const {
     67   assert(DeleterFn && "ManagedStatic not initialized correctly!");
     68   assert(StaticList == this &&
     69          "Not destroyed in reverse order of construction?");
     70   // Unlink from list.
     71   StaticList = Next;
     72   Next = nullptr;
     73 
     74   // Destroy memory.
     75   DeleterFn(Ptr);
     76 
     77   // Cleanup.
     78   Ptr = nullptr;
     79   DeleterFn = nullptr;
     80 }
     81 
     82 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
     83 void llvm::llvm_shutdown() {
     84   MutexGuard Lock(*getManagedStaticMutex());
     85 
     86   while (StaticList)
     87     StaticList->destroy();
     88 }
     89