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()27bool RWMutexImpl::lock_shared() { return true; } unlock_shared()28bool RWMutexImpl::unlock_shared() { return true; } try_lock_shared()29bool RWMutexImpl::try_lock_shared() { return true; } lock()30bool RWMutexImpl::lock() { return true; } unlock()31bool RWMutexImpl::unlock() { return true; } try_lock()32bool 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()43RWMutexImpl::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()64RWMutexImpl::~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()73RWMutexImpl::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()83RWMutexImpl::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()92bool 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()101RWMutexImpl::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()111RWMutexImpl::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()120bool 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()130RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } 131 ~RWMutexImpl()132RWMutexImpl::~RWMutexImpl() { 133 delete static_cast<MutexImpl *>(data_); 134 } 135 lock_shared()136bool RWMutexImpl::lock_shared() { 137 return static_cast<MutexImpl *>(data_)->acquire(); 138 } 139 unlock_shared()140bool RWMutexImpl::unlock_shared() { 141 return static_cast<MutexImpl *>(data_)->release(); 142 } 143 try_lock_shared()144bool RWMutexImpl::try_lock_shared() { 145 return static_cast<MutexImpl *>(data_)->tryacquire(); 146 } 147 lock()148bool RWMutexImpl::lock() { 149 return static_cast<MutexImpl *>(data_)->acquire(); 150 } 151 unlock()152bool RWMutexImpl::unlock() { 153 return static_cast<MutexImpl *>(data_)->release(); 154 } 155 try_lock()156bool RWMutexImpl::try_lock() { 157 return static_cast<MutexImpl *>(data_)->tryacquire(); 158 } 159 160 #endif 161 #endif 162 #endif 163