mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[Support] Base SmartMutex on std::recursive_mutex
- Remove support for non-recursive mutexes. This was unused. - The std::recursive_mutex is now created/destroyed unconditionally. Locking is still only done if threading is enabled. - Alias SmartScopedLock to std::lock_guard. This should make no semantic difference on the existing APIs. llvm-svn: 368158
This commit is contained in:
parent
8e1a600330
commit
a94842ace2
@ -13,97 +13,31 @@
|
|||||||
#ifndef LLVM_SUPPORT_MUTEX_H
|
#ifndef LLVM_SUPPORT_MUTEX_H
|
||||||
#define LLVM_SUPPORT_MUTEX_H
|
#define LLVM_SUPPORT_MUTEX_H
|
||||||
|
|
||||||
#include "llvm/Config/llvm-config.h"
|
|
||||||
#include "llvm/Support/Compiler.h"
|
|
||||||
#include "llvm/Support/Threading.h"
|
#include "llvm/Support/Threading.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace llvm
|
namespace llvm
|
||||||
{
|
{
|
||||||
namespace sys
|
namespace sys
|
||||||
{
|
{
|
||||||
/// Platform agnostic Mutex class.
|
|
||||||
class MutexImpl
|
|
||||||
{
|
|
||||||
/// @name Constructors
|
|
||||||
/// @{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// Initializes the lock but doesn't acquire it. if \p recursive is set
|
|
||||||
/// to false, the lock will not be recursive which makes it cheaper but
|
|
||||||
/// also more likely to deadlock (same thread can't acquire more than
|
|
||||||
/// once).
|
|
||||||
/// Default Constructor.
|
|
||||||
explicit MutexImpl(bool recursive = true);
|
|
||||||
|
|
||||||
/// Releases and removes the lock
|
|
||||||
/// Destructor
|
|
||||||
~MutexImpl();
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
/// @name Methods
|
|
||||||
/// @{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// Attempts to unconditionally acquire the lock. If the lock is held by
|
|
||||||
/// another thread, this method will wait until it can acquire the lock.
|
|
||||||
/// @returns false if any kind of error occurs, true otherwise.
|
|
||||||
/// Unconditionally acquire the lock.
|
|
||||||
bool acquire();
|
|
||||||
|
|
||||||
/// Attempts to release the lock. If the lock is held by the current
|
|
||||||
/// thread, the lock is released allowing other threads to acquire the
|
|
||||||
/// lock.
|
|
||||||
/// @returns false if any kind of error occurs, true otherwise.
|
|
||||||
/// Unconditionally release the lock.
|
|
||||||
bool release();
|
|
||||||
|
|
||||||
/// Attempts to acquire the lock without blocking. If the lock is not
|
|
||||||
/// available, this function returns false quickly (without blocking). If
|
|
||||||
/// the lock is available, it is acquired.
|
|
||||||
/// @returns false if any kind of error occurs or the lock is not
|
|
||||||
/// available, true otherwise.
|
|
||||||
/// Try to acquire the lock.
|
|
||||||
bool tryacquire();
|
|
||||||
|
|
||||||
//@}
|
|
||||||
/// @name Platform Dependent Data
|
|
||||||
/// @{
|
|
||||||
private:
|
|
||||||
#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
|
|
||||||
void* data_; ///< We don't know what the data will be
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @}
|
|
||||||
/// @name Do Not Implement
|
|
||||||
/// @{
|
|
||||||
private:
|
|
||||||
MutexImpl(const MutexImpl &) = delete;
|
|
||||||
void operator=(const MutexImpl &) = delete;
|
|
||||||
/// @}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// SmartMutex - A mutex with a compile time constant parameter that
|
/// SmartMutex - A mutex with a compile time constant parameter that
|
||||||
/// indicates whether this mutex should become a no-op when we're not
|
/// indicates whether this mutex should become a no-op when we're not
|
||||||
/// running in multithreaded mode.
|
/// running in multithreaded mode.
|
||||||
template<bool mt_only>
|
template<bool mt_only>
|
||||||
class SmartMutex {
|
class SmartMutex {
|
||||||
MutexImpl impl;
|
std::recursive_mutex impl;
|
||||||
unsigned acquired;
|
unsigned acquired = 0;
|
||||||
bool recursive;
|
|
||||||
public:
|
|
||||||
explicit SmartMutex(bool rec = true) :
|
|
||||||
impl(rec), acquired(0), recursive(rec) { }
|
|
||||||
|
|
||||||
|
public:
|
||||||
bool lock() {
|
bool lock() {
|
||||||
if (!mt_only || llvm_is_multithreaded()) {
|
if (!mt_only || llvm_is_multithreaded()) {
|
||||||
return impl.acquire();
|
impl.lock();
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Single-threaded debugging code. This would be racy in
|
// Single-threaded debugging code. This would be racy in
|
||||||
// multithreaded mode, but provides not sanity checks in single
|
// multithreaded mode, but provides not sanity checks in single
|
||||||
// threaded mode.
|
// threaded mode.
|
||||||
assert((recursive || acquired == 0) && "Lock already acquired!!");
|
|
||||||
++acquired;
|
++acquired;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -111,13 +45,13 @@ namespace llvm
|
|||||||
|
|
||||||
bool unlock() {
|
bool unlock() {
|
||||||
if (!mt_only || llvm_is_multithreaded()) {
|
if (!mt_only || llvm_is_multithreaded()) {
|
||||||
return impl.release();
|
impl.unlock();
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// Single-threaded debugging code. This would be racy in
|
// Single-threaded debugging code. This would be racy in
|
||||||
// multithreaded mode, but provides not sanity checks in single
|
// multithreaded mode, but provides not sanity checks in single
|
||||||
// threaded mode.
|
// threaded mode.
|
||||||
assert(((recursive && acquired) || (acquired == 1)) &&
|
assert(acquired && "Lock not acquired before release!");
|
||||||
"Lock not acquired before release!");
|
|
||||||
--acquired;
|
--acquired;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -125,31 +59,16 @@ namespace llvm
|
|||||||
|
|
||||||
bool try_lock() {
|
bool try_lock() {
|
||||||
if (!mt_only || llvm_is_multithreaded())
|
if (!mt_only || llvm_is_multithreaded())
|
||||||
return impl.tryacquire();
|
return impl.try_lock();
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
SmartMutex(const SmartMutex<mt_only> & original);
|
|
||||||
void operator=(const SmartMutex<mt_only> &);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Mutex - A standard, always enforced mutex.
|
/// Mutex - A standard, always enforced mutex.
|
||||||
typedef SmartMutex<false> Mutex;
|
typedef SmartMutex<false> Mutex;
|
||||||
|
|
||||||
template<bool mt_only>
|
template <bool mt_only>
|
||||||
class SmartScopedLock {
|
using SmartScopedLock = std::lock_guard<SmartMutex<mt_only>>;
|
||||||
SmartMutex<mt_only>& mtx;
|
|
||||||
|
|
||||||
public:
|
|
||||||
SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
|
|
||||||
mtx.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
~SmartScopedLock() {
|
|
||||||
mtx.unlock();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef SmartScopedLock<false> ScopedLock;
|
typedef SmartScopedLock<false> ScopedLock;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,6 @@ add_llvm_library(LLVMSupport
|
|||||||
Errno.cpp
|
Errno.cpp
|
||||||
Host.cpp
|
Host.cpp
|
||||||
Memory.cpp
|
Memory.cpp
|
||||||
Mutex.cpp
|
|
||||||
Path.cpp
|
Path.cpp
|
||||||
Process.cpp
|
Process.cpp
|
||||||
Program.cpp
|
Program.cpp
|
||||||
|
@ -1,123 +0,0 @@
|
|||||||
//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements the llvm::sys::Mutex class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "llvm/Support/Mutex.h"
|
|
||||||
#include "llvm/Config/config.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//=== WARNING: Implementation here must contain only TRULY operating system
|
|
||||||
//=== independent code.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
|
|
||||||
// Define all methods as no-ops if threading is explicitly disabled
|
|
||||||
namespace llvm {
|
|
||||||
using namespace sys;
|
|
||||||
MutexImpl::MutexImpl( bool recursive) { }
|
|
||||||
MutexImpl::~MutexImpl() { }
|
|
||||||
bool MutexImpl::acquire() { return true; }
|
|
||||||
bool MutexImpl::release() { return true; }
|
|
||||||
bool MutexImpl::tryacquire() { return true; }
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
|
|
||||||
#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
using namespace sys;
|
|
||||||
|
|
||||||
// Construct a Mutex using pthread calls
|
|
||||||
MutexImpl::MutexImpl( bool recursive)
|
|
||||||
: data_(nullptr)
|
|
||||||
{
|
|
||||||
// Declare the pthread_mutex data structures
|
|
||||||
pthread_mutex_t* mutex =
|
|
||||||
static_cast<pthread_mutex_t*>(safe_malloc(sizeof(pthread_mutex_t)));
|
|
||||||
|
|
||||||
pthread_mutexattr_t attr;
|
|
||||||
|
|
||||||
// Initialize the mutex attributes
|
|
||||||
int errorcode = pthread_mutexattr_init(&attr);
|
|
||||||
assert(errorcode == 0); (void)errorcode;
|
|
||||||
|
|
||||||
// Initialize the mutex as a recursive mutex, if requested, or normal
|
|
||||||
// otherwise.
|
|
||||||
int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
|
|
||||||
errorcode = pthread_mutexattr_settype(&attr, kind);
|
|
||||||
assert(errorcode == 0);
|
|
||||||
|
|
||||||
// Initialize the mutex
|
|
||||||
errorcode = pthread_mutex_init(mutex, &attr);
|
|
||||||
assert(errorcode == 0);
|
|
||||||
|
|
||||||
// Destroy the attributes
|
|
||||||
errorcode = pthread_mutexattr_destroy(&attr);
|
|
||||||
assert(errorcode == 0);
|
|
||||||
|
|
||||||
// Assign the data member
|
|
||||||
data_ = mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destruct a Mutex
|
|
||||||
MutexImpl::~MutexImpl()
|
|
||||||
{
|
|
||||||
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
||||||
assert(mutex != nullptr);
|
|
||||||
pthread_mutex_destroy(mutex);
|
|
||||||
free(mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MutexImpl::acquire()
|
|
||||||
{
|
|
||||||
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
||||||
assert(mutex != nullptr);
|
|
||||||
|
|
||||||
int errorcode = pthread_mutex_lock(mutex);
|
|
||||||
return errorcode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MutexImpl::release()
|
|
||||||
{
|
|
||||||
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
||||||
assert(mutex != nullptr);
|
|
||||||
|
|
||||||
int errorcode = pthread_mutex_unlock(mutex);
|
|
||||||
return errorcode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MutexImpl::tryacquire()
|
|
||||||
{
|
|
||||||
pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
|
|
||||||
assert(mutex != nullptr);
|
|
||||||
|
|
||||||
int errorcode = pthread_mutex_trylock(mutex);
|
|
||||||
return errorcode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(LLVM_ON_UNIX)
|
|
||||||
#include "Unix/Mutex.inc"
|
|
||||||
#elif defined( _WIN32)
|
|
||||||
#include "Windows/Mutex.inc"
|
|
||||||
#else
|
|
||||||
#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
|
|
||||||
#endif
|
|
||||||
#endif
|
|
@ -1,42 +0,0 @@
|
|||||||
//===- llvm/Support/Unix/Mutex.inc - Unix Mutex Implementation ---*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements the Unix specific (non-pthread) Mutex class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//=== WARNING: Implementation here must contain only generic UNIX code that
|
|
||||||
//=== is guaranteed to work on *all* UNIX variants.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
namespace llvm
|
|
||||||
{
|
|
||||||
using namespace sys;
|
|
||||||
|
|
||||||
MutexImpl::MutexImpl( bool recursive)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MutexImpl::~MutexImpl()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MutexImpl::release()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
MutexImpl::tryacquire( void )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
//===- llvm/Support/Win32/Mutex.inc - Win32 Mutex Implementation -*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
||||||
// See https://llvm.org/LICENSE.txt for license information.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements the Win32 specific (non-pthread) Mutex class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//=== WARNING: Implementation here must contain only generic Win32 code that
|
|
||||||
//=== is guaranteed to work on *all* Win32 variants.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "WindowsSupport.h"
|
|
||||||
#include "llvm/Support/Mutex.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
sys::MutexImpl::MutexImpl(bool /*recursive*/)
|
|
||||||
{
|
|
||||||
data_ = new CRITICAL_SECTION;
|
|
||||||
InitializeCriticalSection((LPCRITICAL_SECTION)data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
sys::MutexImpl::~MutexImpl()
|
|
||||||
{
|
|
||||||
DeleteCriticalSection((LPCRITICAL_SECTION)data_);
|
|
||||||
delete (LPCRITICAL_SECTION)data_;
|
|
||||||
data_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
sys::MutexImpl::acquire()
|
|
||||||
{
|
|
||||||
EnterCriticalSection((LPCRITICAL_SECTION)data_);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
sys::MutexImpl::release()
|
|
||||||
{
|
|
||||||
LeaveCriticalSection((LPCRITICAL_SECTION)data_);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
sys::MutexImpl::tryacquire()
|
|
||||||
{
|
|
||||||
return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user