Branch data Line data Source code
1 : : /* atomic operations */
2 : :
3 : : /*
4 : : * Copyright (c) 1997-2015, Wind River Systems, Inc.
5 : : *
6 : : * SPDX-License-Identifier: Apache-2.0
7 : : */
8 : :
9 : : #ifndef ZEPHYR_INCLUDE_SYS_ATOMIC_BUILTIN_H_
10 : : #define ZEPHYR_INCLUDE_SYS_ATOMIC_BUILTIN_H_
11 : :
12 : : #ifdef __cplusplus
13 : : extern "C" {
14 : : #endif
15 : :
16 : : /* Included from <atomic.h> */
17 : :
18 : : /**
19 : : * @addtogroup atomic_apis Atomic Services APIs
20 : : * @ingroup kernel_apis
21 : : * @{
22 : : */
23 : :
24 : : /**
25 : : * @brief Atomic compare-and-set.
26 : : *
27 : : * This routine performs an atomic compare-and-set on @a target. If the current
28 : : * value of @a target equals @a old_value, @a target is set to @a new_value.
29 : : * If the current value of @a target does not equal @a old_value, @a target
30 : : * is left unchanged.
31 : : *
32 : : * @note As for all atomic APIs, includes a
33 : : * full/sequentially-consistent memory barrier (where applicable).
34 : : *
35 : : * @param target Address of atomic variable.
36 : : * @param old_value Original value to compare against.
37 : : * @param new_value New value to store.
38 : : * @return true if @a new_value is written, false otherwise.
39 : : */
40 : 1 : static inline bool atomic_cas(atomic_t *target, atomic_val_t old_value,
41 : : atomic_val_t new_value)
42 : : {
43 : 1 : return __atomic_compare_exchange_n(target, &old_value, new_value,
44 : : 0, __ATOMIC_SEQ_CST,
45 : : __ATOMIC_SEQ_CST);
46 : : }
47 : :
48 : : /**
49 : : * @brief Atomic compare-and-set with pointer values
50 : : *
51 : : * This routine performs an atomic compare-and-set on @a target. If the current
52 : : * value of @a target equals @a old_value, @a target is set to @a new_value.
53 : : * If the current value of @a target does not equal @a old_value, @a target
54 : : * is left unchanged.
55 : : *
56 : : * @note As for all atomic APIs, includes a
57 : : * full/sequentially-consistent memory barrier (where applicable).
58 : : *
59 : : * @param target Address of atomic variable.
60 : : * @param old_value Original value to compare against.
61 : : * @param new_value New value to store.
62 : : * @return true if @a new_value is written, false otherwise.
63 : : */
64 : : static inline bool atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value,
65 : : atomic_ptr_val_t new_value)
66 : : {
67 : : return __atomic_compare_exchange_n(target, &old_value, new_value,
68 : : 0, __ATOMIC_SEQ_CST,
69 : : __ATOMIC_SEQ_CST);
70 : : }
71 : :
72 : : /**
73 : : *
74 : : * @brief Atomic addition.
75 : : *
76 : : * This routine performs an atomic addition on @a target.
77 : : *
78 : : * @note As for all atomic APIs, includes a
79 : : * full/sequentially-consistent memory barrier (where applicable).
80 : : *
81 : : * @param target Address of atomic variable.
82 : : * @param value Value to add.
83 : : *
84 : : * @return Previous value of @a target.
85 : : */
86 : 0 : static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
87 : : {
88 : 0 : return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
89 : : }
90 : :
91 : : /**
92 : : *
93 : : * @brief Atomic subtraction.
94 : : *
95 : : * This routine performs an atomic subtraction on @a target.
96 : : *
97 : : * @note As for all atomic APIs, includes a
98 : : * full/sequentially-consistent memory barrier (where applicable).
99 : : *
100 : : * @param target Address of atomic variable.
101 : : * @param value Value to subtract.
102 : : *
103 : : * @return Previous value of @a target.
104 : : */
105 : 0 : static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
106 : : {
107 : 0 : return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
108 : : }
109 : :
110 : : /**
111 : : *
112 : : * @brief Atomic increment.
113 : : *
114 : : * This routine performs an atomic increment by 1 on @a target.
115 : : *
116 : : * @note As for all atomic APIs, includes a
117 : : * full/sequentially-consistent memory barrier (where applicable).
118 : : *
119 : : * @param target Address of atomic variable.
120 : : *
121 : : * @return Previous value of @a target.
122 : : */
123 : 0 : static inline atomic_val_t atomic_inc(atomic_t *target)
124 : : {
125 : 0 : return atomic_add(target, 1);
126 : : }
127 : :
128 : : /**
129 : : *
130 : : * @brief Atomic decrement.
131 : : *
132 : : * This routine performs an atomic decrement by 1 on @a target.
133 : : *
134 : : * @note As for all atomic APIs, includes a
135 : : * full/sequentially-consistent memory barrier (where applicable).
136 : : *
137 : : * @param target Address of atomic variable.
138 : : *
139 : : * @return Previous value of @a target.
140 : : */
141 : 0 : static inline atomic_val_t atomic_dec(atomic_t *target)
142 : : {
143 : 0 : return atomic_sub(target, 1);
144 : : }
145 : :
146 : : /**
147 : : *
148 : : * @brief Atomic get.
149 : : *
150 : : * This routine performs an atomic read on @a target.
151 : : *
152 : : * @note As for all atomic APIs, includes a
153 : : * full/sequentially-consistent memory barrier (where applicable).
154 : : *
155 : : * @param target Address of atomic variable.
156 : : *
157 : : * @return Value of @a target.
158 : : */
159 : 1 : static inline atomic_val_t atomic_get(const atomic_t *target)
160 : : {
161 : 1 : return __atomic_load_n(target, __ATOMIC_SEQ_CST);
162 : : }
163 : :
164 : : /**
165 : : *
166 : : * @brief Atomic get a pointer value
167 : : *
168 : : * This routine performs an atomic read on @a target.
169 : : *
170 : : * @note As for all atomic APIs, includes a
171 : : * full/sequentially-consistent memory barrier (where applicable).
172 : : *
173 : : * @param target Address of pointer variable.
174 : : *
175 : : * @return Value of @a target.
176 : : */
177 : : static inline atomic_ptr_val_t atomic_ptr_get(const atomic_ptr_t *target)
178 : : {
179 : : return __atomic_load_n(target, __ATOMIC_SEQ_CST);
180 : : }
181 : :
182 : : /**
183 : : *
184 : : * @brief Atomic get-and-set.
185 : : *
186 : : * This routine atomically sets @a target to @a value and returns
187 : : * the previous value of @a target.
188 : : *
189 : : * @note As for all atomic APIs, includes a
190 : : * full/sequentially-consistent memory barrier (where applicable).
191 : : *
192 : : * @param target Address of atomic variable.
193 : : * @param value Value to write to @a target.
194 : : *
195 : : * @return Previous value of @a target.
196 : : */
197 : 1 : static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
198 : : {
199 : : /* This builtin, as described by Intel, is not a traditional
200 : : * test-and-set operation, but rather an atomic exchange operation. It
201 : : * writes value into *ptr, and returns the previous contents of *ptr.
202 : : */
203 : 1 : return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
204 : : }
205 : :
206 : : /**
207 : : *
208 : : * @brief Atomic get-and-set for pointer values
209 : : *
210 : : * This routine atomically sets @a target to @a value and returns
211 : : * the previous value of @a target.
212 : : *
213 : : * @note As for all atomic APIs, includes a
214 : : * full/sequentially-consistent memory barrier (where applicable).
215 : : *
216 : : * @param target Address of atomic variable.
217 : : * @param value Value to write to @a target.
218 : : *
219 : : * @return Previous value of @a target.
220 : : */
221 : : static inline atomic_ptr_val_t atomic_ptr_set(atomic_ptr_t *target, atomic_ptr_val_t value)
222 : : {
223 : : return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
224 : : }
225 : :
226 : : /**
227 : : *
228 : : * @brief Atomic clear.
229 : : *
230 : : * This routine atomically sets @a target to zero and returns its previous
231 : : * value. (Hence, it is equivalent to atomic_set(target, 0).)
232 : : *
233 : : * @note As for all atomic APIs, includes a
234 : : * full/sequentially-consistent memory barrier (where applicable).
235 : : *
236 : : * @param target Address of atomic variable.
237 : : *
238 : : * @return Previous value of @a target.
239 : : */
240 : : static inline atomic_val_t atomic_clear(atomic_t *target)
241 : : {
242 : : return atomic_set(target, 0);
243 : : }
244 : :
245 : : /**
246 : : *
247 : : * @brief Atomic clear of a pointer value
248 : : *
249 : : * This routine atomically sets @a target to zero and returns its previous
250 : : * value. (Hence, it is equivalent to atomic_set(target, 0).)
251 : : *
252 : : * @note As for all atomic APIs, includes a
253 : : * full/sequentially-consistent memory barrier (where applicable).
254 : : *
255 : : * @param target Address of atomic variable.
256 : : *
257 : : * @return Previous value of @a target.
258 : : */
259 : : static inline atomic_ptr_val_t atomic_ptr_clear(atomic_ptr_t *target)
260 : : {
261 : : return atomic_ptr_set(target, NULL);
262 : : }
263 : :
264 : : /**
265 : : *
266 : : * @brief Atomic bitwise inclusive OR.
267 : : *
268 : : * This routine atomically sets @a target to the bitwise inclusive OR of
269 : : * @a target and @a value.
270 : : *
271 : : * @note As for all atomic APIs, includes a
272 : : * full/sequentially-consistent memory barrier (where applicable).
273 : : *
274 : : * @param target Address of atomic variable.
275 : : * @param value Value to OR.
276 : : *
277 : : * @return Previous value of @a target.
278 : : */
279 : 1 : static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
280 : : {
281 : 1 : return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
282 : : }
283 : :
284 : : /**
285 : : *
286 : : * @brief Atomic bitwise exclusive OR (XOR).
287 : : *
288 : : * @note As for all atomic APIs, includes a
289 : : * full/sequentially-consistent memory barrier (where applicable).
290 : : *
291 : : * This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
292 : : * @a target and @a value.
293 : : *
294 : : * @param target Address of atomic variable.
295 : : * @param value Value to XOR
296 : : *
297 : : * @return Previous value of @a target.
298 : : */
299 : : static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
300 : : {
301 : : return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
302 : : }
303 : :
304 : : /**
305 : : *
306 : : * @brief Atomic bitwise AND.
307 : : *
308 : : * This routine atomically sets @a target to the bitwise AND of @a target
309 : : * and @a value.
310 : : *
311 : : * @note As for all atomic APIs, includes a
312 : : * full/sequentially-consistent memory barrier (where applicable).
313 : : *
314 : : * @param target Address of atomic variable.
315 : : * @param value Value to AND.
316 : : *
317 : : * @return Previous value of @a target.
318 : : */
319 : 1 : static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
320 : : {
321 : 1 : return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
322 : : }
323 : :
324 : : /**
325 : : *
326 : : * @brief Atomic bitwise NAND.
327 : : *
328 : : * This routine atomically sets @a target to the bitwise NAND of @a target
329 : : * and @a value. (This operation is equivalent to target = ~(target & value).)
330 : : *
331 : : * @note As for all atomic APIs, includes a
332 : : * full/sequentially-consistent memory barrier (where applicable).
333 : : *
334 : : * @param target Address of atomic variable.
335 : : * @param value Value to NAND.
336 : : *
337 : : * @return Previous value of @a target.
338 : : */
339 : : static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
340 : : {
341 : : return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
342 : : }
343 : :
344 : : /** @} */
345 : :
346 : :
347 : : #ifdef __cplusplus
348 : : }
349 : : #endif
350 : :
351 : : #endif /* ZEPHYR_INCLUDE_SYS_ATOMIC_BUILTIN_H_ */
|