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 "llvm/Support/Threading.h"
20 #include <cassert>
21 using namespace llvm;
22 
23 static const ManagedStaticBase *StaticList = nullptr;
24 static sys::Mutex *ManagedStaticMutex = nullptr;
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<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) {
45       void* tmp = Creator();
46 
47       TsanHappensBefore(this);
48       sys::MemoryFence();
49 
50       // This write is racy against the first read in the ManagedStatic
51       // accessors. The race is benign because it does a second read after a
52       // memory fence, at which point it isn't possible to get a partial value.
53       TsanIgnoreWritesBegin();
54       Ptr = tmp;
55       TsanIgnoreWritesEnd();
56       DeleterFn = Deleter;
57 
58       // Add to list of managed statics.
59       Next = StaticList;
60       StaticList = this;
61     }
62   } else {
63     assert(!Ptr && !DeleterFn && !Next &&
64            "Partially initialized ManagedStatic!?");
65     Ptr = Creator();
66     DeleterFn = Deleter;
67 
68     // Add to list of managed statics.
69     Next = StaticList;
70     StaticList = this;
71   }
72 }
73 
74 void ManagedStaticBase::destroy() const {
75   assert(DeleterFn && "ManagedStatic not initialized correctly!");
76   assert(StaticList == this &&
77          "Not destroyed in reverse order of construction?");
78   // Unlink from list.
79   StaticList = Next;
80   Next = nullptr;
81 
82   // Destroy memory.
83   DeleterFn(Ptr);
84 
85   // Cleanup.
86   Ptr = nullptr;
87   DeleterFn = nullptr;
88 }
89 
90 /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
91 void llvm::llvm_shutdown() {
92   {
93     MutexGuard Lock(*getManagedStaticMutex());
94 
95     while (StaticList)
96       StaticList->destroy();
97   }
98 
99   delete ManagedStaticMutex;
100   ManagedStaticMutex = nullptr;
101 }
102