1 #include "shared_mutex_debug.h"
3 #include <system_error>
6 #include "common/valgrind.h"
10 shared_mutex_debug::shared_mutex_debug(const std::string
& n
,
13 bool prioritize_write
)
14 : mutex_debugging_base
{n
, false /* backtrace */},
16 lockdep(enable_lock_dep
)
18 #ifdef HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP
19 if (prioritize_write
) {
20 pthread_rwlockattr_t attr
;
21 pthread_rwlockattr_init(&attr
);
22 // PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
23 // Setting the lock kind to this avoids writer starvation as long as
24 // long as any read locking is not done in a recursive fashion.
25 pthread_rwlockattr_setkind_np(&attr
,
26 PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
);
27 pthread_rwlock_init(&rwlock
, &attr
);
28 pthread_rwlockattr_destroy(&attr
);
31 // Next block is in {} to possibly connect to the above if when code is used.
33 pthread_rwlock_init(&rwlock
, NULL
);
35 ANNOTATE_BENIGN_RACE_SIZED(&id
, sizeof(id
), "shared_mutex_debug lockdep id");
36 ANNOTATE_BENIGN_RACE_SIZED(&nlock
, sizeof(nlock
), "shared_mutex_debug nwlock");
37 ANNOTATE_BENIGN_RACE_SIZED(&nrlock
, sizeof(nrlock
), "shared_mutex_debug nrlock");
41 void shared_mutex_debug::lock()
43 if (g_lockdep
&& lockdep
) {
46 if (int r
= pthread_rwlock_wrlock(&rwlock
); r
!= 0) {
47 throw std::system_error(r
, std::generic_category());
49 if (lockdep
&& g_lockdep
) {
55 bool shared_mutex_debug::try_lock()
57 int r
= pthread_rwlock_trywrlock(&rwlock
);
60 if (lockdep
&& g_lockdep
) {
68 throw std::system_error(r
, std::generic_category());
72 void shared_mutex_debug::unlock()
75 if (lockdep
&& g_lockdep
) {
78 if (int r
= pthread_rwlock_unlock(&rwlock
); r
!= 0) {
79 throw std::system_error(r
, std::generic_category());
84 void shared_mutex_debug::lock_shared()
86 if (lockdep
&& g_lockdep
) {
89 if (int r
= pthread_rwlock_rdlock(&rwlock
); r
!= 0) {
90 throw std::system_error(r
, std::generic_category());
92 if (lockdep
&& g_lockdep
) {
98 bool shared_mutex_debug::try_lock_shared()
100 if (lockdep
&& g_lockdep
) {
103 switch (int r
= pthread_rwlock_rdlock(&rwlock
); r
) {
105 if (lockdep
&& g_lockdep
) {
113 throw std::system_error(r
, std::generic_category());
117 void shared_mutex_debug::unlock_shared()
119 _pre_unlock_shared();
120 if (lockdep
&& g_lockdep
) {
123 if (int r
= pthread_rwlock_unlock(&rwlock
); r
!= 0) {
124 throw std::system_error(r
, std::generic_category());
129 void shared_mutex_debug::_pre_unlock()
132 ceph_assert(nlock
> 0);
134 ceph_assert(locked_by
== std::this_thread::get_id());
135 ceph_assert(nlock
== 0);
136 locked_by
= std::thread::id();
140 void shared_mutex_debug::_post_lock()
143 ceph_assert(nlock
== 0);
144 locked_by
= std::this_thread::get_id();
150 void shared_mutex_debug::_pre_unlock_shared()
153 ceph_assert(nrlock
> 0);
158 void shared_mutex_debug::_post_lock_shared()