[libunwind] r316364 - Abstract rwlocks into a class, provide a SRW lock implementation for windows

Martin Storsjo via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 23 12:29:36 PDT 2017


Author: mstorsjo
Date: Mon Oct 23 12:29:36 2017
New Revision: 316364

URL: http://llvm.org/viewvc/llvm-project?rev=316364&view=rev
Log:
Abstract rwlocks into a class, provide a SRW lock implementation for windows

This requires _WIN32_WINNT >= 0x0600.

If someone wants to spend effort on supporting earlier versions,
one can easily add another fallback implementation based on
critical sections, or try to load SRW lock functions dynamically.

This makes sure that the FDE cache is thread safe on windows.

Differential Revision: https://reviews.llvm.org/D38704

Added:
    libunwind/trunk/src/RWMutex.hpp
Modified:
    libunwind/trunk/src/CMakeLists.txt
    libunwind/trunk/src/UnwindCursor.hpp
    libunwind/trunk/src/config.h

Modified: libunwind/trunk/src/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/CMakeLists.txt?rev=316364&r1=316363&r2=316364&view=diff
==============================================================================
--- libunwind/trunk/src/CMakeLists.txt (original)
+++ libunwind/trunk/src/CMakeLists.txt Mon Oct 23 12:29:36 2017
@@ -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)

Added: libunwind/trunk/src/RWMutex.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/RWMutex.hpp?rev=316364&view=auto
==============================================================================
--- libunwind/trunk/src/RWMutex.hpp (added)
+++ libunwind/trunk/src/RWMutex.hpp Mon Oct 23 12:29:36 2017
@@ -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__

Modified: libunwind/trunk/src/UnwindCursor.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/UnwindCursor.hpp?rev=316364&r1=316363&r2=316364&view=diff
==============================================================================
--- libunwind/trunk/src/UnwindCursor.hpp (original)
+++ libunwind/trunk/src/UnwindCursor.hpp Mon Oct 23 12:29:36 2017
@@ -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 = &_initial
 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>::_registeredForDyl
 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>::fin
       }
     }
   }
-  _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, pi
     _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_
     }
   }
   _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(co
 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)
 

Modified: libunwind/trunk/src/config.h
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/config.h?rev=316364&r1=316363&r2=316364&view=diff
==============================================================================
--- libunwind/trunk/src/config.h (original)
+++ libunwind/trunk/src/config.h Mon Oct 23 12:29:36 2017
@@ -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




More information about the cfe-commits mailing list