Skip to content

Commit

Permalink
Kill the LLVM global lock.
Browse files Browse the repository at this point in the history
This patch removes the LLVM global lock, and updates all existing
users of the global lock to use their own mutex.    None of the
existing users of the global lock were protecting code that was
mutually exclusive with any of the other users of the global
lock, so its purpose was not being met.

Reviewed by: rnk

Differential Revision: http://reviews.llvm.org/D4142

llvm-svn: 211277
  • Loading branch information
Zachary Turner committed Jun 19, 2014
1 parent c8e3b5f commit 6ad2444
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 30 deletions.
5 changes: 0 additions & 5 deletions llvm/docs/ProgrammersManual.rst
Expand Up @@ -2226,11 +2226,6 @@ Note that, because no other threads are allowed to issue LLVM API calls before
``llvm_start_multithreaded()`` returns, it is possible to have
``ManagedStatic``\ s of ``llvm::sys::Mutex``\ s.

The ``llvm_acquire_global_lock()`` and ``llvm_release_global_lock`` APIs provide
access to the global lock used to implement the double-checked locking for lazy
initialization. These should only be used internally to LLVM, and only if you
know what you're doing!

.. _llvmcontext:

Achieving Isolation with ``LLVMContext``
Expand Down
8 changes: 0 additions & 8 deletions llvm/include/llvm/Support/Threading.h
Expand Up @@ -33,14 +33,6 @@ namespace llvm {
/// mode or not.
bool llvm_is_multithreaded();

/// acquire_global_lock - Acquire the global lock. This is a no-op if called
/// before llvm_start_multithreaded().
void llvm_acquire_global_lock();

/// release_global_lock - Release the global lock. This is a no-op if called
/// before llvm_start_multithreaded().
void llvm_release_global_lock();

/// llvm_execute_on_thread - Execute the given \p UserFn on a separate
/// thread, passing it the provided \p UserData.
///
Expand Down
23 changes: 20 additions & 3 deletions llvm/lib/Support/ManagedStatic.cpp
Expand Up @@ -15,15 +15,32 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Atomic.h"
#include <cassert>
#include <mutex>
using namespace llvm;

static const ManagedStaticBase *StaticList = nullptr;

// ManagedStatics can get created during execution of static constructors. As a
// result, we cannot use a global static std::mutex object for the lock since it
// may not have been constructed. Instead, we do a call-once initialization of
// a pointer to a mutex.
static std::once_flag MutexInitializationFlag;
static std::recursive_mutex* ManagedStaticMutex = nullptr;

// Not all supported platforms (in particular VS2012) have thread-safe function
// static initialization, so roll our own.
static std::recursive_mutex& GetManagedStaticMutex() {
std::call_once(MutexInitializationFlag,
[]() { ManagedStaticMutex = new std::recursive_mutex(); } );

return *ManagedStaticMutex;
}

void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
assert(Creator);
if (llvm_is_multithreaded()) {
llvm_acquire_global_lock();
std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex());

if (!Ptr) {
void* tmp = Creator();
Expand All @@ -43,8 +60,6 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
Next = StaticList;
StaticList = this;
}

llvm_release_global_lock();
} else {
assert(!Ptr && !DeleterFn && !Next &&
"Partially initialized ManagedStatic!?");
Expand Down Expand Up @@ -75,6 +90,8 @@ void ManagedStaticBase::destroy() const {

/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm::llvm_shutdown() {
std::lock_guard<std::recursive_mutex> Lock(GetManagedStaticMutex());

while (StaticList)
StaticList->destroy();

Expand Down
12 changes: 0 additions & 12 deletions llvm/lib/Support/Threading.cpp
Expand Up @@ -21,13 +21,10 @@ using namespace llvm;

static bool multithreaded_mode = false;

static sys::Mutex* global_lock = nullptr;

bool llvm::llvm_start_multithreaded() {
#if LLVM_ENABLE_THREADS != 0
assert(!multithreaded_mode && "Already multithreaded!");
multithreaded_mode = true;
global_lock = new sys::Mutex(true);

// We fence here to ensure that all initialization is complete BEFORE we
// return from llvm_start_multithreaded().
Expand All @@ -47,22 +44,13 @@ void llvm::llvm_stop_multithreaded() {
sys::MemoryFence();

multithreaded_mode = false;
delete global_lock;
#endif
}

bool llvm::llvm_is_multithreaded() {
return multithreaded_mode;
}

void llvm::llvm_acquire_global_lock() {
if (multithreaded_mode) global_lock->acquire();
}

void llvm::llvm_release_global_lock() {
if (multithreaded_mode) global_lock->release();
}

#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H)
#include <pthread.h>

Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Support/Timer.cpp
Expand Up @@ -19,6 +19,7 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
Expand Down Expand Up @@ -84,14 +85,13 @@ static TimerGroup *getDefaultTimerGroup() {
sys::MemoryFence();
if (tmp) return tmp;

llvm_acquire_global_lock();
sys::SmartScopedLock<true> Lock(*TimerLock);
tmp = DefaultTimerGroup;
if (!tmp) {
tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
sys::MemoryFence();
DefaultTimerGroup = tmp;
}
llvm_release_global_lock();

return tmp;
}
Expand Down

0 comments on commit 6ad2444

Please sign in to comment.