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