mstorsjo updated this revision to Diff 119094. mstorsjo retitled this revision from "[libunwind] Emulate pthread rwlocks via SRW locks for windows" to "[libunwind] Abstract rwlocks into a class, provide a SRW lock implementation for windows". mstorsjo edited the summary of this revision. mstorsjo added reviewers: majnemer, zturner. mstorsjo removed subscribers: majnemer, zturner. mstorsjo added a comment. Herald added a subscriber: mgorny.
Instead of trying to emulate the pthread rwlocks api with windows implementations, add a RWMutex class (with an interface similar to SmartRWMutex from LLVM) with inline implementations, which can either be no-ops (for no-threads configurations), implemented with SRW locks for windows or pthreads. https://reviews.llvm.org/D38704 Files: src/CMakeLists.txt src/RWMutex.hpp src/UnwindCursor.hpp src/config.h
Index: src/config.h =================================================================== --- src/config.h +++ 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 Index: src/UnwindCursor.hpp =================================================================== --- src/UnwindCursor.hpp +++ 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 @@ // 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 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,24 +98,24 @@ 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)) { result = p->fde; break; } } } - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); return result; } 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 @@ _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 @@ } } _bufferUsed = d; - _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); + _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); } #ifdef __APPLE__ @@ -174,11 +168,11 @@ 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) Index: src/RWMutex.hpp =================================================================== --- /dev/null +++ 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__ Index: src/CMakeLists.txt =================================================================== --- src/CMakeLists.txt +++ 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)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits