16d6babf7SJonas Devlieghere //===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
26d6babf7SJonas Devlieghere //
36d6babf7SJonas Devlieghere // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46d6babf7SJonas Devlieghere // See https://llvm.org/LICENSE.txt for license information.
56d6babf7SJonas Devlieghere // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66d6babf7SJonas Devlieghere //
76d6babf7SJonas Devlieghere //===----------------------------------------------------------------------===//
86d6babf7SJonas Devlieghere //
96d6babf7SJonas Devlieghere // This file implements the llvm::sys::RWMutex class.
106d6babf7SJonas Devlieghere //
116d6babf7SJonas Devlieghere //===----------------------------------------------------------------------===//
126d6babf7SJonas Devlieghere 
136d6babf7SJonas Devlieghere #include "llvm/Support/Allocator.h"
146d6babf7SJonas Devlieghere #include "llvm/Support/RWMutex.h"
156d6babf7SJonas Devlieghere #include "llvm/Config/config.h"
166d6babf7SJonas Devlieghere 
17*f4bdbea0SJonas Devlieghere #if defined(LLVM_USE_RW_MUTEX_IMPL)
186d6babf7SJonas Devlieghere using namespace llvm;
196d6babf7SJonas Devlieghere using namespace sys;
206d6babf7SJonas Devlieghere 
216d6babf7SJonas Devlieghere #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
226d6babf7SJonas Devlieghere // Define all methods as no-ops if threading is explicitly disabled
236d6babf7SJonas Devlieghere 
246d6babf7SJonas Devlieghere RWMutexImpl::RWMutexImpl() = default;
256d6babf7SJonas Devlieghere RWMutexImpl::~RWMutexImpl() = default;
266d6babf7SJonas Devlieghere 
lock_shared()276d6babf7SJonas Devlieghere bool RWMutexImpl::lock_shared() { return true; }
unlock_shared()286d6babf7SJonas Devlieghere bool RWMutexImpl::unlock_shared() { return true; }
lock()296d6babf7SJonas Devlieghere bool RWMutexImpl::lock() { return true; }
unlock()306d6babf7SJonas Devlieghere bool RWMutexImpl::unlock() { return true; }
316d6babf7SJonas Devlieghere 
326d6babf7SJonas Devlieghere #else
336d6babf7SJonas Devlieghere 
346d6babf7SJonas Devlieghere #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
356d6babf7SJonas Devlieghere 
366d6babf7SJonas Devlieghere #include <cassert>
376d6babf7SJonas Devlieghere #include <cstdlib>
386d6babf7SJonas Devlieghere #include <pthread.h>
396d6babf7SJonas Devlieghere 
406d6babf7SJonas Devlieghere // Construct a RWMutex using pthread calls
RWMutexImpl()416d6babf7SJonas Devlieghere RWMutexImpl::RWMutexImpl()
426d6babf7SJonas Devlieghere {
436d6babf7SJonas Devlieghere   // Declare the pthread_rwlock data structures
446d6babf7SJonas Devlieghere   pthread_rwlock_t* rwlock =
456d6babf7SJonas Devlieghere     static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
466d6babf7SJonas Devlieghere 
476d6babf7SJonas Devlieghere #ifdef __APPLE__
486d6babf7SJonas Devlieghere   // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
496d6babf7SJonas Devlieghere   bzero(rwlock, sizeof(pthread_rwlock_t));
506d6babf7SJonas Devlieghere #endif
516d6babf7SJonas Devlieghere 
526d6babf7SJonas Devlieghere   // Initialize the rwlock
536d6babf7SJonas Devlieghere   int errorcode = pthread_rwlock_init(rwlock, nullptr);
546d6babf7SJonas Devlieghere   (void)errorcode;
556d6babf7SJonas Devlieghere   assert(errorcode == 0);
566d6babf7SJonas Devlieghere 
576d6babf7SJonas Devlieghere   // Assign the data member
586d6babf7SJonas Devlieghere   data_ = rwlock;
596d6babf7SJonas Devlieghere }
606d6babf7SJonas Devlieghere 
616d6babf7SJonas Devlieghere // Destruct a RWMutex
~RWMutexImpl()626d6babf7SJonas Devlieghere RWMutexImpl::~RWMutexImpl()
636d6babf7SJonas Devlieghere {
646d6babf7SJonas Devlieghere   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
656d6babf7SJonas Devlieghere   assert(rwlock != nullptr);
666d6babf7SJonas Devlieghere   pthread_rwlock_destroy(rwlock);
676d6babf7SJonas Devlieghere   free(rwlock);
686d6babf7SJonas Devlieghere }
696d6babf7SJonas Devlieghere 
706d6babf7SJonas Devlieghere bool
lock_shared()716d6babf7SJonas Devlieghere RWMutexImpl::lock_shared()
726d6babf7SJonas Devlieghere {
736d6babf7SJonas Devlieghere   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
746d6babf7SJonas Devlieghere   assert(rwlock != nullptr);
756d6babf7SJonas Devlieghere 
766d6babf7SJonas Devlieghere   int errorcode = pthread_rwlock_rdlock(rwlock);
776d6babf7SJonas Devlieghere   return errorcode == 0;
786d6babf7SJonas Devlieghere }
796d6babf7SJonas Devlieghere 
806d6babf7SJonas Devlieghere bool
unlock_shared()816d6babf7SJonas Devlieghere RWMutexImpl::unlock_shared()
826d6babf7SJonas Devlieghere {
836d6babf7SJonas Devlieghere   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
846d6babf7SJonas Devlieghere   assert(rwlock != nullptr);
856d6babf7SJonas Devlieghere 
866d6babf7SJonas Devlieghere   int errorcode = pthread_rwlock_unlock(rwlock);
876d6babf7SJonas Devlieghere   return errorcode == 0;
886d6babf7SJonas Devlieghere }
896d6babf7SJonas Devlieghere 
906d6babf7SJonas Devlieghere bool
lock()916d6babf7SJonas Devlieghere RWMutexImpl::lock()
926d6babf7SJonas Devlieghere {
936d6babf7SJonas Devlieghere   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
946d6babf7SJonas Devlieghere   assert(rwlock != nullptr);
956d6babf7SJonas Devlieghere 
966d6babf7SJonas Devlieghere   int errorcode = pthread_rwlock_wrlock(rwlock);
976d6babf7SJonas Devlieghere   return errorcode == 0;
986d6babf7SJonas Devlieghere }
996d6babf7SJonas Devlieghere 
1006d6babf7SJonas Devlieghere bool
unlock()1016d6babf7SJonas Devlieghere RWMutexImpl::unlock()
1026d6babf7SJonas Devlieghere {
1036d6babf7SJonas Devlieghere   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
1046d6babf7SJonas Devlieghere   assert(rwlock != nullptr);
1056d6babf7SJonas Devlieghere 
1066d6babf7SJonas Devlieghere   int errorcode = pthread_rwlock_unlock(rwlock);
1076d6babf7SJonas Devlieghere   return errorcode == 0;
1086d6babf7SJonas Devlieghere }
1096d6babf7SJonas Devlieghere 
1106d6babf7SJonas Devlieghere #else
1116d6babf7SJonas Devlieghere 
RWMutexImpl()1126d6babf7SJonas Devlieghere RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
1136d6babf7SJonas Devlieghere 
~RWMutexImpl()1146d6babf7SJonas Devlieghere RWMutexImpl::~RWMutexImpl() {
1156d6babf7SJonas Devlieghere   delete static_cast<MutexImpl *>(data_);
1166d6babf7SJonas Devlieghere }
1176d6babf7SJonas Devlieghere 
lock_shared()1186d6babf7SJonas Devlieghere bool RWMutexImpl::lock_shared() {
1196d6babf7SJonas Devlieghere   return static_cast<MutexImpl *>(data_)->acquire();
1206d6babf7SJonas Devlieghere }
1216d6babf7SJonas Devlieghere 
unlock_shared()1226d6babf7SJonas Devlieghere bool RWMutexImpl::unlock_shared() {
1236d6babf7SJonas Devlieghere   return static_cast<MutexImpl *>(data_)->release();
1246d6babf7SJonas Devlieghere }
1256d6babf7SJonas Devlieghere 
lock()1266d6babf7SJonas Devlieghere bool RWMutexImpl::lock() {
1276d6babf7SJonas Devlieghere   return static_cast<MutexImpl *>(data_)->acquire();
1286d6babf7SJonas Devlieghere }
1296d6babf7SJonas Devlieghere 
unlock()1306d6babf7SJonas Devlieghere bool RWMutexImpl::unlock() {
1316d6babf7SJonas Devlieghere   return static_cast<MutexImpl *>(data_)->release();
1326d6babf7SJonas Devlieghere }
1336d6babf7SJonas Devlieghere 
1346d6babf7SJonas Devlieghere #endif
1356d6babf7SJonas Devlieghere #endif
1366d6babf7SJonas Devlieghere #endif
137