blob: 9868207b14ff2733ba7c8ea75b81ec6a98b7abe4 [file] [log] [blame]
Chris Lattner9daff492006-09-28 00:31:55 +00001//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-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 Lattner9daff492006-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 Andersonb9a4a572009-05-20 00:39:20 +000015#include "llvm/Config/config.h"
Benjamin Kramer17388a62014-03-03 18:02:34 +000016#include "llvm/Support/Atomic.h"
Peter Collingbourne4cfa0862015-08-18 22:31:24 +000017#include "llvm/Support/Compiler.h"
Zachary Turnerd119fa02014-06-21 00:24:51 +000018#include "llvm/Support/Mutex.h"
19#include "llvm/Support/MutexGuard.h"
Chris Lattner9daff492006-09-28 00:31:55 +000020#include <cassert>
21using namespace llvm;
22
Craig Topperc10719f2014-04-07 04:17:22 +000023static const ManagedStaticBase *StaticList = nullptr;
Chris Lattner9daff492006-09-28 00:31:55 +000024
Jiangning Liu1fb71bc2014-11-05 04:44:31 +000025static sys::Mutex& getManagedStaticMutex() {
Zachary Turnerd119fa02014-06-21 00:24:51 +000026 // 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.
Jiangning Liu1fb71bc2014-11-05 04:44:31 +000029 static sys::Mutex ManagedStaticMutex;
Zachary Turnerd119fa02014-06-21 00:24:51 +000030 return ManagedStaticMutex;
Zachary Turner6ad24442014-06-19 16:17:42 +000031}
32
Owen Andersonb9a4a572009-05-20 00:39:20 +000033void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
Chris Lattner9daff492006-09-28 00:31:55 +000034 void (*Deleter)(void*)) const {
David Blaikie5b015932014-04-17 20:30:35 +000035 assert(Creator);
Owen Anderson4cb4b612009-06-16 17:33:51 +000036 if (llvm_is_multithreaded()) {
Jiangning Liu1fb71bc2014-11-05 04:44:31 +000037 MutexGuard Lock(getManagedStaticMutex());
Owen Andersonb9a4a572009-05-20 00:39:20 +000038
Craig Topper8d399f82014-04-09 04:20:00 +000039 if (!Ptr) {
David Blaikie5b015932014-04-17 20:30:35 +000040 void* tmp = Creator();
Owen Andersonb9a4a572009-05-20 00:39:20 +000041
Nick Lewyckyfe856112011-11-14 20:50:16 +000042 TsanHappensBefore(this);
Benjamin Kramer17388a62014-03-03 18:02:34 +000043 sys::MemoryFence();
Nick Lewyckyfe856112011-11-14 20:50:16 +000044
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();
Owen Andersonb9a4a572009-05-20 00:39:20 +000049 Ptr = tmp;
Nick Lewyckyfe856112011-11-14 20:50:16 +000050 TsanIgnoreWritesEnd();
Owen Andersonb9a4a572009-05-20 00:39:20 +000051 DeleterFn = Deleter;
52
53 // Add to list of managed statics.
54 Next = StaticList;
55 StaticList = this;
56 }
Owen Andersonb9a4a572009-05-20 00:39:20 +000057 } else {
Craig Topper2617dcc2014-04-15 06:32:26 +000058 assert(!Ptr && !DeleterFn && !Next &&
Bill Wendling09f17a82009-05-30 01:09:53 +000059 "Partially initialized ManagedStatic!?");
David Blaikie5b015932014-04-17 20:30:35 +000060 Ptr = Creator();
Owen Andersonb9a4a572009-05-20 00:39:20 +000061 DeleterFn = Deleter;
Chris Lattner9daff492006-09-28 00:31:55 +000062
Owen Andersonb9a4a572009-05-20 00:39:20 +000063 // Add to list of managed statics.
64 Next = StaticList;
65 StaticList = this;
66 }
Chris Lattner9daff492006-09-28 00:31:55 +000067}
68
69void ManagedStaticBase::destroy() const {
Chris Lattner4510c992007-02-20 06:18:57 +000070 assert(DeleterFn && "ManagedStatic not initialized correctly!");
Chris Lattner9daff492006-09-28 00:31:55 +000071 assert(StaticList == this &&
72 "Not destroyed in reverse order of construction?");
73 // Unlink from list.
74 StaticList = Next;
Craig Topperc10719f2014-04-07 04:17:22 +000075 Next = nullptr;
Chris Lattner9daff492006-09-28 00:31:55 +000076
77 // Destroy memory.
78 DeleterFn(Ptr);
79
80 // Cleanup.
Craig Topperc10719f2014-04-07 04:17:22 +000081 Ptr = nullptr;
82 DeleterFn = nullptr;
Chris Lattner9daff492006-09-28 00:31:55 +000083}
84
85/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
Chris Lattneradf409532006-09-29 18:43:14 +000086void llvm::llvm_shutdown() {
Jiangning Liu1fb71bc2014-11-05 04:44:31 +000087 MutexGuard Lock(getManagedStaticMutex());
Zachary Turner6ad24442014-06-19 16:17:42 +000088
NAKAMURA Takumi256d37a2014-10-14 15:58:16 +000089 while (StaticList)
90 StaticList->destroy();
Chris Lattner9daff492006-09-28 00:31:55 +000091}