1 | //===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===// |
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 | // |
9 | // This file implements the llvm::sys::RWMutex class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/Support/Allocator.h" |
14 | #include "llvm/Support/RWMutex.h" |
15 | #include "llvm/Config/config.h" |
16 | |
17 | #if defined(LLVM_USE_RW_MUTEX_IMPL) |
18 | using namespace llvm; |
19 | using namespace sys; |
20 | |
21 | #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0 |
22 | // Define all methods as no-ops if threading is explicitly disabled |
23 | |
24 | RWMutexImpl::RWMutexImpl() = default; |
25 | RWMutexImpl::~RWMutexImpl() = default; |
26 | |
27 | bool RWMutexImpl::lock_shared() { return true; } |
28 | bool RWMutexImpl::unlock_shared() { return true; } |
29 | bool RWMutexImpl::try_lock_shared() { return true; } |
30 | bool RWMutexImpl::lock() { return true; } |
31 | bool RWMutexImpl::unlock() { return true; } |
32 | bool RWMutexImpl::try_lock() { return true; } |
33 | |
34 | #else |
35 | |
36 | #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) |
37 | |
38 | #include <cassert> |
39 | #include <cstdlib> |
40 | #include <pthread.h> |
41 | |
42 | // Construct a RWMutex using pthread calls |
43 | RWMutexImpl::RWMutexImpl() |
44 | { |
45 | // Declare the pthread_rwlock data structures |
46 | pthread_rwlock_t* rwlock = |
47 | static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t))); |
48 | |
49 | #ifdef __APPLE__ |
50 | // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. |
51 | bzero(rwlock, sizeof(pthread_rwlock_t)); |
52 | #endif |
53 | |
54 | // Initialize the rwlock |
55 | int errorcode = pthread_rwlock_init(rwlock, nullptr); |
56 | (void)errorcode; |
57 | assert(errorcode == 0); |
58 | |
59 | // Assign the data member |
60 | data_ = rwlock; |
61 | } |
62 | |
63 | // Destruct a RWMutex |
64 | RWMutexImpl::~RWMutexImpl() |
65 | { |
66 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
67 | assert(rwlock != nullptr); |
68 | pthread_rwlock_destroy(rwlock); |
69 | free(rwlock); |
70 | } |
71 | |
72 | bool |
73 | RWMutexImpl::lock_shared() |
74 | { |
75 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
76 | assert(rwlock != nullptr); |
77 | |
78 | int errorcode = pthread_rwlock_rdlock(rwlock); |
79 | return errorcode == 0; |
80 | } |
81 | |
82 | bool |
83 | RWMutexImpl::unlock_shared() |
84 | { |
85 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
86 | assert(rwlock != nullptr); |
87 | |
88 | int errorcode = pthread_rwlock_unlock(rwlock); |
89 | return errorcode == 0; |
90 | } |
91 | |
92 | bool RWMutexImpl::try_lock_shared() { |
93 | pthread_rwlock_t *rwlock = static_cast<pthread_rwlock_t *>(data_); |
94 | assert(rwlock != nullptr); |
95 | |
96 | int errorcode = pthread_rwlock_tryrdlock(rwlock); |
97 | return errorcode == 0; |
98 | } |
99 | |
100 | bool |
101 | RWMutexImpl::lock() |
102 | { |
103 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
104 | assert(rwlock != nullptr); |
105 | |
106 | int errorcode = pthread_rwlock_wrlock(rwlock); |
107 | return errorcode == 0; |
108 | } |
109 | |
110 | bool |
111 | RWMutexImpl::unlock() |
112 | { |
113 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
114 | assert(rwlock != nullptr); |
115 | |
116 | int errorcode = pthread_rwlock_unlock(rwlock); |
117 | return errorcode == 0; |
118 | } |
119 | |
120 | bool RWMutexImpl::try_lock() { |
121 | pthread_rwlock_t *rwlock = static_cast<pthread_rwlock_t *>(data_); |
122 | assert(rwlock != nullptr); |
123 | |
124 | int errorcode = pthread_rwlock_trywrlock(rwlock); |
125 | return errorcode == 0; |
126 | } |
127 | |
128 | #else |
129 | |
130 | RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } |
131 | |
132 | RWMutexImpl::~RWMutexImpl() { |
133 | delete static_cast<MutexImpl *>(data_); |
134 | } |
135 | |
136 | bool RWMutexImpl::lock_shared() { |
137 | return static_cast<MutexImpl *>(data_)->acquire(); |
138 | } |
139 | |
140 | bool RWMutexImpl::unlock_shared() { |
141 | return static_cast<MutexImpl *>(data_)->release(); |
142 | } |
143 | |
144 | bool RWMutexImpl::try_lock_shared() { |
145 | return static_cast<MutexImpl *>(data_)->tryacquire(); |
146 | } |
147 | |
148 | bool RWMutexImpl::lock() { |
149 | return static_cast<MutexImpl *>(data_)->acquire(); |
150 | } |
151 | |
152 | bool RWMutexImpl::unlock() { |
153 | return static_cast<MutexImpl *>(data_)->release(); |
154 | } |
155 | |
156 | bool RWMutexImpl::try_lock() { |
157 | return static_cast<MutexImpl *>(data_)->tryacquire(); |
158 | } |
159 | |
160 | #endif |
161 | #endif |
162 | #endif |
163 | |