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>
20using namespace llvm;
21
22static const ManagedStaticBase *StaticList = nullptr;
23
24static 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
32void 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
68void 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.
85void llvm::llvm_shutdown() {
86  MutexGuard Lock(getManagedStaticMutex());
87
88  while (StaticList)
89    StaticList->destroy();
90}
91