blob: 9d7e99f97fb5637c7f837abc834c0f238c174031 [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"
Chris Lattner9daff492006-09-28 00:31:55 +000017#include <cassert>
Zachary Turner6ad24442014-06-19 16:17:42 +000018#include <mutex>
Chris Lattner9daff492006-09-28 00:31:55 +000019using namespace llvm;
20
Craig Topperc10719f2014-04-07 04:17:22 +000021static const ManagedStaticBase *StaticList = nullptr;
Chris Lattner9daff492006-09-28 00:31:55 +000022
Zachary Turner6ad24442014-06-19 16:17:42 +000023// ManagedStatics can get created during execution of static constructors. As a
24// result, we cannot use a global static std::mutex object for the lock since it
25// may not have been constructed. Instead, we do a call-once initialization of
26// a pointer to a mutex.
27static std::once_flag MutexInitializationFlag;
28static std::recursive_mutex* ManagedStaticMutex = nullptr;
29
30// Not all supported platforms (in particular VS2012) have thread-safe function
31// static initialization, so roll our own.
32static std::recursive_mutex& GetManagedStaticMutex() {
33 std::call_once(MutexInitializationFlag,
34 []() { ManagedStaticMutex = new std::recursive_mutex(); } );
35
36 return *ManagedStaticMutex;
37}
38
Owen Andersonb9a4a572009-05-20 00:39:20 +000039void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
Chris Lattner9daff492006-09-28 00:31:55 +000040 void (*Deleter)(void*)) const {
David Blaikie5b015932014-04-17 20:30:35 +000041 assert(Creator);
Owen Anderson4cb4b612009-06-16 17:33:51 +000042 if (llvm_is_multithreaded()) {
Zachary Turner6ad24442014-06-19 16:17:42 +000043 std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex());
Owen Andersonb9a4a572009-05-20 00:39:20 +000044
Craig Topper8d399f82014-04-09 04:20:00 +000045 if (!Ptr) {
David Blaikie5b015932014-04-17 20:30:35 +000046 void* tmp = Creator();
Owen Andersonb9a4a572009-05-20 00:39:20 +000047
Nick Lewyckyfe856112011-11-14 20:50:16 +000048 TsanHappensBefore(this);
Benjamin Kramer17388a62014-03-03 18:02:34 +000049 sys::MemoryFence();
Nick Lewyckyfe856112011-11-14 20:50:16 +000050
51 // This write is racy against the first read in the ManagedStatic
52 // accessors. The race is benign because it does a second read after a
53 // memory fence, at which point it isn't possible to get a partial value.
54 TsanIgnoreWritesBegin();
Owen Andersonb9a4a572009-05-20 00:39:20 +000055 Ptr = tmp;
Nick Lewyckyfe856112011-11-14 20:50:16 +000056 TsanIgnoreWritesEnd();
Owen Andersonb9a4a572009-05-20 00:39:20 +000057 DeleterFn = Deleter;
58
59 // Add to list of managed statics.
60 Next = StaticList;
61 StaticList = this;
62 }
Owen Andersonb9a4a572009-05-20 00:39:20 +000063 } else {
Craig Topper2617dcc2014-04-15 06:32:26 +000064 assert(!Ptr && !DeleterFn && !Next &&
Bill Wendling09f17a82009-05-30 01:09:53 +000065 "Partially initialized ManagedStatic!?");
David Blaikie5b015932014-04-17 20:30:35 +000066 Ptr = Creator();
Owen Andersonb9a4a572009-05-20 00:39:20 +000067 DeleterFn = Deleter;
Chris Lattner9daff492006-09-28 00:31:55 +000068
Owen Andersonb9a4a572009-05-20 00:39:20 +000069 // Add to list of managed statics.
70 Next = StaticList;
71 StaticList = this;
72 }
Chris Lattner9daff492006-09-28 00:31:55 +000073}
74
75void ManagedStaticBase::destroy() const {
Chris Lattner4510c992007-02-20 06:18:57 +000076 assert(DeleterFn && "ManagedStatic not initialized correctly!");
Chris Lattner9daff492006-09-28 00:31:55 +000077 assert(StaticList == this &&
78 "Not destroyed in reverse order of construction?");
79 // Unlink from list.
80 StaticList = Next;
Craig Topperc10719f2014-04-07 04:17:22 +000081 Next = nullptr;
Chris Lattner9daff492006-09-28 00:31:55 +000082
83 // Destroy memory.
84 DeleterFn(Ptr);
85
86 // Cleanup.
Craig Topperc10719f2014-04-07 04:17:22 +000087 Ptr = nullptr;
88 DeleterFn = nullptr;
Chris Lattner9daff492006-09-28 00:31:55 +000089}
90
91/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
Chris Lattneradf409532006-09-29 18:43:14 +000092void llvm::llvm_shutdown() {
Zachary Turner6ad24442014-06-19 16:17:42 +000093 std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex());
94
Chris Lattner9daff492006-09-28 00:31:55 +000095 while (StaticList)
96 StaticList->destroy();
Zachary Turnerccbf3d02014-06-16 22:49:41 +000097
98 if (llvm_is_multithreaded()) llvm_stop_multithreaded();
Chris Lattner9daff492006-09-28 00:31:55 +000099}