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) 18using namespace llvm; 19using 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 24RWMutexImpl::RWMutexImpl() = default; 25RWMutexImpl::~RWMutexImpl() = default; 26 27bool RWMutexImpl::lock_shared() { return true; } 28bool RWMutexImpl::unlock_shared() { return true; } 29bool RWMutexImpl::lock() { return true; } 30bool 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 41RWMutexImpl::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 62RWMutexImpl::~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 70bool 71RWMutexImpl::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 80bool 81RWMutexImpl::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 90bool 91RWMutexImpl::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 100bool 101RWMutexImpl::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 112RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } 113 114RWMutexImpl::~RWMutexImpl() { 115 delete static_cast<MutexImpl *>(data_); 116} 117 118bool RWMutexImpl::lock_shared() { 119 return static_cast<MutexImpl *>(data_)->acquire(); 120} 121 122bool RWMutexImpl::unlock_shared() { 123 return static_cast<MutexImpl *>(data_)->release(); 124} 125 126bool RWMutexImpl::lock() { 127 return static_cast<MutexImpl *>(data_)->acquire(); 128} 129 130bool RWMutexImpl::unlock() { 131 return static_cast<MutexImpl *>(data_)->release(); 132} 133 134#endif 135#endif 136#endif 137