1//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the llvm::sys::RWMutex class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/Support/Allocator.h"
14#include "llvm/Support/RWMutex.h"
15#include "llvm/Config/config.h"
16
17#if defined(LLVM_USE_RW_MUTEX_IMPL)
18using namespace llvm;
19using namespace sys;
20
21#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
22// Define all methods as no-ops if threading is explicitly disabled
23
24RWMutexImpl::RWMutexImpl() = default;
25RWMutexImpl::~RWMutexImpl() = default;
26
27bool RWMutexImpl::lock_shared() { return true; }
28bool RWMutexImpl::unlock_shared() { return true; }
29bool RWMutexImpl::try_lock_shared() { return true; }
30bool RWMutexImpl::lock() { return true; }
31bool RWMutexImpl::unlock() { return true; }
32bool RWMutexImpl::try_lock() { return true; }
33
34#else
35
36#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
37
38#include <cassert>
39#include <cstdlib>
40#include <pthread.h>
41
42// Construct a RWMutex using pthread calls
43RWMutexImpl::RWMutexImpl()
44{
45 // Declare the pthread_rwlock data structures
46 pthread_rwlock_t* rwlock =
47 static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t)));
48
49#ifdef __APPLE__
50 // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
51 bzero(rwlock, sizeof(pthread_rwlock_t));
52#endif
53
54 // Initialize the rwlock
55 int errorcode = pthread_rwlock_init(rwlock, nullptr);
56 (void)errorcode;
57 assert(errorcode == 0);
58
59 // Assign the data member
60 data_ = rwlock;
61}
62
63// Destruct a RWMutex
64RWMutexImpl::~RWMutexImpl()
65{
66 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
67 assert(rwlock != nullptr);
68 pthread_rwlock_destroy(rwlock);
69 free(rwlock);
70}
71
72bool
73RWMutexImpl::lock_shared()
74{
75 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
76 assert(rwlock != nullptr);
77
78 int errorcode = pthread_rwlock_rdlock(rwlock);
79 return errorcode == 0;
80}
81
82bool
83RWMutexImpl::unlock_shared()
84{
85 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
86 assert(rwlock != nullptr);
87
88 int errorcode = pthread_rwlock_unlock(rwlock);
89 return errorcode == 0;
90}
91
92bool RWMutexImpl::try_lock_shared() {
93 pthread_rwlock_t *rwlock = static_cast<pthread_rwlock_t *>(data_);
94 assert(rwlock != nullptr);
95
96 int errorcode = pthread_rwlock_tryrdlock(rwlock);
97 return errorcode == 0;
98}
99
100bool
101RWMutexImpl::lock()
102{
103 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
104 assert(rwlock != nullptr);
105
106 int errorcode = pthread_rwlock_wrlock(rwlock);
107 return errorcode == 0;
108}
109
110bool
111RWMutexImpl::unlock()
112{
113 pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
114 assert(rwlock != nullptr);
115
116 int errorcode = pthread_rwlock_unlock(rwlock);
117 return errorcode == 0;
118}
119
120bool RWMutexImpl::try_lock() {
121 pthread_rwlock_t *rwlock = static_cast<pthread_rwlock_t *>(data_);
122 assert(rwlock != nullptr);
123
124 int errorcode = pthread_rwlock_trywrlock(rwlock);
125 return errorcode == 0;
126}
127
128#else
129
130RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
131
132RWMutexImpl::~RWMutexImpl() {
133 delete static_cast<MutexImpl *>(data_);
134}
135
136bool RWMutexImpl::lock_shared() {
137 return static_cast<MutexImpl *>(data_)->acquire();
138}
139
140bool RWMutexImpl::unlock_shared() {
141 return static_cast<MutexImpl *>(data_)->release();
142}
143
144bool RWMutexImpl::try_lock_shared() {
145 return static_cast<MutexImpl *>(data_)->tryacquire();
146}
147
148bool RWMutexImpl::lock() {
149 return static_cast<MutexImpl *>(data_)->acquire();
150}
151
152bool RWMutexImpl::unlock() {
153 return static_cast<MutexImpl *>(data_)->release();
154}
155
156bool RWMutexImpl::try_lock() {
157 return static_cast<MutexImpl *>(data_)->tryacquire();
158}
159
160#endif
161#endif
162#endif
163