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
|
||||
#define LLVM_SUPPORT_MUTEX_H
|
||||
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Threading.h"
|
||||
#include <cassert>
|
||||
#include <mutex>
|
||||
|
||||
namespace llvm
|
||||
{
|
||||
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
|
||||
/// indicates whether this mutex should become a no-op when we're not
|
||||
/// running in multithreaded mode.
|
||||
template<bool mt_only>
|
||||
class SmartMutex {
|
||||
MutexImpl impl;
|
||||
unsigned acquired;
|
||||
bool recursive;
|
||||
public:
|
||||
explicit SmartMutex(bool rec = true) :
|
||||
impl(rec), acquired(0), recursive(rec) { }
|
||||
std::recursive_mutex impl;
|
||||
unsigned acquired = 0;
|
||||
|
||||
public:
|
||||
bool lock() {
|
||||
if (!mt_only || llvm_is_multithreaded()) {
|
||||
return impl.acquire();
|
||||
impl.lock();
|
||||
return true;
|
||||
} else {
|
||||
// Single-threaded debugging code. This would be racy in
|
||||
// multithreaded mode, but provides not sanity checks in single
|
||||
// threaded mode.
|
||||
assert((recursive || acquired == 0) && "Lock already acquired!!");
|
||||
++acquired;
|
||||
return true;
|
||||
}
|
||||
@ -111,13 +45,13 @@ namespace llvm
|
||||
|
||||
bool unlock() {
|
||||
if (!mt_only || llvm_is_multithreaded()) {
|
||||
return impl.release();
|
||||
impl.unlock();
|
||||
return true;
|
||||
} else {
|
||||
// Single-threaded debugging code. This would be racy in
|
||||
// multithreaded mode, but provides not sanity checks in single
|
||||
// threaded mode.
|
||||
assert(((recursive && acquired) || (acquired == 1)) &&
|
||||
"Lock not acquired before release!");
|
||||
assert(acquired && "Lock not acquired before release!");
|
||||
--acquired;
|
||||
return true;
|
||||
}
|
||||
@ -125,31 +59,16 @@ namespace llvm
|
||||
|
||||
bool try_lock() {
|
||||
if (!mt_only || llvm_is_multithreaded())
|
||||
return impl.tryacquire();
|
||||
return impl.try_lock();
|
||||
else return true;
|
||||
}
|
||||
|
||||
private:
|
||||
SmartMutex(const SmartMutex<mt_only> & original);
|
||||
void operator=(const SmartMutex<mt_only> &);
|
||||
};
|
||||
|
||||
/// Mutex - A standard, always enforced mutex.
|
||||
typedef SmartMutex<false> Mutex;
|
||||
|
||||
template<bool mt_only>
|
||||
class SmartScopedLock {
|
||||
SmartMutex<mt_only>& mtx;
|
||||
|
||||
public:
|
||||
SmartScopedLock(SmartMutex<mt_only>& m) : mtx(m) {
|
||||
mtx.lock();
|
||||
}
|
||||
|
||||
~SmartScopedLock() {
|
||||
mtx.unlock();
|
||||
}
|
||||
};
|
||||
template <bool mt_only>
|
||||
using SmartScopedLock = std::lock_guard<SmartMutex<mt_only>>;
|
||||
|
||||
typedef SmartScopedLock<false> ScopedLock;
|
||||
}
|
||||
|
@ -170,7 +170,6 @@ add_llvm_library(LLVMSupport
|
||||
Errno.cpp
|
||||
Host.cpp
|
||||
Memory.cpp
|
||||
Mutex.cpp
|
||||
Path.cpp
|
||||
Process.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