blob: b8fb2841e5256fdf5b08573b8b4368aecfba490f [file] [log] [blame]
Chris Lattner771cbf32006-09-28 00:31:55 +00001//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattner771cbf32006-09-28 00:31:55 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the ManagedStatic class and llvm_shutdown().
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Support/ManagedStatic.h"
Owen Andersonb4d97b72009-05-20 00:39:20 +000015#include "llvm/Config/config.h"
Michael J. Spencer1f6efa32010-11-29 18:16:10 +000016#include "llvm/Support/Atomic.h"
Stephen Hinesc6a4f5e2014-07-21 00:45:20 -070017#include "llvm/Support/Mutex.h"
18#include "llvm/Support/MutexGuard.h"
Chris Lattner771cbf32006-09-28 00:31:55 +000019#include <cassert>
20using namespace llvm;
21
Stephen Hinesdce4a402014-05-29 02:49:00 -070022static const ManagedStaticBase *StaticList = nullptr;
Chris Lattner771cbf32006-09-28 00:31:55 +000023
Stephen Hinesc6a4f5e2014-07-21 00:45:20 -070024static 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
Owen Andersonb4d97b72009-05-20 00:39:20 +000032void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
Chris Lattner771cbf32006-09-28 00:31:55 +000033 void (*Deleter)(void*)) const {
Stephen Hinesdce4a402014-05-29 02:49:00 -070034 assert(Creator);
Owen Anderson4c7ac182009-06-16 17:33:51 +000035 if (llvm_is_multithreaded()) {
Stephen Hinesc6a4f5e2014-07-21 00:45:20 -070036 MutexGuard Lock(getManagedStaticMutex());
Owen Andersonb4d97b72009-05-20 00:39:20 +000037
Stephen Hinesdce4a402014-05-29 02:49:00 -070038 if (!Ptr) {
39 void* tmp = Creator();
Owen Andersonb4d97b72009-05-20 00:39:20 +000040
Nick Lewycky4d0a9ff2011-11-14 20:50:16 +000041 TsanHappensBefore(this);
Owen Andersonb4d97b72009-05-20 00:39:20 +000042 sys::MemoryFence();
Nick Lewycky4d0a9ff2011-11-14 20:50:16 +000043
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();
Owen Andersonb4d97b72009-05-20 00:39:20 +000048 Ptr = tmp;
Nick Lewycky4d0a9ff2011-11-14 20:50:16 +000049 TsanIgnoreWritesEnd();
Owen Andersonb4d97b72009-05-20 00:39:20 +000050 DeleterFn = Deleter;
51
52 // Add to list of managed statics.
53 Next = StaticList;
54 StaticList = this;
55 }
Owen Andersonb4d97b72009-05-20 00:39:20 +000056 } else {
Stephen Hinesdce4a402014-05-29 02:49:00 -070057 assert(!Ptr && !DeleterFn && !Next &&
Bill Wendling51b16f42009-05-30 01:09:53 +000058 "Partially initialized ManagedStatic!?");
Stephen Hinesdce4a402014-05-29 02:49:00 -070059 Ptr = Creator();
Owen Andersonb4d97b72009-05-20 00:39:20 +000060 DeleterFn = Deleter;
Chris Lattner771cbf32006-09-28 00:31:55 +000061
Owen Andersonb4d97b72009-05-20 00:39:20 +000062 // Add to list of managed statics.
63 Next = StaticList;
64 StaticList = this;
65 }
Chris Lattner771cbf32006-09-28 00:31:55 +000066}
67
68void ManagedStaticBase::destroy() const {
Chris Lattnerd2835662007-02-20 06:18:57 +000069 assert(DeleterFn && "ManagedStatic not initialized correctly!");
Chris Lattner771cbf32006-09-28 00:31:55 +000070 assert(StaticList == this &&
71 "Not destroyed in reverse order of construction?");
72 // Unlink from list.
73 StaticList = Next;
Stephen Hinesdce4a402014-05-29 02:49:00 -070074 Next = nullptr;
Chris Lattner771cbf32006-09-28 00:31:55 +000075
76 // Destroy memory.
77 DeleterFn(Ptr);
78
79 // Cleanup.
Stephen Hinesdce4a402014-05-29 02:49:00 -070080 Ptr = nullptr;
81 DeleterFn = nullptr;
Chris Lattner771cbf32006-09-28 00:31:55 +000082}
83
84/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
Chris Lattner151880b2006-09-29 18:43:14 +000085void llvm::llvm_shutdown() {
Stephen Hinesc6a4f5e2014-07-21 00:45:20 -070086 MutexGuard Lock(getManagedStaticMutex());
87
Chris Lattner771cbf32006-09-28 00:31:55 +000088 while (StaticList)
89 StaticList->destroy();
Chris Lattner771cbf32006-09-28 00:31:55 +000090}