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) |
18 | using namespace llvm; |
19 | using 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 | |
24 | RWMutexImpl::RWMutexImpl() = default; |
25 | RWMutexImpl::~RWMutexImpl() = default; |
26 | |
27 | bool RWMutexImpl::lock_shared() { return true; } |
28 | bool RWMutexImpl::unlock_shared() { return true; } |
29 | bool RWMutexImpl::lock() { return true; } |
30 | bool RWMutexImpl::unlock() { return true; } |
31 | |
32 | #else |
33 | |
34 | #if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT) |
35 | |
36 | #include <cassert> |
37 | #include <cstdlib> |
38 | #include <pthread.h> |
39 | |
40 | // Construct a RWMutex using pthread calls |
41 | RWMutexImpl::RWMutexImpl() |
42 | { |
43 | // Declare the pthread_rwlock data structures |
44 | pthread_rwlock_t* rwlock = |
45 | static_cast<pthread_rwlock_t*>(safe_malloc(sizeof(pthread_rwlock_t))); |
46 | |
47 | #ifdef __APPLE__ |
48 | // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init. |
49 | bzero(rwlock, sizeof(pthread_rwlock_t)); |
50 | #endif |
51 | |
52 | // Initialize the rwlock |
53 | int errorcode = pthread_rwlock_init(rwlock, nullptr); |
54 | (void)errorcode; |
55 | assert(errorcode == 0); |
56 | |
57 | // Assign the data member |
58 | data_ = rwlock; |
59 | } |
60 | |
61 | // Destruct a RWMutex |
62 | RWMutexImpl::~RWMutexImpl() |
63 | { |
64 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
65 | assert(rwlock != nullptr); |
66 | pthread_rwlock_destroy(rwlock); |
67 | free(rwlock); |
68 | } |
69 | |
70 | bool |
71 | RWMutexImpl::lock_shared() |
72 | { |
73 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
74 | assert(rwlock != nullptr); |
75 | |
76 | int errorcode = pthread_rwlock_rdlock(rwlock); |
77 | return errorcode == 0; |
78 | } |
79 | |
80 | bool |
81 | RWMutexImpl::unlock_shared() |
82 | { |
83 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
84 | assert(rwlock != nullptr); |
85 | |
86 | int errorcode = pthread_rwlock_unlock(rwlock); |
87 | return errorcode == 0; |
88 | } |
89 | |
90 | bool |
91 | RWMutexImpl::lock() |
92 | { |
93 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
94 | assert(rwlock != nullptr); |
95 | |
96 | int errorcode = pthread_rwlock_wrlock(rwlock); |
97 | return errorcode == 0; |
98 | } |
99 | |
100 | bool |
101 | RWMutexImpl::unlock() |
102 | { |
103 | pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_); |
104 | assert(rwlock != nullptr); |
105 | |
106 | int errorcode = pthread_rwlock_unlock(rwlock); |
107 | return errorcode == 0; |
108 | } |
109 | |
110 | #else |
111 | |
112 | RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { } |
113 | |
114 | RWMutexImpl::~RWMutexImpl() { |
115 | delete static_cast<MutexImpl *>(data_); |
116 | } |
117 | |
118 | bool RWMutexImpl::lock_shared() { |
119 | return static_cast<MutexImpl *>(data_)->acquire(); |
120 | } |
121 | |
122 | bool RWMutexImpl::unlock_shared() { |
123 | return static_cast<MutexImpl *>(data_)->release(); |
124 | } |
125 | |
126 | bool RWMutexImpl::lock() { |
127 | return static_cast<MutexImpl *>(data_)->acquire(); |
128 | } |
129 | |
130 | bool RWMutexImpl::unlock() { |
131 | return static_cast<MutexImpl *>(data_)->release(); |
132 | } |
133 | |
134 | #endif |
135 | #endif |
136 | #endif |
137 | |