12a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===// 22a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// 32a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// The LLVM Compiler Infrastructure 42a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// 52a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// This file is distributed under the University of Illinois Open Source 62a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// License. See LICENSE.TXT for details. 72a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// 82a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//===----------------------------------------------------------------------===// 92a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// 102a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// This file implements the llvm::sys::RWMutex class. 112a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// 122a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//===----------------------------------------------------------------------===// 132a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 142a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#include "llvm/Config/config.h" 151f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/RWMutex.h" 16107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson#include <cstring> 172a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 182a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//===----------------------------------------------------------------------===// 192a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//=== WARNING: Implementation here must contain only TRULY operating system 202a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//=== independent code. 212a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson//===----------------------------------------------------------------------===// 222a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 232a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0 242a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// Define all methods as no-ops if threading is explicitly disabled 252a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonnamespace llvm { 262a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonusing namespace sys; 27b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::RWMutexImpl() { } 28b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::~RWMutexImpl() { } 29b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen Andersonbool RWMutexImpl::reader_acquire() { return true; } 30b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen Andersonbool RWMutexImpl::reader_release() { return true; } 31b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen Andersonbool RWMutexImpl::writer_acquire() { return true; } 32b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen Andersonbool RWMutexImpl::writer_release() { return true; } 332a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 342a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#else 352a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 362a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) 372a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 382a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#include <cassert> 392a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#include <pthread.h> 402a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#include <stdlib.h> 412a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 422a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonnamespace llvm { 432a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonusing namespace sys; 442a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 452a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 462a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// This variable is useful for situations where the pthread library has been 472a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// compiled with weak linkage for its interface symbols. This allows the 482a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// threading support to be turned off by simply not linking against -lpthread. 492a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// In that situation, the value of pthread_mutex_init will be 0 and 502a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// consequently pthread_enabled will be false. In such situations, all the 512a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// pthread operations become no-ops and the functions all return false. If 522a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// pthread_rwlock_init does have an address, then rwlock support is enabled. 532a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// Note: all LLVM tools will link against -lpthread if its available since it 542a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// is configured into the LIBS variable. 552a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// Note: this line of code generates a warning if pthread_rwlock_init is not 562a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// declared with weak linkage. It's safe to ignore the warning. 572a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonstatic const bool pthread_enabled = true; 582a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 592a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// Construct a RWMutex using pthread calls 60b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::RWMutexImpl() 612a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson : data_(0) 622a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson{ 632a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson if (pthread_enabled) 642a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson { 652a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson // Declare the pthread_rwlock data structures 662a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_t* rwlock = 672a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t))); 68107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson 69107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson#ifdef __APPLE__ 70107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. 71107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson bzero(rwlock, sizeof(pthread_rwlock_t)); 72107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson#endif 73107a537db1261c09f8c9639ef7827b12f0812125Owen Anderson 742a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson // Initialize the rwlock 751cd9708f5cc13995a4e84ef498e4162a47f8b4f5Chandler Carruth int errorcode = pthread_rwlock_init(rwlock, NULL); 761cd9708f5cc13995a4e84ef498e4162a47f8b4f5Chandler Carruth (void)errorcode; 772a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson assert(errorcode == 0); 782a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 792a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson // Assign the data member 802a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson data_ = rwlock; 812a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson } 822a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 832a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 842a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson// Destruct a RWMutex 85b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::~RWMutexImpl() 862a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson{ 872a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson if (pthread_enabled) 882a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson { 892a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 902a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson assert(rwlock != 0); 912a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_destroy(rwlock); 922a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson free(rwlock); 932a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson } 942a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 952a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 962a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonbool 97b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::reader_acquire() 982a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson{ 992a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson if (pthread_enabled) 1002a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson { 1012a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 1022a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson assert(rwlock != 0); 1032a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1042a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson int errorcode = pthread_rwlock_rdlock(rwlock); 1052a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson return errorcode == 0; 106740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } else return false; 1072a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 1082a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1092a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonbool 110b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::reader_release() 1112a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson{ 1122a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson if (pthread_enabled) 1132a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson { 1142a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 1152a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson assert(rwlock != 0); 1162a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1172a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson int errorcode = pthread_rwlock_unlock(rwlock); 1182a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson return errorcode == 0; 119740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } else return false; 1202a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 1212a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1222a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonbool 123b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::writer_acquire() 1242a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson{ 1252a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson if (pthread_enabled) 1262a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson { 1272a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 1282a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson assert(rwlock != 0); 1292a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1302a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson int errorcode = pthread_rwlock_wrlock(rwlock); 1312a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson return errorcode == 0; 132740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } else return false; 1332a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 1342a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1352a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Andersonbool 136b65e9ed10677fe8944822c450b14d7e321f6e6f5Owen AndersonRWMutexImpl::writer_release() 1372a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson{ 1382a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson if (pthread_enabled) 1392a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson { 1402a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); 1412a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson assert(rwlock != 0); 1422a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1432a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson int errorcode = pthread_rwlock_unlock(rwlock); 1442a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson return errorcode == 0; 145740eb5323e449ae4b00a3f657bffaceadcbe2624Duncan Sands } else return false; 1462a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 1472a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1482a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson} 1492a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson 1502a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#elif defined(LLVM_ON_UNIX) 1512a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#include "Unix/RWMutex.inc" 1522a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#elif defined( LLVM_ON_WIN32) 1531f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "Windows/RWMutex.inc" 1542a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#else 1552c607b665dbeb52e2ade86f0e1f191695290da3bDaniel Dunbar#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in Support/Mutex.cpp 1562a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#endif 1572a8cf9aadd39e507e6e09c25530a2f01ca27fe57Owen Anderson#endif 158