Index: libunwind/trunk/src/CMakeLists.txt =================================================================== --- libunwind/trunk/src/CMakeLists.txt +++ libunwind/trunk/src/CMakeLists.txt @@ -30,6 +30,7 @@ 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) Index: libunwind/trunk/src/RWMutex.hpp =================================================================== --- libunwind/trunk/src/RWMutex.hpp +++ libunwind/trunk/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 +#elif !defined(_LIBUNWIND_HAS_NO_THREADS) +#include +#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__ Index: libunwind/trunk/src/UnwindCursor.hpp =================================================================== --- libunwind/trunk/src/UnwindCursor.hpp +++ libunwind/trunk/src/UnwindCursor.hpp @@ -16,9 +16,6 @@ #include #include #include -#ifndef _LIBUNWIND_HAS_NO_THREADS - #include -#endif #include #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 @@ // 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 @@ template typename DwarfFDECache::entry DwarfFDECache::_initialBuffer[64]; -#ifndef _LIBUNWIND_HAS_NO_THREADS template -pthread_rwlock_t DwarfFDECache::_lock = PTHREAD_RWLOCK_INITIALIZER; -#endif +RWMutex DwarfFDECache::_lock; #ifdef __APPLE__ template @@ -104,7 +98,7 @@ template typename A::pint_t DwarfFDECache::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 @@ } } } - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); return result; } @@ -121,7 +115,7 @@ void DwarfFDECache::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 @@ _registeredForDyldUnloads = true; } #endif - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); #endif } template void DwarfFDECache::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 @@ } } _bufferUsed = d; - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #ifdef __APPLE__ @@ -174,11 +168,11 @@ template void DwarfFDECache::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) Index: libunwind/trunk/src/config.h =================================================================== --- libunwind/trunk/src/config.h +++ libunwind/trunk/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