]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/container/detail/mutex.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / container / detail / mutex.hpp
CommitLineData
7c673cae
FG
1//////////////////////////////////////////////////////////////////////////////
2//
b32b8144
FG
3// (C) Copyright Stephen Cleary 2000
4// (C) Copyright Ion Gaztanaga 2015-2017.
5//
6// Distributed under the Boost
7c673cae
FG
7// Software License, Version 1.0. (See accompanying file
8// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10// See http://www.boost.org/libs/container for documentation.
11//
12//////////////////////////////////////////////////////////////////////////////
13
14#ifndef BOOST_CONTAINER_MUTEX_HPP
15#define BOOST_CONTAINER_MUTEX_HPP
16
17#ifndef BOOST_CONFIG_HPP
18# include <boost/config.hpp>
19#endif
20
21#if defined(BOOST_HAS_PRAGMA_ONCE)
22# pragma once
23#endif
24
25//#define BOOST_CONTAINER_NO_MT
26//#define BOOST_CONTAINER_NO_SPINLOCKS
27
28#include <boost/container/detail/config_begin.hpp>
29#include <boost/container/detail/workaround.hpp>
30
31// Extremely Light-Weight wrapper classes for OS thread synchronization
32
33#define BOOST_MUTEX_HELPER_NONE 0
34#define BOOST_MUTEX_HELPER_WIN32 1
35#define BOOST_MUTEX_HELPER_PTHREAD 2
36#define BOOST_MUTEX_HELPER_SPINLOCKS 3
37
38#if !defined(BOOST_HAS_THREADS) && !defined(BOOST_NO_MT)
39# define BOOST_NO_MT
40#endif
41
42#if defined(BOOST_NO_MT) || defined(BOOST_CONTAINER_NO_MT)
43 // No multithreading -> make locks into no-ops
44 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_NONE
45#else
46 //Taken from dlmalloc
47 #if !defined(BOOST_CONTAINER_NO_SPINLOCKS) && \
48 ((defined(__GNUC__) && \
49 ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) || \
50 defined(__i386__) || defined(__x86_64__))) || \
51 (defined(_MSC_VER) && _MSC_VER>=1310))
52 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_SPINLOCKS
53 #endif
54
55 #if defined(BOOST_WINDOWS)
1e59de90
TL
56 #include <boost/winapi/critical_section.hpp>
57 #include <boost/winapi/thread.hpp>
7c673cae
FG
58 #ifndef BOOST_MUTEX_HELPER
59 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
60 #endif
61 #elif defined(BOOST_HAS_UNISTD_H)
62 #include <unistd.h>
63 #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
64 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
65 #endif
66 #endif
67#endif
68
69#ifndef BOOST_MUTEX_HELPER
70 #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
71#endif
72
73#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
74 //...
75#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
76 #if defined(_MSC_VER)
1e59de90 77 #include <boost/detail/interlocked.hpp>
7c673cae
FG
78 #define interlockedcompareexchange _InterlockedCompareExchange
79 #define interlockedexchange _InterlockedExchange
80 #elif defined(WIN32) && defined(__GNUC__)
81 #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
82 #define interlockedexchange __sync_lock_test_and_set
83 #endif /* Win32 */
84
85 /* First, define CAS_LOCK and CLEAR_LOCK on ints */
86 /* Note CAS_LOCK defined to return 0 on success */
87
88 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
89 #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
90 #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
91
92 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
93 /* Custom spin locks for older gcc on x86 */
94 static inline int boost_container_x86_cas_lock(int *sl) {
95 int ret;
96 int val = 1;
97 int cmp = 0;
98 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
99 : "=a" (ret)
100 : "r" (val), "m" (*(sl)), "0"(cmp)
101 : "memory", "cc");
102 return ret;
103 }
104
105 static inline void boost_container_x86_clear_lock(int* sl) {
106 assert(*sl != 0);
107 int prev = 0;
108 int ret;
109 __asm__ __volatile__ ("lock; xchgl %0, %1"
110 : "=r" (ret)
111 : "m" (*(sl)), "0"(prev)
112 : "memory");
113 }
114
115 #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
116 #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
117
118 #else /* Win32 MSC */
119 #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
120 #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
121 #endif
122
123 /* How to yield for a spin lock */
124 #define SPINS_PER_YIELD 63
125 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
126 #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
1e59de90 127 #define SPIN_LOCK_YIELD boost::winapi::SleepEx(SLEEP_EX_DURATION, 0)
7c673cae
FG
128 #elif defined (__SVR4) && defined (__sun) /* solaris */
129 #include <thread.h>
130 #define SPIN_LOCK_YIELD thr_yield();
131 #elif !defined(LACKS_SCHED_H)
132 #include <sched.h>
133 #define SPIN_LOCK_YIELD sched_yield();
134 #else
135 #define SPIN_LOCK_YIELD
136 #endif /* ... yield ... */
137
138 #define BOOST_CONTAINER_SPINS_PER_YIELD 63
139 inline int boost_interprocess_spin_acquire_lock(int *sl) {
140 int spins = 0;
141 while (*(volatile int *)sl != 0 ||
142 BOOST_CONTAINER_CAS_LOCK(sl)) {
143 if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
144 SPIN_LOCK_YIELD;
145 }
146 }
147 return 0;
148 }
149 #define BOOST_CONTAINER_MLOCK_T int
150 #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
151 #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
152 #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
153 #define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0)
154 #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
155#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
156 //
157#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
158 #include <pthread.h>
159#endif
160
161namespace boost {
162namespace container {
11fdf7f2 163namespace dtl {
7c673cae
FG
164
165#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
166 class null_mutex
167 {
168 private:
169 null_mutex(const null_mutex &);
170 void operator=(const null_mutex &);
171
172 public:
173 null_mutex() { }
174
175 static void lock() { }
176 static void unlock() { }
177 };
178
179 typedef null_mutex default_mutex;
180#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
181
182 class spin_mutex
183 {
184 private:
185 BOOST_CONTAINER_MLOCK_T sl;
186 spin_mutex(const spin_mutex &);
187 void operator=(const spin_mutex &);
188
189 public:
190 spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
191
192 void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
193 void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
194 };
195 typedef spin_mutex default_mutex;
196#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
197 class mutex
198 {
199 private:
200 CRITICAL_SECTION mtx;
201
202 mutex(const mutex &);
203 void operator=(const mutex &);
204
205 public:
206 mutex()
207 { InitializeCriticalSection(&mtx); }
208
209 ~mutex()
210 { DeleteCriticalSection(&mtx); }
211
212 void lock()
213 { EnterCriticalSection(&mtx); }
214
215 void unlock()
216 { LeaveCriticalSection(&mtx); }
217 };
218
219 typedef mutex default_mutex;
220#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
221 class mutex
222 {
223 private:
224 pthread_mutex_t mtx;
225
226 mutex(const mutex &);
227 void operator=(const mutex &);
228
229 public:
230 mutex()
231 { pthread_mutex_init(&mtx, 0); }
232
233 ~mutex()
234 { pthread_mutex_destroy(&mtx); }
235
236 void lock()
237 { pthread_mutex_lock(&mtx); }
238
239 void unlock()
240 { pthread_mutex_unlock(&mtx); }
241 };
242
243 typedef mutex default_mutex;
244#endif
245
246template<class Mutex>
247class scoped_lock
248{
249 public:
250 scoped_lock(Mutex &m)
251 : m_(m)
252 { m_.lock(); }
253 ~scoped_lock()
254 { m_.unlock(); }
255
256 private:
257 Mutex &m_;
258};
259
11fdf7f2 260} // namespace dtl
7c673cae
FG
261} // namespace container
262} // namespace boost
263
264#undef BOOST_MUTEX_HELPER_WIN32
265#undef BOOST_MUTEX_HELPER_PTHREAD
266#undef BOOST_MUTEX_HELPER_NONE
267#undef BOOST_MUTEX_HELPER
268#undef BOOST_MUTEX_HELPER_SPINLOCKS
269
270#include <boost/container/detail/config_end.hpp>
271
272#endif