xref: /freebsd/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the llvm::sys::RWMutex class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
140b57cec5SDimitry Andric #include "llvm/Support/RWMutex.h"
150b57cec5SDimitry Andric #include "llvm/Config/config.h"
160b57cec5SDimitry Andric 
178bcb0991SDimitry Andric #if defined(LLVM_USE_RW_MUTEX_IMPL)
188bcb0991SDimitry Andric using namespace llvm;
198bcb0991SDimitry Andric using namespace sys;
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric #if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
220b57cec5SDimitry Andric // Define all methods as no-ops if threading is explicitly disabled
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric RWMutexImpl::RWMutexImpl() = default;
250b57cec5SDimitry Andric RWMutexImpl::~RWMutexImpl() = default;
260b57cec5SDimitry Andric 
lock_shared()278bcb0991SDimitry Andric bool RWMutexImpl::lock_shared() { return true; }
unlock_shared()288bcb0991SDimitry Andric bool RWMutexImpl::unlock_shared() { return true; }
try_lock_shared()29*0fca6ea1SDimitry Andric bool RWMutexImpl::try_lock_shared() { return true; }
lock()308bcb0991SDimitry Andric bool RWMutexImpl::lock() { return true; }
unlock()318bcb0991SDimitry Andric bool RWMutexImpl::unlock() { return true; }
try_lock()32*0fca6ea1SDimitry Andric bool RWMutexImpl::try_lock() { return true; }
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #else
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #include <cassert>
390b57cec5SDimitry Andric #include <cstdlib>
400b57cec5SDimitry Andric #include <pthread.h>
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric // Construct a RWMutex using pthread calls
RWMutexImpl()430b57cec5SDimitry Andric RWMutexImpl::RWMutexImpl()
440b57cec5SDimitry Andric {
450b57cec5SDimitry Andric   // Declare the pthread_rwlock data structures
460b57cec5SDimitry Andric   pthread_rwlock_t* rwlock =
470b57cec5SDimitry Andric     static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric #ifdef __APPLE__
500b57cec5SDimitry Andric   // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
510b57cec5SDimitry Andric   bzero(rwlock, sizeof(pthread_rwlock_t));
520b57cec5SDimitry Andric #endif
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   // Initialize the rwlock
550b57cec5SDimitry Andric   int errorcode = pthread_rwlock_init(rwlock, nullptr);
560b57cec5SDimitry Andric   (void)errorcode;
570b57cec5SDimitry Andric   assert(errorcode == 0);
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   // Assign the data member
600b57cec5SDimitry Andric   data_ = rwlock;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric // Destruct a RWMutex
~RWMutexImpl()640b57cec5SDimitry Andric RWMutexImpl::~RWMutexImpl()
650b57cec5SDimitry Andric {
660b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
670b57cec5SDimitry Andric   assert(rwlock != nullptr);
680b57cec5SDimitry Andric   pthread_rwlock_destroy(rwlock);
690b57cec5SDimitry Andric   free(rwlock);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric bool
lock_shared()738bcb0991SDimitry Andric RWMutexImpl::lock_shared()
740b57cec5SDimitry Andric {
750b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
760b57cec5SDimitry Andric   assert(rwlock != nullptr);
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   int errorcode = pthread_rwlock_rdlock(rwlock);
790b57cec5SDimitry Andric   return errorcode == 0;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric bool
unlock_shared()838bcb0991SDimitry Andric RWMutexImpl::unlock_shared()
840b57cec5SDimitry Andric {
850b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
860b57cec5SDimitry Andric   assert(rwlock != nullptr);
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   int errorcode = pthread_rwlock_unlock(rwlock);
890b57cec5SDimitry Andric   return errorcode == 0;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
try_lock_shared()92*0fca6ea1SDimitry Andric bool RWMutexImpl::try_lock_shared() {
93*0fca6ea1SDimitry Andric   pthread_rwlock_t *rwlock = static_cast<pthread_rwlock_t *>(data_);
94*0fca6ea1SDimitry Andric   assert(rwlock != nullptr);
95*0fca6ea1SDimitry Andric 
96*0fca6ea1SDimitry Andric   int errorcode = pthread_rwlock_tryrdlock(rwlock);
97*0fca6ea1SDimitry Andric   return errorcode == 0;
98*0fca6ea1SDimitry Andric }
99*0fca6ea1SDimitry Andric 
1000b57cec5SDimitry Andric bool
lock()1018bcb0991SDimitry Andric RWMutexImpl::lock()
1020b57cec5SDimitry Andric {
1030b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
1040b57cec5SDimitry Andric   assert(rwlock != nullptr);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   int errorcode = pthread_rwlock_wrlock(rwlock);
1070b57cec5SDimitry Andric   return errorcode == 0;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric bool
unlock()1118bcb0991SDimitry Andric RWMutexImpl::unlock()
1120b57cec5SDimitry Andric {
1130b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
1140b57cec5SDimitry Andric   assert(rwlock != nullptr);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   int errorcode = pthread_rwlock_unlock(rwlock);
1170b57cec5SDimitry Andric   return errorcode == 0;
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
try_lock()120*0fca6ea1SDimitry Andric bool RWMutexImpl::try_lock() {
121*0fca6ea1SDimitry Andric   pthread_rwlock_t *rwlock = static_cast<pthread_rwlock_t *>(data_);
122*0fca6ea1SDimitry Andric   assert(rwlock != nullptr);
123*0fca6ea1SDimitry Andric 
124*0fca6ea1SDimitry Andric   int errorcode = pthread_rwlock_trywrlock(rwlock);
125*0fca6ea1SDimitry Andric   return errorcode == 0;
126*0fca6ea1SDimitry Andric }
127*0fca6ea1SDimitry Andric 
1280b57cec5SDimitry Andric #else
1298bcb0991SDimitry Andric 
RWMutexImpl()1308bcb0991SDimitry Andric RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
1318bcb0991SDimitry Andric 
~RWMutexImpl()1328bcb0991SDimitry Andric RWMutexImpl::~RWMutexImpl() {
1338bcb0991SDimitry Andric   delete static_cast<MutexImpl *>(data_);
1348bcb0991SDimitry Andric }
1358bcb0991SDimitry Andric 
lock_shared()1368bcb0991SDimitry Andric bool RWMutexImpl::lock_shared() {
1378bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->acquire();
1388bcb0991SDimitry Andric }
1398bcb0991SDimitry Andric 
unlock_shared()1408bcb0991SDimitry Andric bool RWMutexImpl::unlock_shared() {
1418bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->release();
1428bcb0991SDimitry Andric }
1438bcb0991SDimitry Andric 
try_lock_shared()144*0fca6ea1SDimitry Andric bool RWMutexImpl::try_lock_shared() {
145*0fca6ea1SDimitry Andric   return static_cast<MutexImpl *>(data_)->tryacquire();
146*0fca6ea1SDimitry Andric }
147*0fca6ea1SDimitry Andric 
lock()1488bcb0991SDimitry Andric bool RWMutexImpl::lock() {
1498bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->acquire();
1508bcb0991SDimitry Andric }
1518bcb0991SDimitry Andric 
unlock()1528bcb0991SDimitry Andric bool RWMutexImpl::unlock() {
1538bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->release();
1548bcb0991SDimitry Andric }
1558bcb0991SDimitry Andric 
try_lock()156*0fca6ea1SDimitry Andric bool RWMutexImpl::try_lock() {
157*0fca6ea1SDimitry Andric   return static_cast<MutexImpl *>(data_)->tryacquire();
158*0fca6ea1SDimitry Andric }
159*0fca6ea1SDimitry Andric 
1608bcb0991SDimitry Andric #endif
1610b57cec5SDimitry Andric #endif
1620b57cec5SDimitry Andric #endif
163