ReactOS 0.4.16-dev-1946-g52006dd
atomic.h
Go to the documentation of this file.
1#pragma once
2
3/*
4 * Most of this header is a giant workaround for MSVC to make atomics into a
5 * somewhat unified interface with how GCC and Clang handle them.
6 *
7 * We don't use the absolutely disgusting C11 stdatomic.h header because it is
8 * unable to operate on non _Atomic types, which enforce implicit sequential
9 * consistency and alter the behavior of the standard C binary/unary operators.
10 *
11 * The strictness of the atomic helpers defined here is assumed to be at least
12 * acquire for loads and release for stores. Cmpxchg uses the standard acq/rel
13 * for success, acq for failure, and is assumed to be strong.
14 */
15
16#ifdef UACPI_OVERRIDE_ATOMIC
17#include "uacpi_atomic.h"
18#else
19
21
22#if defined(_MSC_VER) && !defined(__clang__)
23
24#include <intrin.h>
25
26// mimic __atomic_compare_exchange_n that doesn't exist on MSVC
27#define UACPI_MAKE_MSVC_CMPXCHG(width, type, suffix) \
28 static inline int uacpi_do_atomic_cmpxchg##width( \
29 type volatile *ptr, type volatile *expected, type desired \
30 ) \
31 { \
32 type current; \
33 \
34 current = _InterlockedCompareExchange##suffix(ptr, *expected, desired); \
35 if (current != *expected) { \
36 *expected = current; \
37 return 0; \
38 } \
39 return 1; \
40 }
41
42#define UACPI_MSVC_CMPXCHG_INVOKE(ptr, expected, desired, width, type) \
43 uacpi_do_atomic_cmpxchg##width( \
44 (type volatile*)ptr, (type volatile*)expected, desired \
45 )
46
47#define UACPI_MSVC_ATOMIC_STORE(ptr, value, type, width) \
48 _InterlockedExchange##width((type volatile*)(ptr), (type)(value))
49
50#define UACPI_MSVC_ATOMIC_LOAD(ptr, type, width) \
51 _InterlockedOr##width((type volatile*)(ptr), 0)
52
53#define UACPI_MSVC_ATOMIC_INC(ptr, type, width) \
54 _InterlockedIncrement##width((type volatile*)(ptr))
55
56#define UACPI_MSVC_ATOMIC_DEC(ptr, type, width) \
57 _InterlockedDecrement##width((type volatile*)(ptr))
58
59UACPI_MAKE_MSVC_CMPXCHG(64, __int64, 64)
60UACPI_MAKE_MSVC_CMPXCHG(32, long,)
61UACPI_MAKE_MSVC_CMPXCHG(16, short, 16)
62
63#define uacpi_atomic_cmpxchg16(ptr, expected, desired) \
64 UACPI_MSVC_CMPXCHG_INVOKE(ptr, expected, desired, 16, short)
65
66#define uacpi_atomic_cmpxchg32(ptr, expected, desired) \
67 UACPI_MSVC_CMPXCHG_INVOKE(ptr, expected, desired, 32, long)
68
69#define uacpi_atomic_cmpxchg64(ptr, expected, desired) \
70 UACPI_MSVC_CMPXCHG_INVOKE(ptr, expected, desired, 64, __int64)
71
72#define uacpi_atomic_load8(ptr) UACPI_MSVC_ATOMIC_LOAD(ptr, char, 8)
73#define uacpi_atomic_load16(ptr) UACPI_MSVC_ATOMIC_LOAD(ptr, short, 16)
74#define uacpi_atomic_load32(ptr) UACPI_MSVC_ATOMIC_LOAD(ptr, long,)
75#define uacpi_atomic_load64(ptr) UACPI_MSVC_ATOMIC_LOAD(ptr, __int64, 64)
76
77#define uacpi_atomic_store8(ptr, value) UACPI_MSVC_ATOMIC_STORE(ptr, value, char, 8)
78#define uacpi_atomic_store16(ptr, value) UACPI_MSVC_ATOMIC_STORE(ptr, value, short, 16)
79#define uacpi_atomic_store32(ptr, value) UACPI_MSVC_ATOMIC_STORE(ptr, value, long,)
80#define uacpi_atomic_store64(ptr, value) UACPI_MSVC_ATOMIC_STORE(ptr, value, __int64, 64)
81
82#define uacpi_atomic_inc16(ptr) UACPI_MSVC_ATOMIC_INC(ptr, short, 16)
83#define uacpi_atomic_inc32(ptr) UACPI_MSVC_ATOMIC_INC(ptr, long,)
84#define uacpi_atomic_inc64(ptr) UACPI_MSVC_ATOMIC_INC(ptr, __int64, 64)
85
86#define uacpi_atomic_dec16(ptr) UACPI_MSVC_ATOMIC_DEC(ptr, short, 16)
87#define uacpi_atomic_dec32(ptr) UACPI_MSVC_ATOMIC_DEC(ptr, long,)
88#define uacpi_atomic_dec64(ptr) UACPI_MSVC_ATOMIC_DEC(ptr, __int64, 64)
89#else
90
91#define UACPI_DO_CMPXCHG(ptr, expected, desired) \
92 __atomic_compare_exchange_n(ptr, expected, desired, 0, \
93 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)
94
95#define uacpi_atomic_cmpxchg16(ptr, expected, desired) \
96 UACPI_DO_CMPXCHG(ptr, expected, desired)
97#define uacpi_atomic_cmpxchg32(ptr, expected, desired) \
98 UACPI_DO_CMPXCHG(ptr, expected, desired)
99#define uacpi_atomic_cmpxchg64(ptr, expected, desired) \
100 UACPI_DO_CMPXCHG(ptr, expected, desired)
101
102#define uacpi_atomic_load8(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
103#define uacpi_atomic_load16(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
104#define uacpi_atomic_load32(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
105#define uacpi_atomic_load64(ptr) __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
106
107#define uacpi_atomic_store8(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_RELEASE)
108#define uacpi_atomic_store16(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_RELEASE)
109#define uacpi_atomic_store32(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_RELEASE)
110#define uacpi_atomic_store64(ptr, value) __atomic_store_n(ptr, value, __ATOMIC_RELEASE)
111
112#define uacpi_atomic_inc16(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_ACQ_REL)
113#define uacpi_atomic_inc32(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_ACQ_REL)
114#define uacpi_atomic_inc64(ptr) __atomic_add_fetch(ptr, 1, __ATOMIC_ACQ_REL)
115
116#define uacpi_atomic_dec16(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_ACQ_REL)
117#define uacpi_atomic_dec32(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_ACQ_REL)
118#define uacpi_atomic_dec64(ptr) __atomic_sub_fetch(ptr, 1, __ATOMIC_ACQ_REL)
119#endif
120
121#if UACPI_POINTER_SIZE == 4
122#define uacpi_atomic_load_ptr(ptr_to_ptr) uacpi_atomic_load32(ptr_to_ptr)
123#define uacpi_atomic_store_ptr(ptr_to_ptr, value) uacpi_atomic_store32(ptr_to_ptr, value)
124#else
125#define uacpi_atomic_load_ptr(ptr_to_ptr) uacpi_atomic_load64(ptr_to_ptr)
126#define uacpi_atomic_store_ptr(ptr_to_ptr, value) uacpi_atomic_store64(ptr_to_ptr, value)
127#endif
128
129#endif
#define __int64
Definition: basetyps.h:16