1//===----------------------------- Registers.hpp --------------------------===// 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 25namespace libunwind { 26 27#if defined(_LIBUNWIND_HAS_NO_THREADS) 28 29class _LIBUNWIND_HIDDEN RWMutex { 30public: 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 39class _LIBUNWIND_HIDDEN RWMutex { 40public: 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 58private: 59 SRWLOCK _lock = SRWLOCK_INIT; 60}; 61 62#elif !defined(LIBUNWIND_USE_WEAK_PTHREAD) 63 64class _LIBUNWIND_HIDDEN RWMutex { 65public: 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 71private: 72 pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; 73}; 74 75#else 76 77extern "C" int __attribute__((weak)) 78pthread_create(pthread_t *thread, const pthread_attr_t *attr, 79 void *(*start_routine)(void *), void *arg); 80extern "C" int __attribute__((weak)) 81pthread_rwlock_rdlock(pthread_rwlock_t *lock); 82extern "C" int __attribute__((weak)) 83pthread_rwlock_wrlock(pthread_rwlock_t *lock); 84extern "C" int __attribute__((weak)) 85pthread_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 91class _LIBUNWIND_HIDDEN RWMutex { 92public: 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 106private: 107 pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER; 108}; 109 110#endif 111 112} // namespace libunwind 113 114#endif // __RWMUTEX_HPP__ 115