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::lock() { return true; } 30 bool RWMutexImpl::unlock() { return true; } 31 32 #else 33 34 #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) 35 36 #include <cassert> 37 #include <cstdlib> 38 #include <pthread.h> 39 40 // Construct a RWMutex using pthread calls 41 RWMutexImpl::RWMutexImpl() 42 { 43 // Declare the pthread_rwlock data structures 44 pthread_rwlock_t* rwlock = 45 static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t))); 46 47 #ifdef __APPLE__ 48 // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. 49 bzero(rwlock, sizeof(pthread_rwlock_t)); 50 #endif 51 52 // Initialize the rwlock 53 int errorcode = pthread_rwlock_init(rwlock, nullptr); 54 (void)errorcode; 55 assert(errorcode == 0); 56 57 // Assign the data member 58 data_ = rwlock; 59 } 60 61 // Destruct a RWMutex 62 RWMutexImpl::~RWMutexImpl() 63 { 64 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 65 assert(rwlock != nullptr); 66 pthread_rwlock_destroy(rwlock); 67 free(rwlock); 68 } 69 70 bool 71 RWMutexImpl::lock_shared() 72 { 73 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 74 assert(rwlock != nullptr); 75 76 int errorcode = pthread_rwlock_rdlock(rwlock); 77 return errorcode == 0; 78 } 79 80 bool 81 RWMutexImpl::unlock_shared() 82 { 83 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 84 assert(rwlock != nullptr); 85 86 int errorcode = pthread_rwlock_unlock(rwlock); 87 return errorcode == 0; 88 } 89 90 bool 91 RWMutexImpl::lock() 92 { 93 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 94 assert(rwlock != nullptr); 95 96 int errorcode = pthread_rwlock_wrlock(rwlock); 97 return errorcode == 0; 98 } 99 100 bool 101 RWMutexImpl::unlock() 102 { 103 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 104 assert(rwlock != nullptr); 105 106 int errorcode = pthread_rwlock_unlock(rwlock); 107 return errorcode == 0; 108 } 109 110 #else 111 112 RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } 113 114 RWMutexImpl::~RWMutexImpl() { 115 delete static_cast<MutexImpl *>(data_); 116 } 117 118 bool RWMutexImpl::lock_shared() { 119 return static_cast<MutexImpl *>(data_)->acquire(); 120 } 121 122 bool RWMutexImpl::unlock_shared() { 123 return static_cast<MutexImpl *>(data_)->release(); 124 } 125 126 bool RWMutexImpl::lock() { 127 return static_cast<MutexImpl *>(data_)->acquire(); 128 } 129 130 bool RWMutexImpl::unlock() { 131 return static_cast<MutexImpl *>(data_)->release(); 132 } 133 134 #endif 135 #endif 136 #endif 137