1 #include "shared_mutex_debug.h"
3 #include <system_error>
6 #include "common/valgrind.h"
10 shared_mutex_debug::shared_mutex_debug(std::string group
,
13 bool prioritize_write
)
14 : mutex_debugging_base
{std::move(group
),
16 false /* backtrace */},
19 #ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
20 if (prioritize_write
) {
21 pthread_rwlockattr_t attr
;
22 pthread_rwlockattr_init(&attr
);
23 // PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
24 // Setting the lock kind to this avoids writer starvation as long as
25 // long as any read locking is not done in a recursive fashion.
26 pthread_rwlockattr_setkind_np(&attr
,
27 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
);
28 pthread_rwlock_init(&rwlock
, &attr
);
29 pthread_rwlockattr_destroy(&attr
);
32 // Next block is in {} to possibly connect to the above if when code is used.
34 pthread_rwlock_init(&rwlock
, NULL
);
36 ANNOTATE_BENIGN_RACE_SIZED(&id
, sizeof(id
), "shared_mutex_debug lockdep id");
37 ANNOTATE_BENIGN_RACE_SIZED(&nlock
, sizeof(nlock
), "shared_mutex_debug nwlock");
38 ANNOTATE_BENIGN_RACE_SIZED(&nrlock
, sizeof(nrlock
), "shared_mutex_debug nrlock");
42 void shared_mutex_debug::lock()
44 if (_enable_lockdep()) {
47 if (int r
= pthread_rwlock_wrlock(&rwlock
); r
!= 0) {
48 throw std::system_error(r
, std::generic_category());
50 if (_enable_lockdep()) {
56 bool shared_mutex_debug::try_lock()
58 int r
= pthread_rwlock_trywrlock(&rwlock
);
61 if (_enable_lockdep()) {
69 throw std::system_error(r
, std::generic_category());
73 void shared_mutex_debug::unlock()
76 if (_enable_lockdep()) {
79 if (int r
= pthread_rwlock_unlock(&rwlock
); r
!= 0) {
80 throw std::system_error(r
, std::generic_category());
85 void shared_mutex_debug::lock_shared()
87 if (_enable_lockdep()) {
90 if (int r
= pthread_rwlock_rdlock(&rwlock
); r
!= 0) {
91 throw std::system_error(r
, std::generic_category());
93 if (_enable_lockdep()) {
99 bool shared_mutex_debug::try_lock_shared()
101 if (_enable_lockdep()) {
104 switch (int r
= pthread_rwlock_rdlock(&rwlock
); r
) {
106 if (_enable_lockdep()) {
114 throw std::system_error(r
, std::generic_category());
118 void shared_mutex_debug::unlock_shared()
120 _pre_unlock_shared();
121 if (_enable_lockdep()) {
124 if (int r
= pthread_rwlock_unlock(&rwlock
); r
!= 0) {
125 throw std::system_error(r
, std::generic_category());
130 void shared_mutex_debug::_pre_unlock()
133 ceph_assert(nlock
> 0);
135 ceph_assert(locked_by
== std::this_thread::get_id());
136 ceph_assert(nlock
== 0);
137 locked_by
= std::thread::id();
141 void shared_mutex_debug::_post_lock()
144 ceph_assert(nlock
== 0);
145 locked_by
= std::this_thread::get_id();
151 void shared_mutex_debug::_pre_unlock_shared()
154 ceph_assert(nrlock
> 0);
159 void shared_mutex_debug::_post_lock_shared()