QVisu
Qt-based visualization for smart homes
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
vlc_atomic.h
Go to the documentation of this file.
1 /*****************************************************************************
2  * vlc_atomic.h:
3  *****************************************************************************
4  * Copyright (C) 2010 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20 
21 #ifndef VLC_ATOMIC_H
22 # define VLC_ATOMIC_H
23 
29 # if !defined (__cplusplus) && (__STDC_VERSION__ >= 201112L) \
30  && !defined (__STDC_NO_ATOMICS__)
31 
32 /*** Native C11 atomics ***/
33 # include <stdatomic.h>
34 
35 # else
36 
37 # define ATOMIC_FLAG_INIT false
38 
39 # define ATOMIC_VAR_INIT(value) (value)
40 
41 # define atomic_init(obj, value) \
42  do { *(obj) = (value); } while(0)
43 
44 # define kill_dependency(y) \
45  ((void)0)
46 
47 # define atomic_thread_fence(order) \
48  __sync_synchronize()
49 
50 # define atomic_signal_fence(order) \
51  ((void)0)
52 
53 # define atomic_is_lock_free(obj) \
54  false
55 
56 /* In principles, __sync_*() only supports int, long and long long and their
57  * unsigned equivalents, i.e. 4-bytes and 8-bytes types, although GCC also
58  * supports 1 and 2-bytes types. Some non-x86 architectures do not support
59  * 8-byte atomic types (or not efficiently). */
60 typedef bool atomic_flag;
61 typedef bool atomic_bool;
62 typedef char atomic_char;
63 typedef signed char atomic_schar;
64 typedef unsigned char atomic_uchar;
65 typedef short atomic_short;
66 typedef unsigned short atomic_ushort;
67 typedef int atomic_int;
68 typedef unsigned int atomic_uint;
69 typedef long atomic_long;
70 typedef unsigned long atomic_ulong;
71 typedef long long atomic_llong;
72 typedef unsigned long long atomic_ullong;
73 //typedef char16_t atomic_char16_t;
74 //typedef char32_t atomic_char32_t;
75 typedef wchar_t atomic_wchar_t;
76 typedef int_least8_t atomic_int_least8_t;
77 typedef uint_least8_t atomic_uint_least8_t;
78 typedef int_least16_t atomic_int_least16_t;
79 typedef uint_least16_t atomic_uint_least16_t;
80 typedef int_least32_t atomic_int_least32_t;
81 typedef uint_least32_t atomic_uint_least32_t;
82 typedef int_least64_t atomic_int_least64_t;
83 typedef uint_least64_t atomic_uint_least64_t;
84 typedef int_fast8_t atomic_int_fast8_t;
85 typedef uint_fast8_t atomic_uint_fast8_t;
86 typedef int_fast16_t atomic_int_fast16_t;
87 typedef uint_fast16_t atomic_uint_fast16_t;
88 typedef int_fast32_t atomic_int_fast32_t;
89 typedef uint_fast32_t atomic_uint_fast32_t;
90 typedef int_fast64_t atomic_int_fast64_t;
91 typedef uint_fast64_t atomic_uint_fast64_t;
92 typedef intptr_t atomic_intptr_t;
93 typedef uintptr_t atomic_uintptr_t;
94 typedef size_t atomic_size_t;
95 typedef ptrdiff_t atomic_ptrdiff_t;
96 typedef intmax_t atomic_intmax_t;
97 typedef uintmax_t atomic_uintmax_t;
98 
99 # if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || (defined (__clang__) && (defined (__x86_64__) || defined (__i386__)))
100 
101 /*** Intel/GCC atomics ***/
102 
103 # define atomic_store(object,desired) \
104  do { \
105  *(object) = (desired); \
106  __sync_synchronize(); \
107  } while (0)
108 
109 # define atomic_store_explicit(object,desired,order) \
110  atomic_store(object,desired)
111 
112 # define atomic_load(object) \
113  (__sync_synchronize(), *(object))
114 
115 # define atomic_load_explicit(object,order) \
116  atomic_load(object)
117 
118 # define atomic_exchange(object,desired) \
119 ({ \
120  typeof (object) _obj = (object); \
121  typeof (*object) _old; \
122  do \
123  _old = atomic_load(_obj); \
124  while (!__sync_bool_compare_and_swap(_obj, _old, (desired))); \
125  _old; \
126 })
127 
128 # define atomic_exchange_explicit(object,desired,order) \
129  atomic_exchange(object,desired)
130 
131 # define atomic_compare_exchange(object,expected,desired) \
132 ({ \
133  typeof (object) _exp = (expected); \
134  typeof (*object) _old = *_exp; \
135  *_exp = __sync_val_compare_and_swap((object), _old, (desired)); \
136  *_exp == _old; \
137 })
138 
139 # define atomic_compare_exchange_strong(object,expected,desired) \
140  atomic_compare_exchange(object, expected, desired)
141 
142 # define atomic_compare_exchange_strong_explicit(object,expected,desired,order) \
143  atomic_compare_exchange_strong(object, expected, desired)
144 
145 # define atomic_compare_exchange_weak(object,expected,desired) \
146  atomic_compare_exchange(object, expected, desired)
147 
148 # define atomic_compare_exchange_weak_explicit(object,expected,desired,order) \
149  atomic_compare_exchange_weak(object, expected, desired)
150 
151 # define atomic_fetch_add(object,operand) \
152  __sync_fetch_and_add(object, operand)
153 
154 # define atomic_fetch_add_explicit(object,operand,order) \
155  atomic_fetch_add(object,operand)
156 
157 # define atomic_fetch_sub(object,operand) \
158  __sync_fetch_and_sub(object, operand)
159 
160 # define atomic_fetch_sub_explicit(object,operand,order) \
161  atomic_fetch_sub(object,operand)
162 
163 # define atomic_fetch_or(object,operand) \
164  __sync_fetch_and_or(object, operand)
165 
166 # define atomic_fetch_or_explicit(object,operand,order) \
167  atomic_fetch_or(object,operand)
168 
169 # define atomic_fetch_xor(object,operand) \
170  __sync_fetch_and_sub(object, operand)
171 
172 # define atomic_fetch_xor_explicit(object,operand,order) \
173  atomic_fetch_sub(object,operand)
174 
175 # define atomic_fetch_and(object,operand) \
176  __sync_fetch_and_and(object, operand)
177 
178 # define atomic_fetch_and_explicit(object,operand,order) \
179  atomic_fetch_and(object,operand)
180 
181 # define atomic_flag_test_and_set(object) \
182  atomic_exchange(object, true)
183 
184 # define atomic_flag_test_and_set_explicit(object,order) \
185  atomic_flag_test_and_set(object)
186 
187 # define atomic_flag_clear(object) \
188  atomic_store(object, false)
189 
190 # define atomic_flag_clear_explicit(object,order) \
191  atomic_flag_clear(object)
192 
193 # elif defined (__GNUC__)
194 
195 /*** No atomics ***/
196 
197 # define atomic_store(object,desired) \
198  do { \
199  typeof (object) _obj = (object); \
200  typeof (*object) _des = (desired); \
201  vlc_global_lock(VLC_ATOMIC_MUTEX); \
202  *_obj = _des; \
203  vlc_global_unlock(VLC_ATOMIC_MUTEX); \
204  } while (0)
205 # define atomic_store_explicit(object,desired,order) \
206  atomic_store(object,desired)
207 
208 # define atomic_load(object) \
209 ({ \
210  typeof (object) _obj = (object); \
211  typeof (*object) _old; \
212  vlc_global_lock(VLC_ATOMIC_MUTEX); \
213  _old = *_obj; \
214  vlc_global_unlock(VLC_ATOMIC_MUTEX); \
215  _old; \
216 })
217 # define atomic_load_explicit(object,order) \
218  atomic_load(object)
219 
220 # define atomic_exchange(object,desired) \
221 ({ \
222  typeof (object) _obj = (object); \
223  typeof (*object) _des = (desired); \
224  typeof (*object) _old; \
225  vlc_global_lock(VLC_ATOMIC_MUTEX); \
226  _old = *_obj; \
227  *_obj = _des; \
228  vlc_global_unlock(VLC_ATOMIC_MUTEX); \
229  _old; \
230 })
231 # define atomic_exchange_explicit(object,desired,order) \
232  atomic_exchange(object,desired)
233 
234 # define atomic_compare_exchange_strong(object,expected,desired) \
235 ({ \
236  typeof (object) _obj = (object); \
237  typeof (object) _exp = (expected); \
238  typeof (*object) _des = (desired); \
239  bool ret; \
240  vlc_global_lock(VLC_ATOMIC_MUTEX); \
241  ret = *_obj == *_exp; \
242  if (ret) \
243  *_obj = _des; \
244  else \
245  *_exp = *_obj; \
246  vlc_global_unlock(VLC_ATOMIC_MUTEX); \
247  ret; \
248 })
249 # define atomic_compare_exchange_strong_explicit(object,expected,desired,order) \
250  atomic_compare_exchange_strong(object, expected, desired)
251 # define atomic_compare_exchange_weak(object,expected,desired) \
252  atomic_compare_exchange_strong(object, expected, desired)
253 # define atomic_compare_exchange_weak_explicit(object,expected,desired,order) \
254  atomic_compare_exchange_weak(object, expected, desired)
255 
256 # define atomic_fetch_OP(object,desired,op) \
257 ({ \
258  typeof (object) _obj = (object); \
259  typeof (*object) _des = (desired); \
260  typeof (*object) _old; \
261  vlc_global_lock(VLC_ATOMIC_MUTEX); \
262  _old = *_obj; \
263  *_obj = (*_obj) op (_des); \
264  vlc_global_unlock(VLC_ATOMIC_MUTEX); \
265  _old; \
266 })
267 
268 # define atomic_fetch_add(object,operand) \
269  atomic_fetch_OP(object,operand,+)
270 # define atomic_fetch_add_explicit(object,operand,order) \
271  atomic_fetch_add(object,operand)
272 
273 # define atomic_fetch_sub(object,operand) \
274  atomic_fetch_OP(object,operand,-)
275 # define atomic_fetch_sub_explicit(object,operand,order) \
276  atomic_fetch_sub(object,operand)
277 
278 # define atomic_fetch_or(object,operand) \
279  atomic_fetch_OP(object,operand,|)
280 # define atomic_fetch_or_explicit(object,operand,order) \
281  atomic_fetch_or(object,operand)
282 
283 # define atomic_fetch_xor(object,operand) \
284  atomic_fetch_OP(object,operand,^)
285 # define atomic_fetch_xor_explicit(object,operand,order) \
286  atomic_fetch_sub(object,operand)
287 
288 # define atomic_fetch_and(object,operand) \
289  atomic_fetch_OP(object,operand,&)
290 # define atomic_fetch_and_explicit(object,operand,order) \
291  atomic_fetch_and(object,operand)
292 
293 # define atomic_flag_test_and_set(object) \
294  atomic_exchange(object, true)
295 
296 # define atomic_flag_test_and_set_explicit(object,order) \
297  atomic_flag_test_and_set(object)
298 
299 # define atomic_flag_clear(object) \
300  atomic_store(object, false)
301 
302 # define atomic_flag_clear_explicit(object,order) \
303  atomic_flag_clear(object)
304 
305 # else
306 # error FIXME: implement atomic operations for this compiler.
307 # endif
308 # endif
309 
313 typedef union
314 {
315  atomic_uintptr_t u;
316 } vlc_atomic_t;
317 
319 # define VLC_ATOMIC_INIT(val) { (val) }
320 
321 /* All functions return the atom value _after_ the operation. */
322 static inline uintptr_t vlc_atomic_get(vlc_atomic_t *atom)
323 {
324  return atomic_load(&atom->u);
325 }
326 
327 static inline uintptr_t vlc_atomic_set(vlc_atomic_t *atom, uintptr_t v)
328 {
329  atomic_store(&atom->u, v);
330  return v;
331 }
332 
333 static inline uintptr_t vlc_atomic_add(vlc_atomic_t *atom, uintptr_t v)
334 {
335  return atomic_fetch_add(&atom->u, v) + v;
336 }
337 
338 static inline uintptr_t vlc_atomic_sub (vlc_atomic_t *atom, uintptr_t v)
339 {
340  return atomic_fetch_sub (&atom->u, v) - v;
341 }
342 
343 static inline uintptr_t vlc_atomic_inc (vlc_atomic_t *atom)
344 {
345  return vlc_atomic_add (atom, 1);
346 }
347 
348 static inline uintptr_t vlc_atomic_dec (vlc_atomic_t *atom)
349 {
350  return vlc_atomic_sub (atom, 1);
351 }
352 
353 static inline uintptr_t vlc_atomic_swap(vlc_atomic_t *atom, uintptr_t v)
354 {
355  return atomic_exchange(&atom->u, v);
356 }
357 
358 static inline uintptr_t vlc_atomic_compare_swap(vlc_atomic_t *atom,
359  uintptr_t u, uintptr_t v)
360 {
361  atomic_compare_exchange_strong(&atom->u, &u, v);
362  return u;
363 }
364 
365 typedef atomic_uint_least32_t vlc_atomic_float;
366 
368 static inline float vlc_atomic_loadf(vlc_atomic_float *atom)
369 {
370  union { float f; uint32_t i; } u;
371  u.i = atomic_load(atom);
372  return u.f;
373 }
374 
376 static inline void vlc_atomic_storef(vlc_atomic_float *atom, float f)
377 {
378  union { float f; uint32_t i; } u;
379  u.f = f;
380  atomic_store(atom, u.i);
381 }
382 
383 #endif
Definition: vlc_atomic.h:313