1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 // 8 // Abstract interface to shared reader/writer log, hiding platform and 9 // configuration differences. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef __RWMUTEX_HPP__ 14 #define __RWMUTEX_HPP__ 15 16 #if defined(_WIN32) 17 #include <windows.h> 18 #elif !defined(_LIBUNWIND_HAS_NO_THREADS) 19 #include <pthread.h> 20 #if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB) 21 #pragma comment(lib, "pthread") 22 #endif 23 #endif 24 25 namespace libunwind { 26 27 #if defined(_LIBUNWIND_HAS_NO_THREADS) 28 29 class _LIBUNWIND_HIDDEN RWMutex { 30 public: 31 bool lock_shared() { return true; } 32 bool unlock_shared() { return true; } 33 bool lock() { return true; } 34 bool unlock() { return true; } 35 }; 36 37 #elif defined(_WIN32) 38 39 class _LIBUNWIND_HIDDEN RWMutex { 40 public: 41 bool lock_shared() { 42 AcquireSRWLockShared(&_lock); 43 return true; 44 } 45 bool unlock_shared() { 46 ReleaseSRWLockShared(&_lock); 47 return true; 48 } 49 bool lock() { 50 AcquireSRWLockExclusive(&_lock); 51 return true; 52 } 53 bool unlock() { 54 ReleaseSRWLockExclusive(&_lock); 55 return true; 56 } 57 58 private: 59 SRWLOCK _lock = SRWLOCK_INIT; 60 }; 61 62 #elif !defined(LIBUNWIND_USE_WEAK_PTHREAD) 63 64 class _LIBUNWIND_HIDDEN RWMutex { 65 public: 66 bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0; } 67 bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; } 68 bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; } 69 bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; } 70 71 private: 72 pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; 73 }; 74 75 #else 76 77 extern "C" int __attribute__((weak)) 78 pthread_create(pthread_t *thread, const pthread_attr_t *attr, 79 void *(*start_routine)(void *), void *arg); 80 extern "C" int __attribute__((weak)) 81 pthread_rwlock_rdlock(pthread_rwlock_t *lock); 82 extern "C" int __attribute__((weak)) 83 pthread_rwlock_wrlock(pthread_rwlock_t *lock); 84 extern "C" int __attribute__((weak)) 85 pthread_rwlock_unlock(pthread_rwlock_t *lock); 86 87 // Calls to the locking functions are gated on pthread_create, and not the 88 // functions themselves, because the data structure should only be locked if 89 // another thread has been created. This is what similar libraries do. 90 91 class _LIBUNWIND_HIDDEN RWMutex { 92 public: 93 bool lock_shared() { 94 return !pthread_create || (pthread_rwlock_rdlock(&_lock) == 0); 95 } 96 bool unlock_shared() { 97 return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0); 98 } 99 bool lock() { 100 return !pthread_create || (pthread_rwlock_wrlock(&_lock) == 0); 101 } 102 bool unlock() { 103 return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0); 104 } 105 106 private: 107 pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; 108 }; 109 110 #endif 111 112 } // namespace libunwind 113 114 #endif // __RWMUTEX_HPP__ 115