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