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/Atomic.h"
     17 #include "llvm/Support/Mutex.h"
     18 #include "llvm/Support/MutexGuard.h"
     19 #include <cassert>
     20 using namespace llvm;
     21 
     22 static const ManagedStaticBase *StaticList = nullptr;
     23 
     24 static sys::Mutex& getManagedStaticMutex() {
     25   // We need to use a function local static here, since this can get called
     26   // during a static constructor and we need to guarantee that it's initialized
     27   // correctly.
     28   static sys::Mutex ManagedStaticMutex;
     29   return ManagedStaticMutex;
     30 }
     31 
     32 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
     33                                               void (*Deleter)(void*)) const {
     34   assert(Creator);
     35   if (llvm_is_multithreaded()) {
     36     MutexGuard Lock(getManagedStaticMutex());
     37 
     38     if (!Ptr) {
     39       void* tmp = Creator();
     40 
     41       TsanHappensBefore(this);
     42       sys::MemoryFence();
     43 
     44       // This write is racy against the first read in the ManagedStatic
     45       // accessors. The race is benign because it does a second read after a
     46       // memory fence, at which point it isn't possible to get a partial value.
     47       TsanIgnoreWritesBegin();
     48       Ptr = tmp;
     49       TsanIgnoreWritesEnd();
     50       DeleterFn = Deleter;
     51 
     52       // Add to list of managed statics.
     53       Next = StaticList;
     54       StaticList = this;
     55     }
     56   } else {
     57     assert(!Ptr && !DeleterFn && !Next &&
     58            "Partially initialized ManagedStatic!?");
     59     Ptr = Creator();
     60     DeleterFn = Deleter;
     61 
     62     // Add to list of managed statics.
     63     Next = StaticList;
     64     StaticList = this;
     65   }
     66 }
     67 
     68 void ManagedStaticBase::destroy() const {
     69   assert(DeleterFn && "ManagedStatic not initialized correctly!");
     70   assert(StaticList == this &&
     71          "Not destroyed in reverse order of construction?");
     72   // Unlink from list.
     73   StaticList = Next;
     74   Next = nullptr;
     75 
     76   // Destroy memory.
     77   DeleterFn(Ptr);
     78 
     79   // Cleanup.
     80   Ptr = nullptr;
     81   DeleterFn = nullptr;
     82 }
     83 
     84 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
     85 void llvm::llvm_shutdown() {
     86   MutexGuard Lock(getManagedStaticMutex());
     87 
     88   while (StaticList)
     89     StaticList->destroy();
     90 }
     91