1193323Sed//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file implements the ManagedStatic class and llvm_shutdown().
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#include "llvm/Support/ManagedStatic.h"
15193323Sed#include "llvm/Config/config.h"
16218893Sdim#include "llvm/Support/Atomic.h"
17193323Sed#include <cassert>
18193323Sedusing namespace llvm;
19193323Sed
20193323Sedstatic const ManagedStaticBase *StaticList = 0;
21193323Sed
22193323Sedvoid ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
23193323Sed                                              void (*Deleter)(void*)) const {
24194612Sed  if (llvm_is_multithreaded()) {
25194612Sed    llvm_acquire_global_lock();
26193323Sed
27193323Sed    if (Ptr == 0) {
28193323Sed      void* tmp = Creator ? Creator() : 0;
29193323Sed
30234353Sdim      TsanHappensBefore(this);
31193323Sed      sys::MemoryFence();
32234353Sdim
33234353Sdim      // This write is racy against the first read in the ManagedStatic
34234353Sdim      // accessors. The race is benign because it does a second read after a
35234353Sdim      // memory fence, at which point it isn't possible to get a partial value.
36234353Sdim      TsanIgnoreWritesBegin();
37193323Sed      Ptr = tmp;
38234353Sdim      TsanIgnoreWritesEnd();
39193323Sed      DeleterFn = Deleter;
40193323Sed
41193323Sed      // Add to list of managed statics.
42193323Sed      Next = StaticList;
43193323Sed      StaticList = this;
44193323Sed    }
45193323Sed
46194612Sed    llvm_release_global_lock();
47193323Sed  } else {
48193323Sed    assert(Ptr == 0 && DeleterFn == 0 && Next == 0 &&
49193323Sed           "Partially initialized ManagedStatic!?");
50193323Sed    Ptr = Creator ? Creator() : 0;
51193323Sed    DeleterFn = Deleter;
52193323Sed
53193323Sed    // Add to list of managed statics.
54193323Sed    Next = StaticList;
55193323Sed    StaticList = this;
56193323Sed  }
57193323Sed}
58193323Sed
59193323Sedvoid ManagedStaticBase::destroy() const {
60193323Sed  assert(DeleterFn && "ManagedStatic not initialized correctly!");
61193323Sed  assert(StaticList == this &&
62193323Sed         "Not destroyed in reverse order of construction?");
63193323Sed  // Unlink from list.
64193323Sed  StaticList = Next;
65193323Sed  Next = 0;
66193323Sed
67193323Sed  // Destroy memory.
68193323Sed  DeleterFn(Ptr);
69193323Sed
70193323Sed  // Cleanup.
71193323Sed  Ptr = 0;
72193323Sed  DeleterFn = 0;
73193323Sed}
74193323Sed
75193323Sed/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
76193323Sedvoid llvm::llvm_shutdown() {
77193323Sed  while (StaticList)
78193323Sed    StaticList->destroy();
79193323Sed
80194612Sed  if (llvm_is_multithreaded()) llvm_stop_multithreaded();
81193323Sed}
82