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