Home | History | Annotate | Line # | Download | only in Support
      1 //===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file implements the ManagedStatic class and llvm_shutdown().
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "llvm/Support/ManagedStatic.h"
     14 #include "llvm/Config/config.h"
     15 #include "llvm/Support/Threading.h"
     16 #include <cassert>
     17 #include <mutex>
     18 using namespace llvm;
     19 
     20 static const ManagedStaticBase *StaticList = nullptr;
     21 
     22 static std::recursive_mutex *getManagedStaticMutex() {
     23   static std::recursive_mutex m;
     24   return &m;
     25 }
     26 
     27 void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
     28                                               void (*Deleter)(void*)) const {
     29   assert(Creator);
     30   if (llvm_is_multithreaded()) {
     31     std::lock_guard<std::recursive_mutex> Lock(*getManagedStaticMutex());
     32 
     33     if (!Ptr.load(std::memory_order_relaxed)) {
     34       void *Tmp = Creator();
     35 
     36       Ptr.store(Tmp, std::memory_order_release);
     37       DeleterFn = Deleter;
     38 
     39       // Add to list of managed statics.
     40       Next = StaticList;
     41       StaticList = this;
     42     }
     43   } else {
     44     assert(!Ptr && !DeleterFn && !Next &&
     45            "Partially initialized ManagedStatic!?");
     46     Ptr = Creator();
     47     DeleterFn = Deleter;
     48 
     49     // Add to list of managed statics.
     50     Next = StaticList;
     51     StaticList = this;
     52   }
     53 }
     54 
     55 void ManagedStaticBase::destroy() const {
     56   assert(DeleterFn && "ManagedStatic not initialized correctly!");
     57   assert(StaticList == this &&
     58          "Not destroyed in reverse order of construction?");
     59   // Unlink from list.
     60   StaticList = Next;
     61   Next = nullptr;
     62 
     63   // Destroy memory.
     64   DeleterFn(Ptr);
     65 
     66   // Cleanup.
     67   Ptr = nullptr;
     68   DeleterFn = nullptr;
     69 }
     70 
     71 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
     72 /// IMPORTANT: it's only safe to call llvm_shutdown() in single thread,
     73 /// without any other threads executing LLVM APIs.
     74 /// llvm_shutdown() should be the last use of LLVM APIs.
     75 void llvm::llvm_shutdown() {
     76   while (StaticList)
     77     StaticList->destroy();
     78 }
     79