diff options
-rw-r--r-- | libunwind/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libunwind/src/RWMutex.hpp | 77 | ||||
-rw-r--r-- | libunwind/src/UnwindCursor.hpp | 28 | ||||
-rw-r--r-- | libunwind/src/config.h | 21 |
4 files changed, 97 insertions, 30 deletions
diff --git a/libunwind/src/CMakeLists.txt b/libunwind/src/CMakeLists.txt index d1659589676..17550d9ef8a 100644 --- a/libunwind/src/CMakeLists.txt +++ b/libunwind/src/CMakeLists.txt @@ -30,6 +30,7 @@ set(LIBUNWIND_HEADERS DwarfParser.hpp libunwind_ext.h Registers.hpp + RWMutex.hpp UnwindCursor.hpp ${CMAKE_CURRENT_SOURCE_DIR}/../include/libunwind.h ${CMAKE_CURRENT_SOURCE_DIR}/../include/unwind.h) diff --git a/libunwind/src/RWMutex.hpp b/libunwind/src/RWMutex.hpp new file mode 100644 index 00000000000..50a78a57b08 --- /dev/null +++ b/libunwind/src/RWMutex.hpp @@ -0,0 +1,77 @@ +//===----------------------------- Registers.hpp --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Abstract interface to shared reader/writer log, hiding platform and +// configuration differences. +// +//===----------------------------------------------------------------------===// + +#ifndef __RWMUTEX_HPP__ +#define __RWMUTEX_HPP__ + +#if defined(_WIN32) +#include <windows.h> +#elif !defined(_LIBUNWIND_HAS_NO_THREADS) +#include <pthread.h> +#endif + +namespace libunwind { + +#if defined(_LIBUNWIND_HAS_NO_THREADS) + +class _LIBUNWIND_HIDDEN RWMutex { +public: + bool lock_shared() { return true; } + bool unlock_shared() { return true; } + bool lock() { return true; } + bool unlock() { return true; } +}; + +#elif defined(_WIN32) + +class _LIBUNWIND_HIDDEN RWMutex { +public: + bool lock_shared() { + AcquireSRWLockShared(&_lock); + return true; + } + bool unlock_shared() { + ReleaseSRWLockShared(&_lock); + return true; + } + bool lock() { + AcquireSRWLockExclusive(&_lock); + return true; + } + bool unlock() { + ReleaseSRWLockExclusive(&_lock); + return true; + } + +private: + SRWLOCK _lock = SRWLOCK_INIT; +}; + +#else + +class _LIBUNWIND_HIDDEN RWMutex { +public: + bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; } + bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; } + bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; } + bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; } + +private: + pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; +}; + +#endif + +} // namespace libunwind + +#endif // __RWMUTEX_HPP__ diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 6892f9639d8..ab2f542dbdf 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -16,9 +16,6 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#ifndef _LIBUNWIND_HAS_NO_THREADS - #include <pthread.h> -#endif #include <unwind.h> #ifdef __APPLE__ @@ -34,6 +31,7 @@ #include "EHHeaderParser.hpp" #include "libunwind.h" #include "Registers.hpp" +#include "RWMutex.hpp" #include "Unwind-EHABI.h" namespace libunwind { @@ -62,9 +60,7 @@ private: // These fields are all static to avoid needing an initializer. // There is only one instance of this class per process. -#ifndef _LIBUNWIND_HAS_NO_THREADS - static pthread_rwlock_t _lock; -#endif + static RWMutex _lock; #ifdef __APPLE__ static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); static bool _registeredForDyldUnloads; @@ -91,10 +87,8 @@ DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64]; template <typename A> typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64]; -#ifndef _LIBUNWIND_HAS_NO_THREADS template <typename A> -pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER; -#endif +RWMutex DwarfFDECache<A>::_lock; #ifdef __APPLE__ template <typename A> @@ -104,7 +98,7 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false; template <typename A> typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { pint_t result = 0; - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_rdlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { if ((mh == p->mh) || (mh == 0)) { if ((p->ip_start <= pc) && (pc < p->ip_end)) { @@ -113,7 +107,7 @@ typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { } } } - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); return result; } @@ -121,7 +115,7 @@ template <typename A> void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde) { #if !defined(_LIBUNWIND_NO_HEAP) - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); if (_bufferUsed >= _bufferEnd) { size_t oldSize = (size_t)(_bufferEnd - _buffer); size_t newSize = oldSize * 4; @@ -145,13 +139,13 @@ void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, _registeredForDyldUnloads = true; } #endif - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); #endif } template <typename A> void DwarfFDECache<A>::removeAllIn(pint_t mh) { - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); entry *d = _buffer; for (const entry *s = _buffer; s < _bufferUsed; ++s) { if (s->mh != mh) { @@ -161,7 +155,7 @@ void DwarfFDECache<A>::removeAllIn(pint_t mh) { } } _bufferUsed = d; - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #ifdef __APPLE__ @@ -174,11 +168,11 @@ void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { template <typename A> void DwarfFDECache<A>::iterateCacheEntries(void (*func)( unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); for (entry *p = _buffer; p < _bufferUsed; ++p) { (*func)(p->ip_start, p->ip_end, p->fde, p->mh); } - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) diff --git a/libunwind/src/config.h b/libunwind/src/config.h index 2e2dc57c7e0..6706e5a3acc 100644 --- a/libunwind/src/config.h +++ b/libunwind/src/config.h @@ -93,20 +93,15 @@ fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__) #endif -#if defined(_LIBUNWIND_HAS_NO_THREADS) - // only used with pthread calls, not needed for the single-threaded builds - #define _LIBUNWIND_LOG_NON_ZERO(x) +#if defined(NDEBUG) + #define _LIBUNWIND_LOG_IF_FALSE(x) x #else - #if defined(NDEBUG) - #define _LIBUNWIND_LOG_NON_ZERO(x) x - #else - #define _LIBUNWIND_LOG_NON_ZERO(x) \ - do { \ - int _err = x; \ - if (_err != 0) \ - _LIBUNWIND_LOG("" #x "=%d in %s", _err, __FUNCTION__); \ - } while (0) - #endif + #define _LIBUNWIND_LOG_IF_FALSE(x) \ + do { \ + bool _ret = x; \ + if (!_ret) \ + _LIBUNWIND_LOG("" #x " failed in %s", __FUNCTION__); \ + } while (0) #endif // Macros that define away in non-Debug builds |