xref: /freebsd/contrib/llvm-project/libunwind/src/RWMutex.hpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
1*349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric // Abstract interface to shared reader/writer log, hiding platform and
90b57cec5SDimitry Andric // configuration differences.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef __RWMUTEX_HPP__
140b57cec5SDimitry Andric #define __RWMUTEX_HPP__
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #if defined(_WIN32)
170b57cec5SDimitry Andric #include <windows.h>
180b57cec5SDimitry Andric #elif !defined(_LIBUNWIND_HAS_NO_THREADS)
190b57cec5SDimitry Andric #include <pthread.h>
20480093f4SDimitry Andric #if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB)
210b57cec5SDimitry Andric #pragma comment(lib, "pthread")
220b57cec5SDimitry Andric #endif
230b57cec5SDimitry Andric #endif
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace libunwind {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #if defined(_LIBUNWIND_HAS_NO_THREADS)
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN RWMutex {
300b57cec5SDimitry Andric public:
lock_shared()310b57cec5SDimitry Andric   bool lock_shared() { return true; }
unlock_shared()320b57cec5SDimitry Andric   bool unlock_shared() { return true; }
lock()330b57cec5SDimitry Andric   bool lock() { return true; }
unlock()340b57cec5SDimitry Andric   bool unlock() { return true; }
350b57cec5SDimitry Andric };
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #elif defined(_WIN32)
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN RWMutex {
400b57cec5SDimitry Andric public:
410b57cec5SDimitry Andric   bool lock_shared() {
420b57cec5SDimitry Andric     AcquireSRWLockShared(&_lock);
430b57cec5SDimitry Andric     return true;
440b57cec5SDimitry Andric   }
450b57cec5SDimitry Andric   bool unlock_shared() {
460b57cec5SDimitry Andric     ReleaseSRWLockShared(&_lock);
470b57cec5SDimitry Andric     return true;
480b57cec5SDimitry Andric   }
490b57cec5SDimitry Andric   bool lock() {
500b57cec5SDimitry Andric     AcquireSRWLockExclusive(&_lock);
510b57cec5SDimitry Andric     return true;
520b57cec5SDimitry Andric   }
530b57cec5SDimitry Andric   bool unlock() {
540b57cec5SDimitry Andric     ReleaseSRWLockExclusive(&_lock);
550b57cec5SDimitry Andric     return true;
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric private:
590b57cec5SDimitry Andric   SRWLOCK _lock = SRWLOCK_INIT;
600b57cec5SDimitry Andric };
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric #elif !defined(LIBUNWIND_USE_WEAK_PTHREAD)
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN RWMutex {
650b57cec5SDimitry Andric public:
660b57cec5SDimitry Andric   bool lock_shared() { return pthread_rwlock_rdlock(&_lock) == 0;  }
670b57cec5SDimitry Andric   bool unlock_shared() { return pthread_rwlock_unlock(&_lock) == 0; }
680b57cec5SDimitry Andric   bool lock() { return pthread_rwlock_wrlock(&_lock) == 0; }
690b57cec5SDimitry Andric   bool unlock() { return pthread_rwlock_unlock(&_lock) == 0; }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric private:
720b57cec5SDimitry Andric   pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
730b57cec5SDimitry Andric };
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric #else
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric extern "C" int __attribute__((weak))
780b57cec5SDimitry Andric pthread_create(pthread_t *thread, const pthread_attr_t *attr,
790b57cec5SDimitry Andric                void *(*start_routine)(void *), void *arg);
800b57cec5SDimitry Andric extern "C" int __attribute__((weak))
810b57cec5SDimitry Andric pthread_rwlock_rdlock(pthread_rwlock_t *lock);
820b57cec5SDimitry Andric extern "C" int __attribute__((weak))
830b57cec5SDimitry Andric pthread_rwlock_wrlock(pthread_rwlock_t *lock);
840b57cec5SDimitry Andric extern "C" int __attribute__((weak))
850b57cec5SDimitry Andric pthread_rwlock_unlock(pthread_rwlock_t *lock);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric // Calls to the locking functions are gated on pthread_create, and not the
880b57cec5SDimitry Andric // functions themselves, because the data structure should only be locked if
890b57cec5SDimitry Andric // another thread has been created. This is what similar libraries do.
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN RWMutex {
920b57cec5SDimitry Andric public:
930b57cec5SDimitry Andric   bool lock_shared() {
940b57cec5SDimitry Andric     return !pthread_create || (pthread_rwlock_rdlock(&_lock) == 0);
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric   bool unlock_shared() {
970b57cec5SDimitry Andric     return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0);
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric   bool lock() {
1000b57cec5SDimitry Andric     return !pthread_create || (pthread_rwlock_wrlock(&_lock) == 0);
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric   bool unlock() {
1030b57cec5SDimitry Andric     return !pthread_create || (pthread_rwlock_unlock(&_lock) == 0);
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric private:
1070b57cec5SDimitry Andric   pthread_rwlock_t _lock = PTHREAD_RWLOCK_INITIALIZER;
1080b57cec5SDimitry Andric };
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric #endif
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric } // namespace libunwind
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric #endif // __RWMUTEX_HPP__
115