]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/container/detail/mutex.hpp
update sources to ceph Nautilus 14.2.1
[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)
56 #include <windows.h>
57 #ifndef BOOST_MUTEX_HELPER
58 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_WIN32
59 #endif
60 #elif defined(BOOST_HAS_UNISTD_H)
61 #include <unistd.h>
62 #if !defined(BOOST_MUTEX_HELPER) && (defined(_POSIX_THREADS) || defined(BOOST_HAS_PTHREADS))
63 #define BOOST_MUTEX_HELPER BOOST_MUTEX_HELPER_PTHREAD
64 #endif
65 #endif
66#endif
67
68#ifndef BOOST_MUTEX_HELPER
69 #error Unable to determine platform mutex type; #define BOOST_NO_MT to assume single-threaded
70#endif
71
72#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
73 //...
74#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
75 #if defined(_MSC_VER)
76 #ifndef _M_AMD64
77 /* These are already defined on AMD64 builds */
78 #ifdef __cplusplus
79 extern "C" {
80 #endif /* __cplusplus */
81 long __cdecl _InterlockedCompareExchange(long volatile *Dest, long Exchange, long Comp);
82 long __cdecl _InterlockedExchange(long volatile *Target, long Value);
83 #ifdef __cplusplus
84 }
85 #endif /* __cplusplus */
86 #endif /* _M_AMD64 */
87 #pragma intrinsic (_InterlockedCompareExchange)
88 #pragma intrinsic (_InterlockedExchange)
89 #define interlockedcompareexchange _InterlockedCompareExchange
90 #define interlockedexchange _InterlockedExchange
91 #elif defined(WIN32) && defined(__GNUC__)
92 #define interlockedcompareexchange(a, b, c) __sync_val_compare_and_swap(a, c, b)
93 #define interlockedexchange __sync_lock_test_and_set
94 #endif /* Win32 */
95
96 /* First, define CAS_LOCK and CLEAR_LOCK on ints */
97 /* Note CAS_LOCK defined to return 0 on success */
98
99 #if defined(__GNUC__)&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1))
100 #define BOOST_CONTAINER_CAS_LOCK(sl) __sync_lock_test_and_set(sl, 1)
101 #define BOOST_CONTAINER_CLEAR_LOCK(sl) __sync_lock_release(sl)
102
103 #elif (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)))
104 /* Custom spin locks for older gcc on x86 */
105 static inline int boost_container_x86_cas_lock(int *sl) {
106 int ret;
107 int val = 1;
108 int cmp = 0;
109 __asm__ __volatile__ ("lock; cmpxchgl %1, %2"
110 : "=a" (ret)
111 : "r" (val), "m" (*(sl)), "0"(cmp)
112 : "memory", "cc");
113 return ret;
114 }
115
116 static inline void boost_container_x86_clear_lock(int* sl) {
117 assert(*sl != 0);
118 int prev = 0;
119 int ret;
120 __asm__ __volatile__ ("lock; xchgl %0, %1"
121 : "=r" (ret)
122 : "m" (*(sl)), "0"(prev)
123 : "memory");
124 }
125
126 #define BOOST_CONTAINER_CAS_LOCK(sl) boost_container_x86_cas_lock(sl)
127 #define BOOST_CONTAINER_CLEAR_LOCK(sl) boost_container_x86_clear_lock(sl)
128
129 #else /* Win32 MSC */
130 #define BOOST_CONTAINER_CAS_LOCK(sl) interlockedexchange((long volatile*)sl, (long)1)
131 #define BOOST_CONTAINER_CLEAR_LOCK(sl) interlockedexchange((long volatile*)sl, (long)0)
132 #endif
133
134 /* How to yield for a spin lock */
135 #define SPINS_PER_YIELD 63
136 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
137 #define SLEEP_EX_DURATION 50 /* delay for yield/sleep */
138 #define SPIN_LOCK_YIELD SleepEx(SLEEP_EX_DURATION, FALSE)
139 #elif defined (__SVR4) && defined (__sun) /* solaris */
140 #include <thread.h>
141 #define SPIN_LOCK_YIELD thr_yield();
142 #elif !defined(LACKS_SCHED_H)
143 #include <sched.h>
144 #define SPIN_LOCK_YIELD sched_yield();
145 #else
146 #define SPIN_LOCK_YIELD
147 #endif /* ... yield ... */
148
149 #define BOOST_CONTAINER_SPINS_PER_YIELD 63
150 inline int boost_interprocess_spin_acquire_lock(int *sl) {
151 int spins = 0;
152 while (*(volatile int *)sl != 0 ||
153 BOOST_CONTAINER_CAS_LOCK(sl)) {
154 if ((++spins & BOOST_CONTAINER_SPINS_PER_YIELD) == 0) {
155 SPIN_LOCK_YIELD;
156 }
157 }
158 return 0;
159 }
160 #define BOOST_CONTAINER_MLOCK_T int
161 #define BOOST_CONTAINER_TRY_LOCK(sl) !BOOST_CONTAINER_CAS_LOCK(sl)
162 #define BOOST_CONTAINER_RELEASE_LOCK(sl) BOOST_CONTAINER_CLEAR_LOCK(sl)
163 #define BOOST_CONTAINER_ACQUIRE_LOCK(sl) (BOOST_CONTAINER_CAS_LOCK(sl)? boost_interprocess_spin_acquire_lock(sl) : 0)
164 #define BOOST_MOVE_INITIAL_LOCK(sl) (*sl = 0)
165 #define BOOST_CONTAINER_DESTROY_LOCK(sl) (0)
166#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
167 //
168#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
169 #include <pthread.h>
170#endif
171
172namespace boost {
173namespace container {
11fdf7f2 174namespace dtl {
7c673cae
FG
175
176#if BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_NONE
177 class null_mutex
178 {
179 private:
180 null_mutex(const null_mutex &);
181 void operator=(const null_mutex &);
182
183 public:
184 null_mutex() { }
185
186 static void lock() { }
187 static void unlock() { }
188 };
189
190 typedef null_mutex default_mutex;
191#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_SPINLOCKS
192
193 class spin_mutex
194 {
195 private:
196 BOOST_CONTAINER_MLOCK_T sl;
197 spin_mutex(const spin_mutex &);
198 void operator=(const spin_mutex &);
199
200 public:
201 spin_mutex() { BOOST_MOVE_INITIAL_LOCK(&sl); }
202
203 void lock() { BOOST_CONTAINER_ACQUIRE_LOCK(&sl); }
204 void unlock() { BOOST_CONTAINER_RELEASE_LOCK(&sl); }
205 };
206 typedef spin_mutex default_mutex;
207#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_WIN32
208 class mutex
209 {
210 private:
211 CRITICAL_SECTION mtx;
212
213 mutex(const mutex &);
214 void operator=(const mutex &);
215
216 public:
217 mutex()
218 { InitializeCriticalSection(&mtx); }
219
220 ~mutex()
221 { DeleteCriticalSection(&mtx); }
222
223 void lock()
224 { EnterCriticalSection(&mtx); }
225
226 void unlock()
227 { LeaveCriticalSection(&mtx); }
228 };
229
230 typedef mutex default_mutex;
231#elif BOOST_MUTEX_HELPER == BOOST_MUTEX_HELPER_PTHREAD
232 class mutex
233 {
234 private:
235 pthread_mutex_t mtx;
236
237 mutex(const mutex &);
238 void operator=(const mutex &);
239
240 public:
241 mutex()
242 { pthread_mutex_init(&mtx, 0); }
243
244 ~mutex()
245 { pthread_mutex_destroy(&mtx); }
246
247 void lock()
248 { pthread_mutex_lock(&mtx); }
249
250 void unlock()
251 { pthread_mutex_unlock(&mtx); }
252 };
253
254 typedef mutex default_mutex;
255#endif
256
257template<class Mutex>
258class scoped_lock
259{
260 public:
261 scoped_lock(Mutex &m)
262 : m_(m)
263 { m_.lock(); }
264 ~scoped_lock()
265 { m_.unlock(); }
266
267 private:
268 Mutex &m_;
269};
270
11fdf7f2 271} // namespace dtl
7c673cae
FG
272} // namespace container
273} // namespace boost
274
275#undef BOOST_MUTEX_HELPER_WIN32
276#undef BOOST_MUTEX_HELPER_PTHREAD
277#undef BOOST_MUTEX_HELPER_NONE
278#undef BOOST_MUTEX_HELPER
279#undef BOOST_MUTEX_HELPER_SPINLOCKS
280
281#include <boost/container/detail/config_end.hpp>
282
283#endif