]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/ceph_mutex.h
import ceph quincy 17.2.4
[ceph.git] / ceph / src / common / ceph_mutex.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 #pragma once
5
6 #include <utility>
7 #include "common/containers.h"
8
9 // What and why
10 // ============
11 //
12 // For general code making use of mutexes, use these ceph:: types.
13 // The key requirement is that you make use of the ceph::make_mutex()
14 // and make_recursive_mutex() factory methods, which take a string
15 // naming the mutex for the purposes of the lockdep debug variant.
16
17 #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
18
19 namespace ceph {
20 // an empty class satisfying the mutex concept
21 struct dummy_mutex {
22 void lock() {}
23 bool try_lock() {
24 return true;
25 }
26 void unlock() {}
27 void lock_shared() {}
28 void unlock_shared() {}
29 };
30
31 struct dummy_shared_mutex : dummy_mutex {
32 void lock_shared() {}
33 void unlock_shared() {}
34 };
35
36 using mutex = dummy_mutex;
37 using recursive_mutex = dummy_mutex;
38 using shared_mutex = dummy_shared_mutex;
39 // in seastar, we should use a difference interface for enforcing the
40 // semantics of condition_variable
41
42 template <typename ...Args>
43 dummy_mutex make_mutex(Args&& ...args) {
44 return {};
45 }
46
47 template <typename ...Args>
48 recursive_mutex make_recursive_mutex(Args&& ...args) {
49 return {};
50 }
51
52 template <typename ...Args>
53 shared_mutex make_shared_mutex(Args&& ...args) {
54 return {};
55 }
56
57 #define ceph_mutex_is_locked(m) true
58 #define ceph_mutex_is_locked_by_me(m) true
59 }
60
61 #else // defined (WITH_SEASTAR) && !defined(WITH_ALIEN)
62 //
63 // For legacy Mutex users that passed recursive=true, use
64 // ceph::make_recursive_mutex. For legacy Mutex users that passed
65 // lockdep=false, use std::mutex directly.
66
67 #ifdef CEPH_DEBUG_MUTEX
68
69 // ============================================================================
70 // debug (lockdep-capable, various sanity checks and asserts)
71 // ============================================================================
72 //
73 // Note: this is known to cause deadlocks on Windows because
74 // of the winpthreads shared mutex implementation.
75
76 #include "common/condition_variable_debug.h"
77 #include "common/mutex_debug.h"
78 #include "common/shared_mutex_debug.h"
79
80 namespace ceph {
81 typedef ceph::mutex_debug mutex;
82 typedef ceph::mutex_recursive_debug recursive_mutex;
83 typedef ceph::condition_variable_debug condition_variable;
84 typedef ceph::shared_mutex_debug shared_mutex;
85
86 // pass arguments to mutex_debug ctor
87 template <typename ...Args>
88 mutex make_mutex(Args&& ...args) {
89 return {std::forward<Args>(args)...};
90 }
91
92 // pass arguments to recursive_mutex_debug ctor
93 template <typename ...Args>
94 recursive_mutex make_recursive_mutex(Args&& ...args) {
95 return {std::forward<Args>(args)...};
96 }
97
98 // pass arguments to shared_mutex_debug ctor
99 template <typename ...Args>
100 shared_mutex make_shared_mutex(Args&& ...args) {
101 return {std::forward<Args>(args)...};
102 }
103
104 // debug methods
105 #define ceph_mutex_is_locked(m) ((m).is_locked())
106 #define ceph_mutex_is_not_locked(m) (!(m).is_locked())
107 #define ceph_mutex_is_rlocked(m) ((m).is_rlocked())
108 #define ceph_mutex_is_wlocked(m) ((m).is_wlocked())
109 #define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me())
110 #define ceph_mutex_is_not_locked_by_me(m) (!(m).is_locked_by_me())
111 }
112
113 #else
114
115 // ============================================================================
116 // release (fast and minimal)
117 // ============================================================================
118
119 #include <condition_variable>
120 #include <mutex>
121
122 // The winpthreads shared mutex implementation is broken.
123 // We'll use boost::shared_mutex instead.
124 // https://github.com/msys2/MINGW-packages/issues/3319
125 #if __MINGW32__
126 #include <boost/thread/shared_mutex.hpp>
127 #else
128 #include <shared_mutex>
129 #endif
130
131 namespace ceph {
132
133 typedef std::mutex mutex;
134 typedef std::recursive_mutex recursive_mutex;
135 typedef std::condition_variable condition_variable;
136
137 #if __MINGW32__
138 typedef boost::shared_mutex shared_mutex;
139 #else
140 typedef std::shared_mutex shared_mutex;
141 #endif
142
143 // discard arguments to make_mutex (they are for debugging only)
144 template <typename ...Args>
145 mutex make_mutex(Args&& ...args) {
146 return {};
147 }
148 template <typename ...Args>
149 recursive_mutex make_recursive_mutex(Args&& ...args) {
150 return {};
151 }
152 template <typename ...Args>
153 shared_mutex make_shared_mutex(Args&& ...args) {
154 return {};
155 }
156
157 // debug methods. Note that these can blindly return true
158 // because any code that does anything other than assert these
159 // are true is broken.
160 #define ceph_mutex_is_locked(m) true
161 #define ceph_mutex_is_not_locked(m) true
162 #define ceph_mutex_is_rlocked(m) true
163 #define ceph_mutex_is_wlocked(m) true
164 #define ceph_mutex_is_locked_by_me(m) true
165 #define ceph_mutex_is_not_locked_by_me(m) true
166
167 }
168
169 #endif // CEPH_DEBUG_MUTEX
170
171 #endif // WITH_SEASTAR
172
173 namespace ceph {
174
175 template <class LockT,
176 class LockFactoryT>
177 ceph::containers::tiny_vector<LockT> make_lock_container(
178 const std::size_t num_instances,
179 LockFactoryT&& lock_factory)
180 {
181 return {
182 num_instances, [&](const std::size_t i, auto emplacer) {
183 // this will be called `num_instances` times
184 new (emplacer.data()) LockT {lock_factory(i)};
185 }
186 };
187 }
188 } // namespace ceph
189