1 //===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the llvm::sys::RWMutex class.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Support/RWMutex.h"
14 #include "llvm/Config/config.h"
15 #include "llvm/Config/llvm-config.h" // for LLVM_ENABLE_THREADS
16 #include "llvm/Support/Allocator.h"
18 #if defined(LLVM_USE_RW_MUTEX_IMPL)
22 #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
23 // Define all methods as no-ops if threading is explicitly disabled
25 RWMutexImpl::RWMutexImpl() = default;
26 RWMutexImpl::~RWMutexImpl() = default;
28 bool RWMutexImpl::lock_shared() { return true; }
29 bool RWMutexImpl::unlock_shared() { return true; }
30 bool RWMutexImpl::try_lock_shared() { return true; }
31 bool RWMutexImpl::lock() { return true; }
32 bool RWMutexImpl::unlock() { return true; }
33 bool RWMutexImpl::try_lock() { return true; }
37 #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
43 // Construct a RWMutex using pthread calls
44 RWMutexImpl::RWMutexImpl()
46 // Declare the pthread_rwlock data structures
47 pthread_rwlock_t
* rwlock
=
48 static_cast<pthread_rwlock_t
*>(safe_malloc(sizeof(pthread_rwlock_t
)));
51 // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
52 bzero(rwlock
, sizeof(pthread_rwlock_t
));
55 // Initialize the rwlock
56 int errorcode
= pthread_rwlock_init(rwlock
, nullptr);
58 assert(errorcode
== 0);
60 // Assign the data member
65 RWMutexImpl::~RWMutexImpl()
67 pthread_rwlock_t
* rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
68 assert(rwlock
!= nullptr);
69 pthread_rwlock_destroy(rwlock
);
74 RWMutexImpl::lock_shared()
76 pthread_rwlock_t
* rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
77 assert(rwlock
!= nullptr);
79 int errorcode
= pthread_rwlock_rdlock(rwlock
);
80 return errorcode
== 0;
84 RWMutexImpl::unlock_shared()
86 pthread_rwlock_t
* rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
87 assert(rwlock
!= nullptr);
89 int errorcode
= pthread_rwlock_unlock(rwlock
);
90 return errorcode
== 0;
93 bool RWMutexImpl::try_lock_shared() {
94 pthread_rwlock_t
*rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
95 assert(rwlock
!= nullptr);
97 int errorcode
= pthread_rwlock_tryrdlock(rwlock
);
98 return errorcode
== 0;
104 pthread_rwlock_t
* rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
105 assert(rwlock
!= nullptr);
107 int errorcode
= pthread_rwlock_wrlock(rwlock
);
108 return errorcode
== 0;
112 RWMutexImpl::unlock()
114 pthread_rwlock_t
* rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
115 assert(rwlock
!= nullptr);
117 int errorcode
= pthread_rwlock_unlock(rwlock
);
118 return errorcode
== 0;
121 bool RWMutexImpl::try_lock() {
122 pthread_rwlock_t
*rwlock
= static_cast<pthread_rwlock_t
*>(data_
);
123 assert(rwlock
!= nullptr);
125 int errorcode
= pthread_rwlock_trywrlock(rwlock
);
126 return errorcode
== 0;
131 RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
133 RWMutexImpl::~RWMutexImpl() {
134 delete static_cast<MutexImpl
*>(data_
);
137 bool RWMutexImpl::lock_shared() {
138 return static_cast<MutexImpl
*>(data_
)->acquire();
141 bool RWMutexImpl::unlock_shared() {
142 return static_cast<MutexImpl
*>(data_
)->release();
145 bool RWMutexImpl::try_lock_shared() {
146 return static_cast<MutexImpl
*>(data_
)->tryacquire();
149 bool RWMutexImpl::lock() {
150 return static_cast<MutexImpl
*>(data_
)->acquire();
153 bool RWMutexImpl::unlock() {
154 return static_cast<MutexImpl
*>(data_
)->release();
157 bool RWMutexImpl::try_lock() {
158 return static_cast<MutexImpl
*>(data_
)->tryacquire();