mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
d9782db93e
This gets rid of the memory fence in the hot path (dereferencing the ManagedStatic), trading for an extra mutex lock in the cold path (when the ManagedStatic was uninitialized). Since this only happens on the first accesses it shouldn't matter much. On strict architectures like x86 this removes any atomic instructions from the hot path. Also remove the tsan annotations, tsan knows how standard atomics work so they should be unnecessary now. llvm-svn: 274131
89 lines
2.5 KiB
C++
89 lines
2.5 KiB
C++
//===-- ManagedStatic.cpp - Static Global wrapper -------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the ManagedStatic class and llvm_shutdown().
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
#include "llvm/Config/config.h"
|
|
#include "llvm/Support/Mutex.h"
|
|
#include "llvm/Support/MutexGuard.h"
|
|
#include "llvm/Support/Threading.h"
|
|
#include <cassert>
|
|
using namespace llvm;
|
|
|
|
static const ManagedStaticBase *StaticList = nullptr;
|
|
static sys::Mutex *ManagedStaticMutex = nullptr;
|
|
LLVM_DEFINE_ONCE_FLAG(mutex_init_flag);
|
|
|
|
static void initializeMutex() {
|
|
ManagedStaticMutex = new sys::Mutex();
|
|
}
|
|
|
|
static sys::Mutex* getManagedStaticMutex() {
|
|
// We need to use a function local static here, since this can get called
|
|
// during a static constructor and we need to guarantee that it's initialized
|
|
// correctly.
|
|
llvm::call_once(mutex_init_flag, initializeMutex);
|
|
return ManagedStaticMutex;
|
|
}
|
|
|
|
void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
|
|
void (*Deleter)(void*)) const {
|
|
assert(Creator);
|
|
if (llvm_is_multithreaded()) {
|
|
MutexGuard Lock(*getManagedStaticMutex());
|
|
|
|
if (!Ptr.load(std::memory_order_relaxed)) {
|
|
void *Tmp = Creator();
|
|
|
|
Ptr.store(Tmp, std::memory_order_release);
|
|
DeleterFn = Deleter;
|
|
|
|
// Add to list of managed statics.
|
|
Next = StaticList;
|
|
StaticList = this;
|
|
}
|
|
} else {
|
|
assert(!Ptr && !DeleterFn && !Next &&
|
|
"Partially initialized ManagedStatic!?");
|
|
Ptr = Creator();
|
|
DeleterFn = Deleter;
|
|
|
|
// Add to list of managed statics.
|
|
Next = StaticList;
|
|
StaticList = this;
|
|
}
|
|
}
|
|
|
|
void ManagedStaticBase::destroy() const {
|
|
assert(DeleterFn && "ManagedStatic not initialized correctly!");
|
|
assert(StaticList == this &&
|
|
"Not destroyed in reverse order of construction?");
|
|
// Unlink from list.
|
|
StaticList = Next;
|
|
Next = nullptr;
|
|
|
|
// Destroy memory.
|
|
DeleterFn(Ptr);
|
|
|
|
// Cleanup.
|
|
Ptr = nullptr;
|
|
DeleterFn = nullptr;
|
|
}
|
|
|
|
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
|
|
void llvm::llvm_shutdown() {
|
|
MutexGuard Lock(*getManagedStaticMutex());
|
|
|
|
while (StaticList)
|
|
StaticList->destroy();
|
|
}
|