--- /dev/null
+//===----------------------------- 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__
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#ifndef _LIBUNWIND_HAS_NO_THREADS
- #include <pthread.h>
-#endif
#include <unwind.h>
#ifdef __APPLE__
#include "EHHeaderParser.hpp"
#include "libunwind.h"
#include "Registers.hpp"
+#include "RWMutex.hpp"
#include "Unwind-EHABI.h"
namespace libunwind {
// 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;
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>
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)) {
}
}
}
- _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
+ _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());
return result;
}
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;
_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) {
}
}
_bufferUsed = d;
- _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
+ _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
}
#ifdef __APPLE__
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)
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