FFmpeg
Loading...
Searching...
No Matches
stdatomic.h
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifndef COMPAT_ATOMICS_STDATOMIC_H
20#define COMPAT_ATOMICS_STDATOMIC_H
21
22#include <stdbool.h>
23#include <stddef.h>
24#include <stdint.h>
25
27
36
37/*
38 * The implementation header provides the primitives:
39 * - FF_ATOMIC_LOCK_FREE, the value of the ATOMIC_*_LOCK_FREE macros.
40 * - FF_ATOMIC_ALIGN64, the declaration specifier that aligns the 8-byte
41 * types to 8 bytes, empty where they are naturally aligned.
42 * - ff_atomic_thread_fence(order) and ff_atomic_signal_fence(order).
43 * - Helpers for the widths W = bool, 8, 16, 32 and 64, selected by the size
44 * of the object, taking it as a void pointer and the values as the
45 * unsigned integer type of the width, which every value of an object of
46 * the width converts to, bool for the bool set:
47 * type ff_atomic_load_W(object, memory_order order)
48 * void ff_atomic_store_W(object, type desired, memory_order order)
49 * type ff_atomic_exchange_W(object, type desired, memory_order order)
50 * bool ff_atomic_cas_W(object, void *expected, type desired, memory_order order)
51 * type ff_atomic_fetch_{add,sub,or,xor,and}_W(object, type operand, memory_order order)
52 * The _Generic dispatch below selects one by the object type, the argument
53 * and result conversions happen at the call.
54 */
55#include "stdatomic_impl.h"
56
57typedef bool atomic_bool;
58typedef char atomic_char;
59typedef signed char atomic_schar;
60typedef unsigned char atomic_uchar;
61typedef short atomic_short;
62typedef unsigned short atomic_ushort;
63typedef int atomic_int;
64typedef unsigned int atomic_uint;
65typedef long atomic_long;
66typedef unsigned long atomic_ulong;
68typedef FF_ATOMIC_ALIGN64 unsigned long long atomic_ullong;
69typedef unsigned char atomic_char8_t;
70typedef uint_least16_t atomic_char16_t;
71typedef uint_least32_t atomic_char32_t;
72typedef wchar_t atomic_wchar_t;
73typedef int_least8_t atomic_int_least8_t;
74typedef uint_least8_t atomic_uint_least8_t;
75typedef int_least16_t atomic_int_least16_t;
76typedef uint_least16_t atomic_uint_least16_t;
77typedef int_least32_t atomic_int_least32_t;
78typedef uint_least32_t atomic_uint_least32_t;
81typedef int_fast8_t atomic_int_fast8_t;
82typedef uint_fast8_t atomic_uint_fast8_t;
83typedef int_fast16_t atomic_int_fast16_t;
84typedef uint_fast16_t atomic_uint_fast16_t;
85typedef int_fast32_t atomic_int_fast32_t;
86typedef uint_fast32_t atomic_uint_fast32_t;
89typedef intptr_t atomic_intptr_t;
90typedef uintptr_t atomic_uintptr_t;
91typedef size_t atomic_size_t;
92typedef ptrdiff_t atomic_ptrdiff_t;
95
96/*
97 * Emulation of the _Atomic qualifier form for integer and pointer types of at
98 * most 8 bytes. This has very limited support, and will fail to compile when
99 * used with other types. Notably:
100 * - The specifier form "_Atomic(T)" is not supported, a macro cannot
101 * provide both forms.
102 * - Loads and exchanges of pointer objects return void *, not T *. Function
103 * pointer objects rely on the common extension converting them to and
104 * from void *.
105 * - Enumerated types are not supported, MSVC does not match them against
106 * their underlying type in _Generic.
107 * - atomic_fetch_add() and atomic_fetch_sub() stay restricted to integer
108 * types, on pointers they would have to scale by the pointee size.
109 * - Plain accesses to atomic objects, _Atomic qualified or the atomic_*
110 * typedefs, are ordinary accesses, unlike in C11 where they are
111 * implicitly atomic. Every access has to go through the atomic_*
112 * functions.
113 * - The 8-byte typedefs carry the alignment their accesses need to be
114 * atomic where the compiler does not provide it, on 32-bit x86, the
115 * qualifier form cannot.
116 */
117#define _Atomic
118
119#define atomic_init(obj, value) ((void)(*(obj) = (value)))
120
121#define kill_dependency(y) (y)
122
123#define ATOMIC_BOOL_LOCK_FREE FF_ATOMIC_LOCK_FREE
124#define ATOMIC_CHAR_LOCK_FREE FF_ATOMIC_LOCK_FREE
125#define ATOMIC_CHAR8_T_LOCK_FREE FF_ATOMIC_LOCK_FREE
126#define ATOMIC_CHAR16_T_LOCK_FREE FF_ATOMIC_LOCK_FREE
127#define ATOMIC_CHAR32_T_LOCK_FREE FF_ATOMIC_LOCK_FREE
128#define ATOMIC_WCHAR_T_LOCK_FREE FF_ATOMIC_LOCK_FREE
129#define ATOMIC_SHORT_LOCK_FREE FF_ATOMIC_LOCK_FREE
130#define ATOMIC_INT_LOCK_FREE FF_ATOMIC_LOCK_FREE
131#define ATOMIC_LONG_LOCK_FREE FF_ATOMIC_LOCK_FREE
132#define ATOMIC_LLONG_LOCK_FREE FF_ATOMIC_LOCK_FREE
133#define ATOMIC_POINTER_LOCK_FREE FF_ATOMIC_LOCK_FREE
134
135#define atomic_is_lock_free(obj) ((void)(obj), (bool)(FF_ATOMIC_LOCK_FREE == 2))
136
137#define atomic_thread_fence(order) ff_atomic_thread_fence(order)
138#define atomic_signal_fence(order) ff_atomic_signal_fence(order)
139
140#define FF_ATOMIC_SIZE(op, size) \
141 _Generic((char (*)[size])0, \
142 char (*)[1]: ff_atomic_##op##_8, \
143 char (*)[2]: ff_atomic_##op##_16, \
144 char (*)[4]: ff_atomic_##op##_32, \
145 char (*)[8]: ff_atomic_##op##_64)
146
147static av_always_inline uintptr_t
148ff_atomic_load_ptr(const volatile void *object, memory_order order)
149{
150 return FF_ATOMIC_SIZE(load, sizeof(void *))(object, order);
151}
152
153static av_always_inline void ff_atomic_store_ptr(volatile void *object,
154 const volatile void *desired,
155 memory_order order)
156{
157/* The alias analysis of MSVC for ARM before 19.44 does not track a pointer
158 * converted to an integer for the store intrinsics, so the stores initializing
159 * the pointed-to object are eliminated as dead. The interlocked exchange is not
160 * affected, and with its result unused it compiles to the same store as a plain
161 * store would without the bug. */
162#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER < 1944 && \
163 (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC))
164 FF_ATOMIC_SIZE(exchange, sizeof(void *))(object, (uintptr_t)desired, order);
165#else
166 FF_ATOMIC_SIZE(store, sizeof(void *))(object, (uintptr_t)desired, order);
167#endif
168}
169
170static av_always_inline uintptr_t
171ff_atomic_exchange_ptr(volatile void *object, const volatile void *desired,
172 memory_order order)
173{
174 return FF_ATOMIC_SIZE(exchange, sizeof(void *))(object, (uintptr_t)desired,
175 order);
176}
177
178static av_always_inline bool ff_atomic_cas_ptr(volatile void *object,
179 void *expected,
180 const volatile void *desired,
181 memory_order order)
182{
183 return FF_ATOMIC_SIZE(cas, sizeof(void *))(object, expected,
184 (uintptr_t)desired, order);
185}
186
188
189/* the pointer helpers, for the objects of the pointer size only */
190#define FF_ATOMIC_PTR(op, object) \
191 _Generic((char (*)[sizeof(*(object))])0, \
192 char (*)[sizeof(void *)]: ff_atomic_##op##_ptr, \
193 default: ff_atomic_unsupported)
194
195/* MSVC before 19.44 does not treat char as its own type in _Generic. It matches
196 * either signed char or unsigned char, depending on /J, and rejects a separate
197 * char association as a duplicate.
198 * <https://developercommunity.visualstudio.com/t/_Generic-char-signed-char-unsigned-cha/1228885> */
199#if defined(_MSC_VER) && !defined(__clang__) && _MSC_VER < 1944
200#define FF_ATOMIC_CHAR(x)
201#else
202#define FF_ATOMIC_CHAR(x) char: x,
203#endif
204
205#define FF_ATOMIC_INT(op, object) \
206 FF_ATOMIC_CHAR(FF_ATOMIC_SIZE(op, sizeof(*(object)))) \
207 signed char: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
208 unsigned char: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
209 short: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
210 unsigned short: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
211 int: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
212 unsigned int: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
213 long: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
214 unsigned long: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
215 long long: FF_ATOMIC_SIZE(op, sizeof(*(object))), \
216 unsigned long long: FF_ATOMIC_SIZE(op, sizeof(*(object)))
217
218/* bool objects have their own set for the normalization */
219#define FF_ATOMIC_FN(op, object) \
220 _Generic(*(object), \
221 bool: ff_atomic_##op##_bool, \
222 FF_ATOMIC_INT(op, object), \
223 default: FF_ATOMIC_PTR(op, object))
224
225/* the fetch operations are for the integer objects only, bool is excluded
226 * and on pointers they would have to scale by the pointee size */
227#define FF_ATOMIC_FETCH_FN(op, object) \
228 _Generic(*(object), FF_ATOMIC_INT(op, object))
229
230/* the width or uintptr_t result back to the non-atomic type C */
231#define ff_atomic_c(object, x) \
232 _Generic(*(object), \
233 bool: (bool)(x), \
234 FF_ATOMIC_CHAR((char)(x)) \
235 signed char: (signed char)(x), \
236 unsigned char: (unsigned char)(x), \
237 short: (short)(x), \
238 unsigned short: (unsigned short)(x), \
239 int: (int)(x), \
240 unsigned int: (unsigned int)(x), \
241 long: (long)(x), \
242 unsigned long: (unsigned long)(x), \
243 long long: (long long)(x), \
244 unsigned long long: (unsigned long long)(x), \
245 default: (void *)(uintptr_t)(x))
246
247#define atomic_load_explicit(object, order) \
248 ff_atomic_c(object, FF_ATOMIC_FN(load, object)(object, order))
249
250#define atomic_load(object) \
251 atomic_load_explicit(object, memory_order_seq_cst)
252
253#define atomic_store_explicit(object, desired, order) \
254 FF_ATOMIC_FN(store, object)(object, desired, order)
255
256#define atomic_store(object, desired) \
257 atomic_store_explicit(object, desired, memory_order_seq_cst)
258
259#define atomic_exchange_explicit(object, desired, order) \
260 ff_atomic_c(object, FF_ATOMIC_FN(exchange, object)(object, desired, order))
261
262#define atomic_exchange(object, desired) \
263 atomic_exchange_explicit(object, desired, memory_order_seq_cst)
264
266 memory_order failure)
267{
268 if (success == memory_order_release && failure != memory_order_relaxed)
270 return success;
271}
272
273/* expected has to point to an object of the width of the atomic one */
274#define atomic_compare_exchange_strong_explicit(object, expected, desired, \
275 success, failure) \
276 ((void)_Generic((char (*)[sizeof(*(expected))])0, \
277 char (*)[sizeof(*(object))]: 0), \
278 FF_ATOMIC_FN(cas, object)(object, expected, desired, \
279 ff_atomic_cas_order(success, failure)))
280
281#define atomic_compare_exchange_strong(object, expected, desired) \
282 atomic_compare_exchange_strong_explicit(object, expected, desired, \
283 memory_order_seq_cst, \
284 memory_order_seq_cst)
285
286#define atomic_compare_exchange_weak_explicit(object, expected, desired, \
287 success, failure) \
288 atomic_compare_exchange_strong_explicit(object, expected, desired, \
289 success, failure)
290
291#define atomic_compare_exchange_weak(object, expected, desired) \
292 atomic_compare_exchange_strong(object, expected, desired)
293
294#define ff_atomic_fetch(object, operand, op, order) \
295 ff_atomic_c(object, FF_ATOMIC_FETCH_FN(op, object)(object, operand, order))
296
297#define atomic_fetch_add_explicit(object, operand, order) \
298 ff_atomic_fetch(object, operand, fetch_add, order)
299
300#define atomic_fetch_sub_explicit(object, operand, order) \
301 ff_atomic_fetch(object, operand, fetch_sub, order)
302
303#define atomic_fetch_or_explicit(object, operand, order) \
304 ff_atomic_fetch(object, operand, fetch_or, order)
305
306#define atomic_fetch_xor_explicit(object, operand, order) \
307 ff_atomic_fetch(object, operand, fetch_xor, order)
308
309#define atomic_fetch_and_explicit(object, operand, order) \
310 ff_atomic_fetch(object, operand, fetch_and, order)
311
312#define atomic_fetch_add(object, operand) \
313 atomic_fetch_add_explicit(object, operand, memory_order_seq_cst)
314
315#define atomic_fetch_sub(object, operand) \
316 atomic_fetch_sub_explicit(object, operand, memory_order_seq_cst)
317
318#define atomic_fetch_or(object, operand) \
319 atomic_fetch_or_explicit(object, operand, memory_order_seq_cst)
320
321#define atomic_fetch_xor(object, operand) \
322 atomic_fetch_xor_explicit(object, operand, memory_order_seq_cst)
323
324#define atomic_fetch_and(object, operand) \
325 atomic_fetch_and_explicit(object, operand, memory_order_seq_cst)
326
330
331#define ATOMIC_FLAG_INIT { 0 }
332
333#define atomic_flag_test_and_set_explicit(object, order) \
334 atomic_exchange_explicit(&(object)->value, 1, order)
335
336#define atomic_flag_test_and_set(object) \
337 atomic_flag_test_and_set_explicit(object, memory_order_seq_cst)
338
339#define atomic_flag_clear_explicit(object, order) \
340 atomic_store_explicit(&(object)->value, 0, order)
341
342#define atomic_flag_clear(object) \
343 atomic_flag_clear_explicit(object, memory_order_seq_cst)
344
345#endif /* COMPAT_ATOMICS_STDATOMIC_H */
#define FF_ATOMIC_ALIGN64
Macro definitions for various function/variable attributes.
#define av_always_inline
Definition attributes.h:72
static int exchange(MqcState *mqc, uint8_t *cxstate, int lps)
Definition mqcdec.c:45
FF_ATOMIC_ALIGN64 int_least64_t atomic_int_least64_t
Definition stdatomic.h:79
int_fast8_t atomic_int_fast8_t
Definition stdatomic.h:81
memory_order
Definition stdatomic.h:28
@ memory_order_consume
Definition stdatomic.h:30
@ memory_order_seq_cst
Definition stdatomic.h:34
@ memory_order_release
Definition stdatomic.h:32
@ memory_order_relaxed
Definition stdatomic.h:29
@ memory_order_acq_rel
Definition stdatomic.h:33
@ memory_order_acquire
Definition stdatomic.h:31
uint_least8_t atomic_uint_least8_t
Definition stdatomic.h:74
static av_always_inline uintptr_t ff_atomic_exchange_ptr(volatile void *object, const volatile void *desired, memory_order order)
Definition stdatomic.h:171
#define FF_ATOMIC_SIZE(op, size)
Definition stdatomic.h:140
unsigned char atomic_uchar
Definition stdatomic.h:60
uint_fast16_t atomic_uint_fast16_t
Definition stdatomic.h:84
uint_least16_t atomic_char16_t
Definition stdatomic.h:70
FF_ATOMIC_ALIGN64 unsigned long long atomic_ullong
Definition stdatomic.h:68
int atomic_int
Definition stdatomic.h:63
static av_always_inline memory_order ff_atomic_cas_order(memory_order success, memory_order failure)
Definition stdatomic.h:265
FF_ATOMIC_ALIGN64 uint_least64_t atomic_uint_least64_t
Definition stdatomic.h:80
char atomic_char
Definition stdatomic.h:58
FF_ATOMIC_ALIGN64 long long atomic_llong
Definition stdatomic.h:67
intptr_t atomic_intptr_t
Definition stdatomic.h:89
static av_always_inline bool ff_atomic_cas_ptr(volatile void *object, void *expected, const volatile void *desired, memory_order order)
Definition stdatomic.h:178
static av_always_inline void ff_atomic_store_ptr(volatile void *object, const volatile void *desired, memory_order order)
Definition stdatomic.h:153
unsigned int atomic_uint
Definition stdatomic.h:64
uint_fast8_t atomic_uint_fast8_t
Definition stdatomic.h:82
bool atomic_bool
Definition stdatomic.h:57
uint_least32_t atomic_char32_t
Definition stdatomic.h:71
unsigned char atomic_char8_t
Definition stdatomic.h:69
FF_ATOMIC_ALIGN64 int_fast64_t atomic_int_fast64_t
Definition stdatomic.h:87
short atomic_short
Definition stdatomic.h:61
unsigned short atomic_ushort
Definition stdatomic.h:62
ptrdiff_t atomic_ptrdiff_t
Definition stdatomic.h:92
long atomic_long
Definition stdatomic.h:65
int_least32_t atomic_int_least32_t
Definition stdatomic.h:77
size_t atomic_size_t
Definition stdatomic.h:91
unsigned long atomic_ulong
Definition stdatomic.h:66
FF_ATOMIC_ALIGN64 uint_fast64_t atomic_uint_fast64_t
Definition stdatomic.h:88
uintptr_t atomic_uintptr_t
Definition stdatomic.h:90
void ff_atomic_unsupported(void)
static av_always_inline uintptr_t ff_atomic_load_ptr(const volatile void *object, memory_order order)
Definition stdatomic.h:148
int_fast32_t atomic_int_fast32_t
Definition stdatomic.h:85
wchar_t atomic_wchar_t
Definition stdatomic.h:72
int_fast16_t atomic_int_fast16_t
Definition stdatomic.h:83
uint_fast32_t atomic_uint_fast32_t
Definition stdatomic.h:86
int_least16_t atomic_int_least16_t
Definition stdatomic.h:75
FF_ATOMIC_ALIGN64 intmax_t atomic_intmax_t
Definition stdatomic.h:93
uint_least16_t atomic_uint_least16_t
Definition stdatomic.h:76
FF_ATOMIC_ALIGN64 uintmax_t atomic_uintmax_t
Definition stdatomic.h:94
signed char atomic_schar
Definition stdatomic.h:59
int_least8_t atomic_int_least8_t
Definition stdatomic.h:73
uint_least32_t atomic_uint_least32_t
Definition stdatomic.h:78
atomic_bool value
Definition stdatomic.h:328