]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 | ||
9f95a23c TL |
6 | #include <utility> |
7 | #include "common/containers.h" | |
8 | ||
11fdf7f2 TL |
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 | ||
9f95a23c | 17 | #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN) |
11fdf7f2 TL |
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() {} | |
9f95a23c TL |
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() {} | |
11fdf7f2 TL |
34 | }; |
35 | ||
36 | using mutex = dummy_mutex; | |
37 | using recursive_mutex = dummy_mutex; | |
9f95a23c | 38 | using shared_mutex = dummy_shared_mutex; |
11fdf7f2 TL |
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 | ||
9f95a23c TL |
52 | template <typename ...Args> |
53 | shared_mutex make_shared_mutex(Args&& ...args) { | |
54 | return {}; | |
55 | } | |
56 | ||
11fdf7f2 TL |
57 | #define ceph_mutex_is_locked(m) true |
58 | #define ceph_mutex_is_locked_by_me(m) true | |
59 | } | |
60 | ||
9f95a23c | 61 | #else // defined (WITH_SEASTAR) && !defined(WITH_ALIEN) |
11fdf7f2 TL |
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 | // ============================================================================ | |
2a845540 TL |
72 | // |
73 | // Note: this is known to cause deadlocks on Windows because | |
74 | // of the winpthreads shared mutex implementation. | |
11fdf7f2 TL |
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()) | |
9f95a23c TL |
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()) | |
11fdf7f2 | 109 | #define ceph_mutex_is_locked_by_me(m) ((m).is_locked_by_me()) |
9f95a23c | 110 | #define ceph_mutex_is_not_locked_by_me(m) (!(m).is_locked_by_me()) |
11fdf7f2 TL |
111 | } |
112 | ||
113 | #else | |
114 | ||
115 | // ============================================================================ | |
116 | // release (fast and minimal) | |
117 | // ============================================================================ | |
118 | ||
119 | #include <condition_variable> | |
120 | #include <mutex> | |
11fdf7f2 | 121 | |
2a845540 TL |
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 | |
11fdf7f2 TL |
130 | |
131 | namespace ceph { | |
132 | ||
133 | typedef std::mutex mutex; | |
134 | typedef std::recursive_mutex recursive_mutex; | |
135 | typedef std::condition_variable condition_variable; | |
2a845540 TL |
136 | |
137 | #if __MINGW32__ | |
138 | typedef boost::shared_mutex shared_mutex; | |
139 | #else | |
11fdf7f2 | 140 | typedef std::shared_mutex shared_mutex; |
2a845540 | 141 | #endif |
11fdf7f2 TL |
142 | |
143 | // discard arguments to make_mutex (they are for debugging only) | |
144 | template <typename ...Args> | |
2a845540 | 145 | mutex make_mutex(Args&& ...args) { |
11fdf7f2 TL |
146 | return {}; |
147 | } | |
148 | template <typename ...Args> | |
2a845540 | 149 | recursive_mutex make_recursive_mutex(Args&& ...args) { |
11fdf7f2 TL |
150 | return {}; |
151 | } | |
152 | template <typename ...Args> | |
2a845540 | 153 | shared_mutex make_shared_mutex(Args&& ...args) { |
11fdf7f2 TL |
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 | |
9f95a23c TL |
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 | |
11fdf7f2 | 164 | #define ceph_mutex_is_locked_by_me(m) true |
9f95a23c TL |
165 | #define ceph_mutex_is_not_locked_by_me(m) true |
166 | ||
11fdf7f2 TL |
167 | } |
168 | ||
169 | #endif // CEPH_DEBUG_MUTEX | |
170 | ||
171 | #endif // WITH_SEASTAR | |
9f95a23c TL |
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 |