xref: /freebsd/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
lock_shared()27 bool RWMutexImpl::lock_shared() { return true; }
unlock_shared()28 bool RWMutexImpl::unlock_shared() { return true; }
try_lock_shared()29 bool RWMutexImpl::try_lock_shared() { return true; }
lock()30 bool RWMutexImpl::lock() { return true; }
unlock()31 bool RWMutexImpl::unlock() { return true; }
try_lock()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
RWMutexImpl()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
~RWMutexImpl()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
lock_shared()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
unlock_shared()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 
try_lock_shared()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
lock()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
unlock()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 
try_lock()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 
RWMutexImpl()130 RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
131 
~RWMutexImpl()132 RWMutexImpl::~RWMutexImpl() {
133   delete static_cast<MutexImpl *>(data_);
134 }
135 
lock_shared()136 bool RWMutexImpl::lock_shared() {
137   return static_cast<MutexImpl *>(data_)->acquire();
138 }
139 
unlock_shared()140 bool RWMutexImpl::unlock_shared() {
141   return static_cast<MutexImpl *>(data_)->release();
142 }
143 
try_lock_shared()144 bool RWMutexImpl::try_lock_shared() {
145   return static_cast<MutexImpl *>(data_)->tryacquire();
146 }
147 
lock()148 bool RWMutexImpl::lock() {
149   return static_cast<MutexImpl *>(data_)->acquire();
150 }
151 
unlock()152 bool RWMutexImpl::unlock() {
153   return static_cast<MutexImpl *>(data_)->release();
154 }
155 
try_lock()156 bool RWMutexImpl::try_lock() {
157   return static_cast<MutexImpl *>(data_)->tryacquire();
158 }
159 
160 #endif
161 #endif
162 #endif
163