1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +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:
Benjamin Kramer 2019-08-07 11:59:57 +00:00
parent 8e1a600330
commit a94842ace2
5 changed files with 12 additions and 315 deletions

View File

@ -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;
}

View File

@ -170,7 +170,6 @@ add_llvm_library(LLVMSupport
Errno.cpp
Host.cpp
Memory.cpp
Mutex.cpp
Path.cpp
Process.cpp
Program.cpp

View File

@ -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

View File

@ -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;
}
}

View File

@ -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_);
}
}