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(ENABLE_THREADS) || 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 46 // This variable is useful for situations where the pthread library has been 47 // compiled with weak linkage for its interface symbols. This allows the 48 // threading support to be turned off by simply not linking against -lpthread. 49 // In that situation, the value of pthread_mutex_init will be 0 and 50 // consequently pthread_enabled will be false. In such situations, all the 51 // pthread operations become no-ops and the functions all return false. If 52 // pthread_rwlock_init does have an address, then rwlock support is enabled. 53 // Note: all LLVM tools will link against -lpthread if its available since it 54 // is configured into the LIBS variable. 55 // Note: this line of code generates a warning if pthread_rwlock_init is not 56 // declared with weak linkage. It's safe to ignore the warning. 57 static const bool pthread_enabled = true; 58 59 // Construct a RWMutex using pthread calls RWMutexImpl()60RWMutexImpl::RWMutexImpl() 61 : data_(0) 62 { 63 if (pthread_enabled) 64 { 65 // Declare the pthread_rwlock data structures 66 pthread_rwlock_t* rwlock = 67 static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t))); 68 69 #ifdef __APPLE__ 70 // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. 71 bzero(rwlock, sizeof(pthread_rwlock_t)); 72 #endif 73 74 // Initialize the rwlock 75 int errorcode = pthread_rwlock_init(rwlock, NULL); 76 (void)errorcode; 77 assert(errorcode == 0); 78 79 // Assign the data member 80 data_ = rwlock; 81 } 82 } 83 84 // Destruct a RWMutex ~RWMutexImpl()85RWMutexImpl::~RWMutexImpl() 86 { 87 if (pthread_enabled) 88 { 89 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 90 assert(rwlock != 0); 91 pthread_rwlock_destroy(rwlock); 92 free(rwlock); 93 } 94 } 95 96 bool reader_acquire()97RWMutexImpl::reader_acquire() 98 { 99 if (pthread_enabled) 100 { 101 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 102 assert(rwlock != 0); 103 104 int errorcode = pthread_rwlock_rdlock(rwlock); 105 return errorcode == 0; 106 } else return false; 107 } 108 109 bool reader_release()110RWMutexImpl::reader_release() 111 { 112 if (pthread_enabled) 113 { 114 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 115 assert(rwlock != 0); 116 117 int errorcode = pthread_rwlock_unlock(rwlock); 118 return errorcode == 0; 119 } else return false; 120 } 121 122 bool writer_acquire()123RWMutexImpl::writer_acquire() 124 { 125 if (pthread_enabled) 126 { 127 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 128 assert(rwlock != 0); 129 130 int errorcode = pthread_rwlock_wrlock(rwlock); 131 return errorcode == 0; 132 } else return false; 133 } 134 135 bool writer_release()136RWMutexImpl::writer_release() 137 { 138 if (pthread_enabled) 139 { 140 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 141 assert(rwlock != 0); 142 143 int errorcode = pthread_rwlock_unlock(rwlock); 144 return errorcode == 0; 145 } else return false; 146 } 147 148 } 149 150 #elif defined(LLVM_ON_UNIX) 151 #include "Unix/RWMutex.inc" 152 #elif defined( LLVM_ON_WIN32) 153 #include "Windows/RWMutex.inc" 154 #else 155 #warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp 156 #endif 157 #endif 158