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