]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/shared_mutex_debug.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / common / shared_mutex_debug.cc
CommitLineData
11fdf7f2
TL
1#include "shared_mutex_debug.h"
2
3#include <system_error>
4
5#include "acconfig.h"
6#include "common/valgrind.h"
7
8namespace ceph {
9
9f95a23c 10shared_mutex_debug::shared_mutex_debug(std::string group,
11fdf7f2
TL
11 bool track_lock,
12 bool enable_lock_dep,
13 bool prioritize_write)
9f95a23c
TL
14 : mutex_debugging_base{std::move(group),
15 enable_lock_dep,
16 false /* backtrace */},
17 track(track_lock)
11fdf7f2
TL
18{
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);
30 } else
31#endif
32 // Next block is in {} to possibly connect to the above if when code is used.
33 {
34 pthread_rwlock_init(&rwlock, NULL);
35 }
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");
39}
40
41// exclusive
42void shared_mutex_debug::lock()
43{
9f95a23c 44 if (_enable_lockdep()) {
11fdf7f2
TL
45 _will_lock();
46 }
47 if (int r = pthread_rwlock_wrlock(&rwlock); r != 0) {
48 throw std::system_error(r, std::generic_category());
49 }
9f95a23c 50 if (_enable_lockdep()) {
11fdf7f2
TL
51 _locked();
52 }
53 _post_lock();
54}
55
56bool shared_mutex_debug::try_lock()
57{
58 int r = pthread_rwlock_trywrlock(&rwlock);
59 switch (r) {
60 case 0:
9f95a23c 61 if (_enable_lockdep()) {
11fdf7f2
TL
62 _locked();
63 }
64 _post_lock();
65 return true;
66 case EBUSY:
67 return false;
68 default:
69 throw std::system_error(r, std::generic_category());
70 }
71}
72
73void shared_mutex_debug::unlock()
74{
75 _pre_unlock();
9f95a23c 76 if (_enable_lockdep()) {
11fdf7f2
TL
77 _will_unlock();
78 }
79 if (int r = pthread_rwlock_unlock(&rwlock); r != 0) {
80 throw std::system_error(r, std::generic_category());
81 }
82}
83
84// shared locking
85void shared_mutex_debug::lock_shared()
86{
9f95a23c 87 if (_enable_lockdep()) {
11fdf7f2
TL
88 _will_lock();
89 }
90 if (int r = pthread_rwlock_rdlock(&rwlock); r != 0) {
91 throw std::system_error(r, std::generic_category());
92 }
9f95a23c 93 if (_enable_lockdep()) {
11fdf7f2
TL
94 _locked();
95 }
96 _post_lock_shared();
97}
98
99bool shared_mutex_debug::try_lock_shared()
100{
9f95a23c 101 if (_enable_lockdep()) {
11fdf7f2
TL
102 _will_unlock();
103 }
104 switch (int r = pthread_rwlock_rdlock(&rwlock); r) {
105 case 0:
9f95a23c 106 if (_enable_lockdep()) {
11fdf7f2
TL
107 _locked();
108 }
109 _post_lock_shared();
110 return true;
111 case EBUSY:
112 return false;
113 default:
114 throw std::system_error(r, std::generic_category());
115 }
116}
117
118void shared_mutex_debug::unlock_shared()
119{
120 _pre_unlock_shared();
9f95a23c 121 if (_enable_lockdep()) {
11fdf7f2
TL
122 _will_unlock();
123 }
124 if (int r = pthread_rwlock_unlock(&rwlock); r != 0) {
125 throw std::system_error(r, std::generic_category());
126 }
127}
128
129// exclusive locking
130void shared_mutex_debug::_pre_unlock()
131{
132 if (track) {
133 ceph_assert(nlock > 0);
134 --nlock;
135 ceph_assert(locked_by == std::this_thread::get_id());
136 ceph_assert(nlock == 0);
137 locked_by = std::thread::id();
138 }
139}
140
141void shared_mutex_debug::_post_lock()
142{
143 if (track) {
144 ceph_assert(nlock == 0);
145 locked_by = std::this_thread::get_id();
146 ++nlock;
147 }
148}
149
150// shared locking
151void shared_mutex_debug::_pre_unlock_shared()
152{
153 if (track) {
154 ceph_assert(nrlock > 0);
155 nrlock--;
156 }
157}
158
159void shared_mutex_debug::_post_lock_shared()
160{
161 if (track) {
162 ++nrlock;
163 }
164}
165
166} // namespace ceph