xref: /freebsd/contrib/llvm-project/llvm/lib/Support/RWMutex.cpp (revision 06690044dac183ea1d93c2ae227e261da3bdca2a)
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::try_lock_shared() { return true; }
30  bool RWMutexImpl::lock() { return true; }
31  bool RWMutexImpl::unlock() { return true; }
32  bool 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
43  RWMutexImpl::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
64  RWMutexImpl::~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  
72  bool
73  RWMutexImpl::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  
82  bool
83  RWMutexImpl::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  
92  bool 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  
100  bool
101  RWMutexImpl::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  
110  bool
111  RWMutexImpl::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  
120  bool 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  
130  RWMutexImpl::RWMutexImpl() : data_(new MutexImpl(false)) { }
131  
132  RWMutexImpl::~RWMutexImpl() {
133    delete static_cast<MutexImpl *>(data_);
134  }
135  
136  bool RWMutexImpl::lock_shared() {
137    return static_cast<MutexImpl *>(data_)->acquire();
138  }
139  
140  bool RWMutexImpl::unlock_shared() {
141    return static_cast<MutexImpl *>(data_)->release();
142  }
143  
144  bool RWMutexImpl::try_lock_shared() {
145    return static_cast<MutexImpl *>(data_)->tryacquire();
146  }
147  
148  bool RWMutexImpl::lock() {
149    return static_cast<MutexImpl *>(data_)->acquire();
150  }
151  
152  bool RWMutexImpl::unlock() {
153    return static_cast<MutexImpl *>(data_)->release();
154  }
155  
156  bool RWMutexImpl::try_lock() {
157    return static_cast<MutexImpl *>(data_)->tryacquire();
158  }
159  
160  #endif
161  #endif
162  #endif
163