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