1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | //===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the llvm::sys::RWMutex class. // //===----------------------------------------------------------------------===// #include "llvm/Support/Allocator.h" #include "llvm/Support/RWMutex.h" #include "llvm/Config/config.h" #if defined(LLVM_USE_RW_MUTEX_IMPL) using namespace llvm; using namespace sys; #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0 // Define all methods as no-ops if threading is explicitly disabled RWMutexImpl::RWMutexImpl() = default; RWMutexImpl::~RWMutexImpl() = default; bool RWMutexImpl::lock_shared() { return true; } bool RWMutexImpl::unlock_shared() { return true; } bool RWMutexImpl::lock() { return true; } bool RWMutexImpl::unlock() { return true; } #else #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) #include <cassert> #include <cstdlib> #include <pthread.h> // Construct a RWMutex using pthread calls RWMutexImpl::RWMutexImpl() { // Declare the pthread_rwlock data structures pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t))); #ifdef __APPLE__ // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. bzero(rwlock, sizeof(pthread_rwlock_t)); #endif // Initialize the rwlock int errorcode = pthread_rwlock_init(rwlock, nullptr); (void)errorcode; assert(errorcode == 0); // Assign the data member data_ = rwlock; } // Destruct a RWMutex RWMutexImpl::~RWMutexImpl() { pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); assert(rwlock != nullptr); pthread_rwlock_destroy(rwlock); free(rwlock); } bool RWMutexImpl::lock_shared() { pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); assert(rwlock != nullptr); int errorcode = pthread_rwlock_rdlock(rwlock); return errorcode == 0; } bool RWMutexImpl::unlock_shared() { pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); assert(rwlock != nullptr); int errorcode = pthread_rwlock_unlock(rwlock); return errorcode == 0; } bool RWMutexImpl::lock() { pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); assert(rwlock != nullptr); int errorcode = pthread_rwlock_wrlock(rwlock); return errorcode == 0; } bool RWMutexImpl::unlock() { pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); assert(rwlock != nullptr); int errorcode = pthread_rwlock_unlock(rwlock); return errorcode == 0; } #else RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } RWMutexImpl::~RWMutexImpl() { delete static_cast<MutexImpl *>(data_); } bool RWMutexImpl::lock_shared() { return static_cast<MutexImpl *>(data_)->acquire(); } bool RWMutexImpl::unlock_shared() { return static_cast<MutexImpl *>(data_)->release(); } bool RWMutexImpl::lock() { return static_cast<MutexImpl *>(data_)->acquire(); } bool RWMutexImpl::unlock() { return static_cast<MutexImpl *>(data_)->release(); } #endif #endif #endif |