xref: /freebsd/contrib/llvm-project/llvm/lib/Support/ManagedStatic.cpp (revision b49b6e0f95c89f8dcb5898424c360b46019254b4)
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