10b57cec5SDimitry Andric //===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the llvm::sys::RWMutex class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 140b57cec5SDimitry Andric #include "llvm/Support/RWMutex.h" 150b57cec5SDimitry Andric #include "llvm/Config/config.h" 160b57cec5SDimitry Andric 17*8bcb0991SDimitry Andric #if defined(LLVM_USE_RW_MUTEX_IMPL) 18*8bcb0991SDimitry Andric using namespace llvm; 19*8bcb0991SDimitry Andric using namespace sys; 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0 220b57cec5SDimitry Andric // Define all methods as no-ops if threading is explicitly disabled 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric RWMutexImpl::RWMutexImpl() = default; 250b57cec5SDimitry Andric RWMutexImpl::~RWMutexImpl() = default; 260b57cec5SDimitry Andric 27*8bcb0991SDimitry Andric bool RWMutexImpl::lock_shared() { return true; } 28*8bcb0991SDimitry Andric bool RWMutexImpl::unlock_shared() { return true; } 29*8bcb0991SDimitry Andric bool RWMutexImpl::lock() { return true; } 30*8bcb0991SDimitry Andric bool RWMutexImpl::unlock() { return true; } 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #else 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric #include <cassert> 370b57cec5SDimitry Andric #include <cstdlib> 380b57cec5SDimitry Andric #include <pthread.h> 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric // Construct a RWMutex using pthread calls 410b57cec5SDimitry Andric RWMutexImpl::RWMutexImpl() 420b57cec5SDimitry Andric { 430b57cec5SDimitry Andric // Declare the pthread_rwlock data structures 440b57cec5SDimitry Andric pthread_rwlock_t* rwlock = 450b57cec5SDimitry Andric static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t))); 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric #ifdef __APPLE__ 480b57cec5SDimitry Andric // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. 490b57cec5SDimitry Andric bzero(rwlock, sizeof(pthread_rwlock_t)); 500b57cec5SDimitry Andric #endif 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // Initialize the rwlock 530b57cec5SDimitry Andric int errorcode = pthread_rwlock_init(rwlock, nullptr); 540b57cec5SDimitry Andric (void)errorcode; 550b57cec5SDimitry Andric assert(errorcode == 0); 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // Assign the data member 580b57cec5SDimitry Andric data_ = rwlock; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Destruct a RWMutex 620b57cec5SDimitry Andric RWMutexImpl::~RWMutexImpl() 630b57cec5SDimitry Andric { 640b57cec5SDimitry Andric pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 650b57cec5SDimitry Andric assert(rwlock != nullptr); 660b57cec5SDimitry Andric pthread_rwlock_destroy(rwlock); 670b57cec5SDimitry Andric free(rwlock); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric bool 71*8bcb0991SDimitry Andric RWMutexImpl::lock_shared() 720b57cec5SDimitry Andric { 730b57cec5SDimitry Andric pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 740b57cec5SDimitry Andric assert(rwlock != nullptr); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric int errorcode = pthread_rwlock_rdlock(rwlock); 770b57cec5SDimitry Andric return errorcode == 0; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric bool 81*8bcb0991SDimitry Andric RWMutexImpl::unlock_shared() 820b57cec5SDimitry Andric { 830b57cec5SDimitry Andric pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 840b57cec5SDimitry Andric assert(rwlock != nullptr); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric int errorcode = pthread_rwlock_unlock(rwlock); 870b57cec5SDimitry Andric return errorcode == 0; 880b57cec5SDimitry Andric } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric bool 91*8bcb0991SDimitry Andric RWMutexImpl::lock() 920b57cec5SDimitry Andric { 930b57cec5SDimitry Andric pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 940b57cec5SDimitry Andric assert(rwlock != nullptr); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric int errorcode = pthread_rwlock_wrlock(rwlock); 970b57cec5SDimitry Andric return errorcode == 0; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric bool 101*8bcb0991SDimitry Andric RWMutexImpl::unlock() 1020b57cec5SDimitry Andric { 1030b57cec5SDimitry Andric pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 1040b57cec5SDimitry Andric assert(rwlock != nullptr); 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric int errorcode = pthread_rwlock_unlock(rwlock); 1070b57cec5SDimitry Andric return errorcode == 0; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric #else 111*8bcb0991SDimitry Andric 112*8bcb0991SDimitry Andric RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } 113*8bcb0991SDimitry Andric 114*8bcb0991SDimitry Andric RWMutexImpl::~RWMutexImpl() { 115*8bcb0991SDimitry Andric delete static_cast<MutexImpl *>(data_); 116*8bcb0991SDimitry Andric } 117*8bcb0991SDimitry Andric 118*8bcb0991SDimitry Andric bool RWMutexImpl::lock_shared() { 119*8bcb0991SDimitry Andric return static_cast<MutexImpl *>(data_)->acquire(); 120*8bcb0991SDimitry Andric } 121*8bcb0991SDimitry Andric 122*8bcb0991SDimitry Andric bool RWMutexImpl::unlock_shared() { 123*8bcb0991SDimitry Andric return static_cast<MutexImpl *>(data_)->release(); 124*8bcb0991SDimitry Andric } 125*8bcb0991SDimitry Andric 126*8bcb0991SDimitry Andric bool RWMutexImpl::lock() { 127*8bcb0991SDimitry Andric return static_cast<MutexImpl *>(data_)->acquire(); 128*8bcb0991SDimitry Andric } 129*8bcb0991SDimitry Andric 130*8bcb0991SDimitry Andric bool RWMutexImpl::unlock() { 131*8bcb0991SDimitry Andric return static_cast<MutexImpl *>(data_)->release(); 132*8bcb0991SDimitry Andric } 133*8bcb0991SDimitry Andric 134*8bcb0991SDimitry Andric #endif 1350b57cec5SDimitry Andric #endif 1360b57cec5SDimitry Andric #endif 137