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 //===----------------------------------------------------------------------===// 18 //=== WARNING: Implementation here must contain only TRULY operating system 19 //=== independent code. 20 //===----------------------------------------------------------------------===// 21 22 #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0 23 // Define all methods as no-ops if threading is explicitly disabled 24 25 using namespace llvm; 26 using namespace sys; 27 28 RWMutexImpl::RWMutexImpl() = default; 29 RWMutexImpl::~RWMutexImpl() = default; 30 31 bool RWMutexImpl::reader_acquire() { return true; } 32 bool RWMutexImpl::reader_release() { return true; } 33 bool RWMutexImpl::writer_acquire() { return true; } 34 bool RWMutexImpl::writer_release() { return true; } 35 36 #else 37 38 #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) 39 40 #include <cassert> 41 #include <cstdlib> 42 #include <pthread.h> 43 44 using namespace llvm; 45 using namespace sys; 46 47 // Construct a RWMutex using pthread calls 48 RWMutexImpl::RWMutexImpl() 49 { 50 // Declare the pthread_rwlock data structures 51 pthread_rwlock_t* rwlock = 52 static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t))); 53 54 #ifdef __APPLE__ 55 // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. 56 bzero(rwlock, sizeof(pthread_rwlock_t)); 57 #endif 58 59 // Initialize the rwlock 60 int errorcode = pthread_rwlock_init(rwlock, nullptr); 61 (void)errorcode; 62 assert(errorcode == 0); 63 64 // Assign the data member 65 data_ = rwlock; 66 } 67 68 // Destruct a RWMutex 69 RWMutexImpl::~RWMutexImpl() 70 { 71 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 72 assert(rwlock != nullptr); 73 pthread_rwlock_destroy(rwlock); 74 free(rwlock); 75 } 76 77 bool 78 RWMutexImpl::reader_acquire() 79 { 80 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 81 assert(rwlock != nullptr); 82 83 int errorcode = pthread_rwlock_rdlock(rwlock); 84 return errorcode == 0; 85 } 86 87 bool 88 RWMutexImpl::reader_release() 89 { 90 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 91 assert(rwlock != nullptr); 92 93 int errorcode = pthread_rwlock_unlock(rwlock); 94 return errorcode == 0; 95 } 96 97 bool 98 RWMutexImpl::writer_acquire() 99 { 100 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 101 assert(rwlock != nullptr); 102 103 int errorcode = pthread_rwlock_wrlock(rwlock); 104 return errorcode == 0; 105 } 106 107 bool 108 RWMutexImpl::writer_release() 109 { 110 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 111 assert(rwlock != nullptr); 112 113 int errorcode = pthread_rwlock_unlock(rwlock); 114 return errorcode == 0; 115 } 116 117 #elif defined(LLVM_ON_UNIX) 118 #include "Unix/RWMutex.inc" 119 #elif defined( _WIN32) 120 #include "Windows/RWMutex.inc" 121 #else 122 #warning Neither LLVM_ON_UNIX nor _WIN32 was set in Support/Mutex.cpp 123 #endif 124 #endif 125