Line data Source code
1 : #ifndef AWS_COMMON_ATOMICS_GNU_INL
2 : #define AWS_COMMON_ATOMICS_GNU_INL
3 :
4 : /**
5 : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6 : * SPDX-License-Identifier: Apache-2.0.
7 : */
8 :
9 : /* These are implicitly included, but help with editor highlighting */
10 : #include <aws/common/atomics.h>
11 : #include <aws/common/common.h>
12 :
13 : #include <stdint.h>
14 : #include <stdlib.h>
15 :
16 : AWS_EXTERN_C_BEGIN
17 :
18 : #ifdef __clang__
19 : # pragma clang diagnostic push
20 : # pragma clang diagnostic ignored "-Wc11-extensions"
21 : #else
22 : # pragma GCC diagnostic push
23 : # pragma GCC diagnostic ignored "-Wpedantic"
24 : #endif
25 :
26 : typedef size_t aws_atomic_impl_int_t;
27 :
28 130000 : static inline int aws_atomic_priv_xlate_order(enum aws_memory_order order) {
29 130000 : switch (order) {
30 0 : case aws_memory_order_relaxed:
31 0 : return __ATOMIC_RELAXED;
32 0 : case aws_memory_order_acquire:
33 0 : return __ATOMIC_ACQUIRE;
34 0 : case aws_memory_order_release:
35 0 : return __ATOMIC_RELEASE;
36 0 : case aws_memory_order_acq_rel:
37 0 : return __ATOMIC_ACQ_REL;
38 130000 : case aws_memory_order_seq_cst:
39 130000 : return __ATOMIC_SEQ_CST;
40 0 : default: /* Unknown memory order */
41 0 : abort();
42 130000 : }
43 130000 : }
44 :
45 : /**
46 : * Initializes an atomic variable with an integer value. This operation should be done before any
47 : * other operations on this atomic variable, and must be done before attempting any parallel operations.
48 : */
49 : AWS_STATIC_IMPL
50 0 : void aws_atomic_init_int(volatile struct aws_atomic_var *var, size_t n) {
51 0 : AWS_ATOMIC_VAR_INTVAL(var) = n;
52 0 : }
53 :
54 : /**
55 : * Initializes an atomic variable with a pointer value. This operation should be done before any
56 : * other operations on this atomic variable, and must be done before attempting any parallel operations.
57 : */
58 : AWS_STATIC_IMPL
59 15838 : void aws_atomic_init_ptr(volatile struct aws_atomic_var *var, void *p) {
60 15838 : AWS_ATOMIC_VAR_PTRVAL(var) = p;
61 15838 : }
62 :
63 : /**
64 : * Reads an atomic var as an integer, using the specified ordering, and returns the result.
65 : */
66 : AWS_STATIC_IMPL
67 0 : size_t aws_atomic_load_int_explicit(volatile const struct aws_atomic_var *var, enum aws_memory_order memory_order) {
68 0 : return __atomic_load_n(&AWS_ATOMIC_VAR_INTVAL(var), aws_atomic_priv_xlate_order(memory_order));
69 0 : }
70 :
71 : /**
72 : * Reads an atomic var as a pointer, using the specified ordering, and returns the result.
73 : */
74 : AWS_STATIC_IMPL
75 104756 : void *aws_atomic_load_ptr_explicit(volatile const struct aws_atomic_var *var, enum aws_memory_order memory_order) {
76 104756 : return __atomic_load_n(&AWS_ATOMIC_VAR_PTRVAL(var), aws_atomic_priv_xlate_order(memory_order));
77 104756 : }
78 :
79 : /**
80 : * Stores an integer into an atomic var, using the specified ordering.
81 : */
82 : AWS_STATIC_IMPL
83 0 : void aws_atomic_store_int_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order memory_order) {
84 0 : __atomic_store_n(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(memory_order));
85 0 : }
86 :
87 : /**
88 : * Stores an pointer into an atomic var, using the specified ordering.
89 : */
90 : AWS_STATIC_IMPL
91 25244 : void aws_atomic_store_ptr_explicit(volatile struct aws_atomic_var *var, void *p, enum aws_memory_order memory_order) {
92 25244 : __atomic_store_n(&AWS_ATOMIC_VAR_PTRVAL(var), p, aws_atomic_priv_xlate_order(memory_order));
93 25244 : }
94 :
95 : /**
96 : * Exchanges an integer with the value in an atomic_var, using the specified ordering.
97 : * Returns the value that was previously in the atomic_var.
98 : */
99 : AWS_STATIC_IMPL
100 : size_t aws_atomic_exchange_int_explicit(
101 : volatile struct aws_atomic_var *var,
102 : size_t n,
103 0 : enum aws_memory_order memory_order) {
104 0 : return __atomic_exchange_n(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(memory_order));
105 0 : }
106 :
107 : /**
108 : * Exchanges a pointer with the value in an atomic_var, using the specified ordering.
109 : * Returns the value that was previously in the atomic_var.
110 : */
111 : AWS_STATIC_IMPL
112 : void *aws_atomic_exchange_ptr_explicit(
113 : volatile struct aws_atomic_var *var,
114 : void *p,
115 0 : enum aws_memory_order memory_order) {
116 0 : return __atomic_exchange_n(&AWS_ATOMIC_VAR_PTRVAL(var), p, aws_atomic_priv_xlate_order(memory_order));
117 0 : }
118 :
119 : /**
120 : * Atomically compares *var to *expected; if they are equal, atomically sets *var = desired. Otherwise, *expected is set
121 : * to the value in *var. On success, the memory ordering used was order_success; otherwise, it was order_failure.
122 : * order_failure must be no stronger than order_success, and must not be release or acq_rel.
123 : */
124 : AWS_STATIC_IMPL
125 : bool aws_atomic_compare_exchange_int_explicit(
126 : volatile struct aws_atomic_var *var,
127 : size_t *expected,
128 : size_t desired,
129 : enum aws_memory_order order_success,
130 0 : enum aws_memory_order order_failure) {
131 0 : return __atomic_compare_exchange_n(
132 0 : &AWS_ATOMIC_VAR_INTVAL(var),
133 0 : expected,
134 0 : desired,
135 0 : false,
136 0 : aws_atomic_priv_xlate_order(order_success),
137 0 : aws_atomic_priv_xlate_order(order_failure));
138 0 : }
139 :
140 : /**
141 : * Atomically compares *var to *expected; if they are equal, atomically sets *var = desired. Otherwise, *expected is set
142 : * to the value in *var. On success, the memory ordering used was order_success; otherwise, it was order_failure.
143 : * order_failure must be no stronger than order_success, and must not be release or acq_rel.
144 : */
145 : AWS_STATIC_IMPL
146 : bool aws_atomic_compare_exchange_ptr_explicit(
147 : volatile struct aws_atomic_var *var,
148 : void **expected,
149 : void *desired,
150 : enum aws_memory_order order_success,
151 0 : enum aws_memory_order order_failure) {
152 0 : return __atomic_compare_exchange_n(
153 0 : &AWS_ATOMIC_VAR_PTRVAL(var),
154 0 : expected,
155 0 : desired,
156 0 : false,
157 0 : aws_atomic_priv_xlate_order(order_success),
158 0 : aws_atomic_priv_xlate_order(order_failure));
159 0 : }
160 :
161 : /**
162 : * Atomically adds n to *var, and returns the previous value of *var.
163 : */
164 : AWS_STATIC_IMPL
165 0 : size_t aws_atomic_fetch_add_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
166 0 : return __atomic_fetch_add(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(order));
167 0 : }
168 :
169 : /**
170 : * Atomically subtracts n from *var, and returns the previous value of *var.
171 : */
172 : AWS_STATIC_IMPL
173 0 : size_t aws_atomic_fetch_sub_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
174 0 : return __atomic_fetch_sub(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(order));
175 0 : }
176 :
177 : /**
178 : * Atomically ORs n with *var, and returns the previous value of *var.
179 : */
180 : AWS_STATIC_IMPL
181 0 : size_t aws_atomic_fetch_or_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
182 0 : return __atomic_fetch_or(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(order));
183 0 : }
184 :
185 : /**
186 : * Atomically ANDs n with *var, and returns the previous value of *var.
187 : */
188 : AWS_STATIC_IMPL
189 0 : size_t aws_atomic_fetch_and_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
190 0 : return __atomic_fetch_and(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(order));
191 0 : }
192 :
193 : /**
194 : * Atomically XORs n with *var, and returns the previous value of *var.
195 : */
196 : AWS_STATIC_IMPL
197 0 : size_t aws_atomic_fetch_xor_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
198 0 : return __atomic_fetch_xor(&AWS_ATOMIC_VAR_INTVAL(var), n, aws_atomic_priv_xlate_order(order));
199 0 : }
200 :
201 : /**
202 : * Provides the same reordering guarantees as an atomic operation with the specified memory order, without
203 : * needing to actually perform an atomic operation.
204 : */
205 : AWS_STATIC_IMPL
206 0 : void aws_atomic_thread_fence(enum aws_memory_order order) {
207 0 : __atomic_thread_fence(order);
208 0 : }
209 :
210 : #ifdef __clang__
211 : # pragma clang diagnostic pop
212 : #else
213 : # pragma GCC diagnostic pop
214 : #endif
215 :
216 : #define AWS_ATOMICS_HAVE_THREAD_FENCE
217 : AWS_EXTERN_C_END
218 : #endif /* AWS_COMMON_ATOMICS_GNU_INL */
|