xref: /freebsd/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
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 
17*8bcb0991SDimitry Andric #if defined(LLVM_USE_RW_MUTEX_IMPL)
18*8bcb0991SDimitry Andric using namespace llvm;
19*8bcb0991SDimitry 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 
27*8bcb0991SDimitry Andric bool RWMutexImpl::lock_shared() { return true; }
28*8bcb0991SDimitry Andric bool RWMutexImpl::unlock_shared() { return true; }
29*8bcb0991SDimitry Andric bool RWMutexImpl::lock() { return true; }
30*8bcb0991SDimitry Andric bool RWMutexImpl::unlock() { return true; }
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric #else
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #include <cassert>
370b57cec5SDimitry Andric #include <cstdlib>
380b57cec5SDimitry Andric #include <pthread.h>
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric // Construct a RWMutex using pthread calls
410b57cec5SDimitry Andric RWMutexImpl::RWMutexImpl()
420b57cec5SDimitry Andric {
430b57cec5SDimitry Andric   // Declare the pthread_rwlock data structures
440b57cec5SDimitry Andric   pthread_rwlock_t* rwlock =
450b57cec5SDimitry Andric     static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric #ifdef __APPLE__
480b57cec5SDimitry Andric   // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
490b57cec5SDimitry Andric   bzero(rwlock, sizeof(pthread_rwlock_t));
500b57cec5SDimitry Andric #endif
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   // Initialize the rwlock
530b57cec5SDimitry Andric   int errorcode = pthread_rwlock_init(rwlock, nullptr);
540b57cec5SDimitry Andric   (void)errorcode;
550b57cec5SDimitry Andric   assert(errorcode == 0);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   // Assign the data member
580b57cec5SDimitry Andric   data_ = rwlock;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric // Destruct a RWMutex
620b57cec5SDimitry Andric RWMutexImpl::~RWMutexImpl()
630b57cec5SDimitry Andric {
640b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
650b57cec5SDimitry Andric   assert(rwlock != nullptr);
660b57cec5SDimitry Andric   pthread_rwlock_destroy(rwlock);
670b57cec5SDimitry Andric   free(rwlock);
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric bool
71*8bcb0991SDimitry Andric RWMutexImpl::lock_shared()
720b57cec5SDimitry Andric {
730b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
740b57cec5SDimitry Andric   assert(rwlock != nullptr);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   int errorcode = pthread_rwlock_rdlock(rwlock);
770b57cec5SDimitry Andric   return errorcode == 0;
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric bool
81*8bcb0991SDimitry Andric RWMutexImpl::unlock_shared()
820b57cec5SDimitry Andric {
830b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
840b57cec5SDimitry Andric   assert(rwlock != nullptr);
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   int errorcode = pthread_rwlock_unlock(rwlock);
870b57cec5SDimitry Andric   return errorcode == 0;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric bool
91*8bcb0991SDimitry Andric RWMutexImpl::lock()
920b57cec5SDimitry Andric {
930b57cec5SDimitry Andric   pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
940b57cec5SDimitry Andric   assert(rwlock != nullptr);
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   int errorcode = pthread_rwlock_wrlock(rwlock);
970b57cec5SDimitry Andric   return errorcode == 0;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric bool
101*8bcb0991SDimitry Andric RWMutexImpl::unlock()
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_unlock(rwlock);
1070b57cec5SDimitry Andric   return errorcode == 0;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric #else
111*8bcb0991SDimitry Andric 
112*8bcb0991SDimitry Andric RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
113*8bcb0991SDimitry Andric 
114*8bcb0991SDimitry Andric RWMutexImpl::~RWMutexImpl() {
115*8bcb0991SDimitry Andric   delete static_cast<MutexImpl *>(data_);
116*8bcb0991SDimitry Andric }
117*8bcb0991SDimitry Andric 
118*8bcb0991SDimitry Andric bool RWMutexImpl::lock_shared() {
119*8bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->acquire();
120*8bcb0991SDimitry Andric }
121*8bcb0991SDimitry Andric 
122*8bcb0991SDimitry Andric bool RWMutexImpl::unlock_shared() {
123*8bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->release();
124*8bcb0991SDimitry Andric }
125*8bcb0991SDimitry Andric 
126*8bcb0991SDimitry Andric bool RWMutexImpl::lock() {
127*8bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->acquire();
128*8bcb0991SDimitry Andric }
129*8bcb0991SDimitry Andric 
130*8bcb0991SDimitry Andric bool RWMutexImpl::unlock() {
131*8bcb0991SDimitry Andric   return static_cast<MutexImpl *>(data_)->release();
132*8bcb0991SDimitry Andric }
133*8bcb0991SDimitry Andric 
134*8bcb0991SDimitry Andric #endif
1350b57cec5SDimitry Andric #endif
1360b57cec5SDimitry Andric #endif
137