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