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