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