#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Threading.h"
#include <cassert>
+#include <mutex>
+#include <shared_mutex>
namespace llvm {
namespace sys {
- /// Platform agnostic RWMutex class.
- class RWMutexImpl
- {
- /// @name Constructors
- /// @{
- public:
-
- /// Initializes the lock but doesn't acquire it.
- /// Default Constructor.
- explicit RWMutexImpl();
-
- /// @}
- /// @name Do Not Implement
- /// @{
- RWMutexImpl(const RWMutexImpl & original) = delete;
- RWMutexImpl &operator=(const RWMutexImpl &) = delete;
- /// @}
-
- /// Releases and removes the lock
- /// Destructor
- ~RWMutexImpl();
-
- /// @}
- /// @name Methods
- /// @{
- public:
-
- /// Attempts to unconditionally acquire the lock in reader mode. If the
- /// lock is held by a writer, this method will wait until it can acquire
- /// the lock.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally acquire the lock in reader mode.
- bool reader_acquire();
-
- /// Attempts to release the lock in reader mode.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally release the lock in reader mode.
- bool reader_release();
-
- /// Attempts to unconditionally acquire the lock in reader mode. If the
- /// lock is held by any readers, this method will wait until it can
- /// acquire the lock.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally acquire the lock in writer mode.
- bool writer_acquire();
-
- /// Attempts to release the lock in writer mode.
- /// @returns false if any kind of error occurs, true otherwise.
- /// Unconditionally release the lock in write mode.
- bool writer_release();
-
- //@}
- /// @name Platform Dependent Data
- /// @{
- private:
-#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
- void* data_ = nullptr; ///< We don't know what the data will be
-#endif
- };
-
/// SmartMutex - An R/W 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 SmartRWMutex {
- RWMutexImpl impl;
+ // shared_mutex (C++17) is more efficient than shared_timed_mutex (C++14)
+ // on Windows and always available on MSVC.
+#if defined(_MSC_VER) || __cplusplus > 201402L
+ std::shared_mutex impl;
+#else
+ std::shared_timed_mutex impl;
+#endif
unsigned readers = 0;
unsigned writers = 0;
public:
- explicit SmartRWMutex() = default;
- SmartRWMutex(const SmartRWMutex<mt_only> & original) = delete;
- SmartRWMutex<mt_only> &operator=(const SmartRWMutex<mt_only> &) = delete;
-
bool lock_shared() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.reader_acquire();
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.lock_shared();
+ return true;
+ }
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
}
bool unlock_shared() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.reader_release();
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.unlock_shared();
+ return true;
+ }
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
}
bool lock() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.writer_acquire();
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.lock();
+ return true;
+ }
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
}
bool unlock() {
- if (!mt_only || llvm_is_multithreaded())
- return impl.writer_release();
+ if (!mt_only || llvm_is_multithreaded()) {
+ impl.unlock();
+ return true;
+ }
// Single-threaded debugging code. This would be racy in multithreaded
// mode, but provides not sanity checks in single threaded mode.
/// ScopedReader - RAII acquisition of a reader lock
template<bool mt_only>
- struct SmartScopedReader {
- SmartRWMutex<mt_only>& mutex;
-
- explicit SmartScopedReader(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.lock_shared();
- }
-
- ~SmartScopedReader() {
- mutex.unlock_shared();
- }
- };
+ using SmartScopedReader = const std::shared_lock<SmartRWMutex<mt_only>>;
typedef SmartScopedReader<false> ScopedReader;
/// ScopedWriter - RAII acquisition of a writer lock
template<bool mt_only>
- struct SmartScopedWriter {
- SmartRWMutex<mt_only>& mutex;
-
- explicit SmartScopedWriter(SmartRWMutex<mt_only>& m) : mutex(m) {
- mutex.lock();
- }
-
- ~SmartScopedWriter() {
- mutex.unlock();
- }
- };
+ using SmartScopedWriter = std::lock_guard<SmartRWMutex<mt_only>>;
typedef SmartScopedWriter<false> ScopedWriter;
Path.cpp
Process.cpp
Program.cpp
- RWMutex.cpp
Signals.cpp
TargetRegistry.cpp
ThreadLocal.cpp
+++ /dev/null
-//===- RWMutex.cpp - Reader/Writer 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::RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/RWMutex.h"
-#include "llvm/Config/config.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
-
-using namespace llvm;
-using namespace sys;
-
-RWMutexImpl::RWMutexImpl() = default;
-RWMutexImpl::~RWMutexImpl() = default;
-
-bool RWMutexImpl::reader_acquire() { return true; }
-bool RWMutexImpl::reader_release() { return true; }
-bool RWMutexImpl::writer_acquire() { return true; }
-bool RWMutexImpl::writer_release() { return true; }
-
-#else
-
-#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
-
-#include <cassert>
-#include <cstdlib>
-#include <pthread.h>
-
-using namespace llvm;
-using namespace sys;
-
-// Construct a RWMutex using pthread calls
-RWMutexImpl::RWMutexImpl()
-{
- // Declare the pthread_rwlock data structures
- pthread_rwlock_t* rwlock =
- static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
-
-#ifdef __APPLE__
- // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
- bzero(rwlock, sizeof(pthread_rwlock_t));
-#endif
-
- // Initialize the rwlock
- int errorcode = pthread_rwlock_init(rwlock, nullptr);
- (void)errorcode;
- assert(errorcode == 0);
-
- // Assign the data member
- data_ = rwlock;
-}
-
-// Destruct a RWMutex
-RWMutexImpl::~RWMutexImpl()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
- pthread_rwlock_destroy(rwlock);
- free(rwlock);
-}
-
-bool
-RWMutexImpl::reader_acquire()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_rdlock(rwlock);
- return errorcode == 0;
-}
-
-bool
-RWMutexImpl::reader_release()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_unlock(rwlock);
- return errorcode == 0;
-}
-
-bool
-RWMutexImpl::writer_acquire()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_wrlock(rwlock);
- return errorcode == 0;
-}
-
-bool
-RWMutexImpl::writer_release()
-{
- pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
- assert(rwlock != nullptr);
-
- int errorcode = pthread_rwlock_unlock(rwlock);
- return errorcode == 0;
-}
-
-#elif defined(LLVM_ON_UNIX)
-#include "Unix/RWMutex.inc"
-#elif defined( _WIN32)
-#include "Windows/RWMutex.inc"
-#else
-#warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp
-#endif
-#endif
+++ /dev/null
-//= llvm/Support/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =//
-//
-// 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) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic UNIX code that
-//=== is guaranteed to work on *all* UNIX variants.
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Mutex.h"
-
-namespace llvm {
-
-using namespace sys;
-
-// This naive implementation treats readers the same as writers. This
-// will therefore deadlock if a thread tries to acquire a read lock
-// multiple times.
-
-RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
-
-RWMutexImpl::~RWMutexImpl() {
- delete static_cast<MutexImpl *>(data_);
-}
-
-bool RWMutexImpl::reader_acquire() {
- return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::reader_release() {
- return static_cast<MutexImpl *>(data_)->release();
-}
-
-bool RWMutexImpl::writer_acquire() {
- return static_cast<MutexImpl *>(data_)->acquire();
-}
-
-bool RWMutexImpl::writer_release() {
- return static_cast<MutexImpl *>(data_)->release();
-}
-
-}
+++ /dev/null
-//= llvm/Support/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
-//
-// 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) RWMutex class.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-//=== WARNING: Implementation here must contain only generic Win32 code that
-//=== is guaranteed to work on *all* Win32 variants.
-//===----------------------------------------------------------------------===//
-
-#include "WindowsSupport.h"
-
-namespace llvm {
-
-// Windows has slim read-writer lock support on Vista and higher, so we
-// will attempt to load the APIs. If they exist, we will use them, and
-// if not, we will fall back on critical sections. When we drop support
-// for XP, we can stop lazy-loading these APIs and just use them directly.
-#if defined(__MINGW32__)
- // Taken from WinNT.h
- typedef struct _RTL_SRWLOCK {
- PVOID Ptr;
- } RTL_SRWLOCK, *PRTL_SRWLOCK;
-
- // Taken from WinBase.h
- typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
-#endif
-
-static VOID (WINAPI *fpInitializeSRWLock)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpAcquireSRWLockShared)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockExclusive)(PSRWLOCK lock) = NULL;
-static VOID (WINAPI *fpReleaseSRWLockShared)(PSRWLOCK lock) = NULL;
-
-static bool sHasSRW = false;
-
-static bool loadSRW() {
- static bool sChecked = false;
- if (!sChecked) {
- sChecked = true;
-
- if (HMODULE hLib = ::GetModuleHandleW(L"Kernel32.dll")) {
- fpInitializeSRWLock =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "InitializeSRWLock");
- fpAcquireSRWLockExclusive =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "AcquireSRWLockExclusive");
- fpAcquireSRWLockShared =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "AcquireSRWLockShared");
- fpReleaseSRWLockExclusive =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "ReleaseSRWLockExclusive");
- fpReleaseSRWLockShared =
- (VOID (WINAPI *)(PSRWLOCK))::GetProcAddress(hLib,
- "ReleaseSRWLockShared");
-
- if (fpInitializeSRWLock != NULL) {
- sHasSRW = true;
- }
- }
- }
- return sHasSRW;
-}
-
-sys::RWMutexImpl::RWMutexImpl() {
- if (loadSRW()) {
- data_ = safe_calloc(1, sizeof(SRWLOCK));
- fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
- } else {
- data_ = safe_calloc(1, sizeof(CRITICAL_SECTION));
- InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
-}
-
-sys::RWMutexImpl::~RWMutexImpl() {
- if (!sHasSRW)
- DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- // Nothing to do in the case of slim reader/writers except free the memory.
- free(data_);
-}
-
-bool sys::RWMutexImpl::reader_acquire() {
- if (sHasSRW) {
- fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
- } else {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::reader_release() {
- if (sHasSRW) {
- fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
- } else {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::writer_acquire() {
- if (sHasSRW) {
- fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
- } else {
- EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-bool sys::RWMutexImpl::writer_release() {
- if (sHasSRW) {
- fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
- } else {
- LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
- }
- return true;
-}
-
-
-}