From 2a8cf9aadd39e507e6e09c25530a2f01ca27fe57 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Tue, 16 Jun 2009 20:19:28 +0000 Subject: [PATCH] Add a portable wrapper for reader-writer locks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73545 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/System/RWMutex.h | 84 +++++++++++++++++ lib/System/RWMutex.cpp | 169 ++++++++++++++++++++++++++++++++++ lib/System/Unix/RWMutex.inc | 43 +++++++++ lib/System/Win32/Mutex.inc | 2 +- lib/System/Win32/RWMutex.inc | 55 +++++++++++ 5 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 include/llvm/System/RWMutex.h create mode 100644 lib/System/RWMutex.cpp create mode 100644 lib/System/Unix/RWMutex.inc create mode 100644 lib/System/Win32/RWMutex.inc diff --git a/include/llvm/System/RWMutex.h b/include/llvm/System/RWMutex.h new file mode 100644 index 00000000000..eb56eec75f6 --- /dev/null +++ b/include/llvm/System/RWMutex.h @@ -0,0 +1,84 @@ +//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MUTEX_H +#define LLVM_SYSTEM_MUTEX_H + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic Mutex class. + class RWMutex + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. + /// @brief Default Constructor. + explicit RWMutex(); + + /// Releases and removes the lock + /// @brief Destructor + ~RWMutex(); + + /// @} + /// @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. + /// @brief 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. + /// @brief 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. + /// @brief 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. + /// @brief Unconditionally release the lock in write mode. + bool writer_release(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: +#ifdef ENABLE_THREADS + void* data_; ///< We don't know what the data will be +#endif + + /// @} + /// @name Do Not Implement + /// @{ + private: + RWMutex(const RWMutex & original); + void operator=(const RWMutex &); + /// @} + }; + } +} + +#endif diff --git a/lib/System/RWMutex.cpp b/lib/System/RWMutex.cpp new file mode 100644 index 00000000000..a781a379ed4 --- /dev/null +++ b/lib/System/RWMutex.cpp @@ -0,0 +1,169 @@ +//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the llvm::sys::RWMutex class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" +#include "llvm/System/RWMutex.h" + +//===----------------------------------------------------------------------===// +//=== WARNING: Implementation here must contain only TRULY operating system +//=== independent code. +//===----------------------------------------------------------------------===// + +#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 +// Define all methods as no-ops if threading is explicitly disabled +namespace llvm { +using namespace sys; +RWMutex::RWMutex( bool recursive) { } +RWMutex::~RWMutex() { } +bool RWMutex::reader_acquire() { return true; } +bool RWMutex::reader_release() { return true; } +bool RWMutex::writer_acquire() { return true; } +bool RWMutex::writer_release() { return true; } +} +#else + +#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) + +#include +#include +#include + +namespace llvm { +using namespace sys; + + +// This variable is useful for situations where the pthread library has been +// compiled with weak linkage for its interface symbols. This allows the +// threading support to be turned off by simply not linking against -lpthread. +// In that situation, the value of pthread_mutex_init will be 0 and +// consequently pthread_enabled will be false. In such situations, all the +// pthread operations become no-ops and the functions all return false. If +// pthread_rwlock_init does have an address, then rwlock support is enabled. +// Note: all LLVM tools will link against -lpthread if its available since it +// is configured into the LIBS variable. +// Note: this line of code generates a warning if pthread_rwlock_init is not +// declared with weak linkage. It's safe to ignore the warning. +static const bool pthread_enabled = true; + +// Construct a RWMutex using pthread calls +RWMutex::RWMutex() + : data_(0) +{ + if (pthread_enabled) + { + // Declare the pthread_rwlock data structures + pthread_rwlock_t* rwlock = + static_cast(malloc(sizeof(pthread_rwlock_t))); + pthread_rwlockattr_t attr; + + // Initialize the rwlock attributes + int errorcode = pthread_rwlockattr_init(&attr); + assert(errorcode == 0); + +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) + // Make it a process local rwlock + errorcode = pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE); +#endif + + // Initialize the rwlock + errorcode = pthread_rwlock_init(rwlock, &attr); + assert(errorcode == 0); + + // Destroy the attributes + errorcode = pthread_rwlockattr_destroy(&attr); + assert(errorcode == 0); + + // Assign the data member + data_ = rwlock; + } +} + +// Destruct a RWMutex +RWMutex::~RWMutex() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + pthread_rwlock_destroy(rwlock); + free(rwlock); + } +} + +bool +RWMutex::reader_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_rdlock(rwlock); + return errorcode == 0; + } + return false; +} + +bool +RWMutex::reader_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } + return false; +} + +bool +RWMutex::writer_acquire() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_wrlock(rwlock); + return errorcode == 0; + } + return false; +} + +bool +RWMutex::writer_release() +{ + if (pthread_enabled) + { + pthread_rwlock_t* rwlock = static_cast(data_); + assert(rwlock != 0); + + int errorcode = pthread_rwlock_unlock(rwlock); + return errorcode == 0; + } + return false; +} + +} + +#elif defined(LLVM_ON_UNIX) +#include "Unix/RWMutex.inc" +#elif defined( LLVM_ON_WIN32) +#include "Win32/RWMutex.inc" +#else +#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp +#endif +#endif + diff --git a/lib/System/Unix/RWMutex.inc b/lib/System/Unix/RWMutex.inc new file mode 100644 index 00000000000..4487d7f83da --- /dev/null +++ b/lib/System/Unix/RWMutex.inc @@ -0,0 +1,43 @@ +//= llvm/System/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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. +//===----------------------------------------------------------------------===// + +namespace llvm { + +using namespace sys; + +RWMutex::RWMutex() { } + +RWMutex::~RWMutex() { } + +bool RWMutex::reader_acquire() { + return true; +} + +bool RWMutex::reader_release() { + return true; +} + +bool RWMutex::writer_acquire() { + return true; +} + +bool RWMutex::writer_release() { + return true; +} + +} diff --git a/lib/System/Win32/Mutex.inc b/lib/System/Win32/Mutex.inc index 7c1723be73f..85cf0a7f9b5 100644 --- a/lib/System/Win32/Mutex.inc +++ b/lib/System/Win32/Mutex.inc @@ -22,7 +22,7 @@ namespace llvm { using namespace sys; -Mutex::Mutex(bool /*recursive*/) +Mutex::Mutex() { data_ = new CRITICAL_SECTION; InitializeCriticalSection((LPCRITICAL_SECTION)data_); diff --git a/lib/System/Win32/RWMutex.inc b/lib/System/Win32/RWMutex.inc new file mode 100644 index 00000000000..08c31f1eb7d --- /dev/null +++ b/lib/System/Win32/RWMutex.inc @@ -0,0 +1,55 @@ +//= llvm/System/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// 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 "Win32.h" + +namespace llvm { +using namespace sys; + +RWMutex::RWMutex() { + data_ = new PSRWLOCK; + InitializeSRWLock((PSRWLOCK*)data_); +} + +RWMutex::~RWMutex() { + delete (PSRWLOCK*)data_; + data_ = 0; +} + +bool RWMutex::reader_acquire() { + AcquireSRWLockShared((PSRWLOCK*)data_); + return true; +} + +bool RWMutex::reader_release() { + ReleaseSRWLockShared((PSRWLOCK*)data_); + return true; +} + +bool RWMutex::writer_acquire() { + AcquireSRWLockExclusive((PSRWLOCK*)data_); + return true; +} + +bool RWMutex::writer_release() { + ReleaseSRWLockExclusive((PSRWLOCK*)data_); + return true; +} + + +}