GCC Code Coverage Report


Directory: main/
File: zephyr/atomic.h
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 11 11 100.0%
Functions: 3 3 100.0%
Branches: 0 2 0.0%

Line Branch Exec Source
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_H_
10 #define ZEPHYR_INCLUDE_SYS_ATOMIC_H_
11
12 #include <stdbool.h>
13 #ifdef BLUERETRO
14 #include "types.h"
15 #else
16 #include <toolchain.h>
17
18 #include <zephyr/types.h>
19 #endif /* BLUERETRO */
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 #ifdef BLUERETRO
26 typedef int32_t atomic_t;
27 #else
28 #error atomic int
29 typedef int atomic_t;
30 #endif /* BLUERETRO */
31 typedef atomic_t atomic_val_t;
32
33 /**
34 * @defgroup atomic_apis Atomic Services APIs
35 * @ingroup kernel_apis
36 * @{
37 */
38
39 /**
40 * @brief Atomic compare-and-set.
41 *
42 * This routine performs an atomic compare-and-set on @a target. If the current
43 * value of @a target equals @a old_value, @a target is set to @a new_value.
44 * If the current value of @a target does not equal @a old_value, @a target
45 * is left unchanged.
46 *
47 * @param target Address of atomic variable.
48 * @param old_value Original value to compare against.
49 * @param new_value New value to store.
50 * @return true if @a new_value is written, false otherwise.
51 */
52 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
53 static inline bool atomic_cas(atomic_t *target, atomic_val_t old_value,
54 atomic_val_t new_value)
55 {
56 return __atomic_compare_exchange_n(target, &old_value, new_value,
57 0, __ATOMIC_SEQ_CST,
58 __ATOMIC_SEQ_CST);
59 }
60 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
61 __syscall int atomic_cas(atomic_t *target, atomic_val_t old_value,
62 atomic_val_t new_value);
63
64 #else
65 extern int atomic_cas(atomic_t *target, atomic_val_t old_value,
66 atomic_val_t new_value);
67 #endif
68
69 /**
70 *
71 * @brief Atomic addition.
72 *
73 * This routine performs an atomic addition on @a target.
74 *
75 * @param target Address of atomic variable.
76 * @param value Value to add.
77 *
78 * @return Previous value of @a target.
79 */
80 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
81 static inline atomic_val_t atomic_add(atomic_t *target, atomic_val_t value)
82 {
83 return __atomic_fetch_add(target, value, __ATOMIC_SEQ_CST);
84 }
85 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
86 __syscall atomic_val_t atomic_add(atomic_t *target, atomic_val_t value);
87 #else
88 extern atomic_val_t atomic_add(atomic_t *target, atomic_val_t value);
89 #endif
90
91 /**
92 *
93 * @brief Atomic subtraction.
94 *
95 * This routine performs an atomic subtraction on @a target.
96 *
97 * @param target Address of atomic variable.
98 * @param value Value to subtract.
99 *
100 * @return Previous value of @a target.
101 */
102 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
103 static inline atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value)
104 {
105 return __atomic_fetch_sub(target, value, __ATOMIC_SEQ_CST);
106 }
107 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
108 __syscall atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value);
109 #else
110 extern atomic_val_t atomic_sub(atomic_t *target, atomic_val_t value);
111 #endif
112
113 /**
114 *
115 * @brief Atomic increment.
116 *
117 * This routine performs an atomic increment by 1 on @a target.
118 *
119 * @param target Address of atomic variable.
120 *
121 * @return Previous value of @a target.
122 */
123 #if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || defined (CONFIG_ATOMIC_OPERATIONS_C)
124 static inline atomic_val_t atomic_inc(atomic_t *target)
125 {
126 return atomic_add(target, 1);
127 }
128 #else
129 extern atomic_val_t atomic_inc(atomic_t *target);
130 #endif
131
132 /**
133 *
134 * @brief Atomic decrement.
135 *
136 * This routine performs an atomic decrement by 1 on @a target.
137 *
138 * @param target Address of atomic variable.
139 *
140 * @return Previous value of @a target.
141 */
142 #if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || defined (CONFIG_ATOMIC_OPERATIONS_C)
143 static inline atomic_val_t atomic_dec(atomic_t *target)
144 {
145 return atomic_sub(target, 1);
146 }
147 #else
148 extern atomic_val_t atomic_dec(atomic_t *target);
149 #endif
150
151 /**
152 *
153 * @brief Atomic get.
154 *
155 * This routine performs an atomic read on @a target.
156 *
157 * @param target Address of atomic variable.
158 *
159 * @return Value of @a target.
160 */
161 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
162 static inline atomic_val_t atomic_get(const atomic_t *target)
163 {
164 return __atomic_load_n(target, __ATOMIC_SEQ_CST);
165 }
166 #else
167 extern atomic_val_t atomic_get(const atomic_t *target);
168 #endif
169
170 /**
171 *
172 * @brief Atomic get-and-set.
173 *
174 * This routine atomically sets @a target to @a value and returns
175 * the previous value of @a target.
176 *
177 * @param target Address of atomic variable.
178 * @param value Value to write to @a target.
179 *
180 * @return Previous value of @a target.
181 */
182 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
183 static inline atomic_val_t atomic_set(atomic_t *target, atomic_val_t value)
184 {
185 /* This builtin, as described by Intel, is not a traditional
186 * test-and-set operation, but rather an atomic exchange operation. It
187 * writes value into *ptr, and returns the previous contents of *ptr.
188 */
189 return __atomic_exchange_n(target, value, __ATOMIC_SEQ_CST);
190 }
191 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
192 __syscall atomic_val_t atomic_set(atomic_t *target, atomic_val_t value);
193 #else
194 extern atomic_val_t atomic_set(atomic_t *target, atomic_val_t value);
195 #endif
196
197 /**
198 *
199 * @brief Atomic clear.
200 *
201 * This routine atomically sets @a target to zero and returns its previous
202 * value. (Hence, it is equivalent to atomic_set(target, 0).)
203 *
204 * @param target Address of atomic variable.
205 *
206 * @return Previous value of @a target.
207 */
208 #if defined(CONFIG_ATOMIC_OPERATIONS_BUILTIN) || defined (CONFIG_ATOMIC_OPERATIONS_C)
209 static inline atomic_val_t atomic_clear(atomic_t *target)
210 {
211 return atomic_set(target, 0);
212 }
213 #else
214 extern atomic_val_t atomic_clear(atomic_t *target);
215 #endif
216
217 /**
218 *
219 * @brief Atomic bitwise inclusive OR.
220 *
221 * This routine atomically sets @a target to the bitwise inclusive OR of
222 * @a target and @a value.
223 *
224 * @param target Address of atomic variable.
225 * @param value Value to OR.
226 *
227 * @return Previous value of @a target.
228 */
229 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
230 static inline atomic_val_t atomic_or(atomic_t *target, atomic_val_t value)
231 {
232 return __atomic_fetch_or(target, value, __ATOMIC_SEQ_CST);
233 }
234 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
235 __syscall atomic_val_t atomic_or(atomic_t *target, atomic_val_t value);
236
237 #else
238 extern atomic_val_t atomic_or(atomic_t *target, atomic_val_t value);
239 #endif
240
241 /**
242 *
243 * @brief Atomic bitwise exclusive OR (XOR).
244 *
245 * This routine atomically sets @a target to the bitwise exclusive OR (XOR) of
246 * @a target and @a value.
247 *
248 * @param target Address of atomic variable.
249 * @param value Value to XOR
250 *
251 * @return Previous value of @a target.
252 */
253 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
254 static inline atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value)
255 {
256 return __atomic_fetch_xor(target, value, __ATOMIC_SEQ_CST);
257 }
258 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
259 __syscall atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value);
260 #else
261 extern atomic_val_t atomic_xor(atomic_t *target, atomic_val_t value);
262 #endif
263
264 /**
265 *
266 * @brief Atomic bitwise AND.
267 *
268 * This routine atomically sets @a target to the bitwise AND of @a target
269 * and @a value.
270 *
271 * @param target Address of atomic variable.
272 * @param value Value to AND.
273 *
274 * @return Previous value of @a target.
275 */
276 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
277 static inline atomic_val_t atomic_and(atomic_t *target, atomic_val_t value)
278 {
279 return __atomic_fetch_and(target, value, __ATOMIC_SEQ_CST);
280 }
281 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
282 __syscall atomic_val_t atomic_and(atomic_t *target, atomic_val_t value);
283 #else
284 extern atomic_val_t atomic_and(atomic_t *target, atomic_val_t value);
285 #endif
286
287 /**
288 *
289 * @brief Atomic bitwise NAND.
290 *
291 * This routine atomically sets @a target to the bitwise NAND of @a target
292 * and @a value. (This operation is equivalent to target = ~(target & value).)
293 *
294 * @param target Address of atomic variable.
295 * @param value Value to NAND.
296 *
297 * @return Previous value of @a target.
298 */
299 #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN
300 static inline atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value)
301 {
302 return __atomic_fetch_nand(target, value, __ATOMIC_SEQ_CST);
303 }
304 #elif defined(CONFIG_ATOMIC_OPERATIONS_C)
305 __syscall atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value);
306 #else
307 extern atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value);
308 #endif
309
310
311 /**
312 * @brief Initialize an atomic variable.
313 *
314 * This macro can be used to initialize an atomic variable. For example,
315 * @code atomic_t my_var = ATOMIC_INIT(75); @endcode
316 *
317 * @param i Value to assign to atomic variable.
318 */
319 #define ATOMIC_INIT(i) (i)
320
321 /**
322 * @cond INTERNAL_HIDDEN
323 */
324
325 #define ATOMIC_BITS (sizeof(atomic_val_t) * 8)
326 #define ATOMIC_MASK(bit) (1 << ((u32_t)(bit) & (ATOMIC_BITS - 1)))
327 #define ATOMIC_ELEM(addr, bit) ((addr) + ((bit) / ATOMIC_BITS))
328
329 /**
330 * INTERNAL_HIDDEN @endcond
331 */
332
333 /**
334 * @brief Define an array of atomic variables.
335 *
336 * This macro defines an array of atomic variables containing at least
337 * @a num_bits bits.
338 *
339 * @note
340 * If used from file scope, the bits of the array are initialized to zero;
341 * if used from within a function, the bits are left uninitialized.
342 *
343 * @param name Name of array of atomic variables.
344 * @param num_bits Number of bits needed.
345 */
346 #define ATOMIC_DEFINE(name, num_bits) \
347 atomic_t name[1 + ((num_bits) - 1) / ATOMIC_BITS]
348
349 /**
350 * @brief Atomically test a bit.
351 *
352 * This routine tests whether bit number @a bit of @a target is set or not.
353 * The target may be a single atomic variable or an array of them.
354 *
355 * @param target Address of atomic variable or array.
356 * @param bit Bit number (starting from 0).
357 *
358 * @return true if the bit was set, false if it wasn't.
359 */
360 14473 static inline bool atomic_test_bit(const atomic_t *target, int bit)
361 {
362 14473 atomic_val_t val = atomic_get(ATOMIC_ELEM(target, bit));
363
364
0/2
✗ Branch 0 (5→6) not taken.
✗ Branch 1 (5→16) not taken.
12635 return (1 & (val >> (bit & (ATOMIC_BITS - 1)))) != 0;
365 }
366
367 /**
368 * @brief Atomically test and clear a bit.
369 *
370 * Atomically clear bit number @a bit of @a target and return its old value.
371 * The target may be a single atomic variable or an array of them.
372 *
373 * @param target Address of atomic variable or array.
374 * @param bit Bit number (starting from 0).
375 *
376 * @return true if the bit was set, false if it wasn't.
377 */
378 static inline bool atomic_test_and_clear_bit(atomic_t *target, int bit)
379 {
380 atomic_val_t mask = ATOMIC_MASK(bit);
381 atomic_val_t old;
382
383 old = atomic_and(ATOMIC_ELEM(target, bit), ~mask);
384
385 return (old & mask) != 0;
386 }
387
388 /**
389 * @brief Atomically set a bit.
390 *
391 * Atomically set bit number @a bit of @a target and return its old value.
392 * The target may be a single atomic variable or an array of them.
393 *
394 * @param target Address of atomic variable or array.
395 * @param bit Bit number (starting from 0).
396 *
397 * @return true if the bit was set, false if it wasn't.
398 */
399 static inline bool atomic_test_and_set_bit(atomic_t *target, int bit)
400 {
401 atomic_val_t mask = ATOMIC_MASK(bit);
402 atomic_val_t old;
403
404 old = atomic_or(ATOMIC_ELEM(target, bit), mask);
405
406 return (old & mask) != 0;
407 }
408
409 /**
410 * @brief Atomically clear a bit.
411 *
412 * Atomically clear bit number @a bit of @a target.
413 * The target may be a single atomic variable or an array of them.
414 *
415 * @param target Address of atomic variable or array.
416 * @param bit Bit number (starting from 0).
417 *
418 * @return N/A
419 */
420 718 static inline void atomic_clear_bit(atomic_t *target, int bit)
421 {
422 718 atomic_val_t mask = ATOMIC_MASK(bit);
423
424 718 (void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
425 718 }
426
427 /**
428 * @brief Atomically set a bit.
429 *
430 * Atomically set bit number @a bit of @a target.
431 * The target may be a single atomic variable or an array of them.
432 *
433 * @param target Address of atomic variable or array.
434 * @param bit Bit number (starting from 0).
435 *
436 * @return N/A
437 */
438 287 static inline void atomic_set_bit(atomic_t *target, int bit)
439 {
440 287 atomic_val_t mask = ATOMIC_MASK(bit);
441
442 287 (void)atomic_or(ATOMIC_ELEM(target, bit), mask);
443 287 }
444
445 /**
446 * @brief Atomically set a bit to a given value.
447 *
448 * Atomically set bit number @a bit of @a target to value @a val.
449 * The target may be a single atomic variable or an array of them.
450 *
451 * @param target Address of atomic variable or array.
452 * @param bit Bit number (starting from 0).
453 * @param val true for 1, false for 0.
454 *
455 * @return N/A
456 */
457 static inline void atomic_set_bit_to(atomic_t *target, int bit, bool val)
458 {
459 atomic_val_t mask = ATOMIC_MASK(bit);
460
461 if (val) {
462 (void)atomic_or(ATOMIC_ELEM(target, bit), mask);
463 } else {
464 (void)atomic_and(ATOMIC_ELEM(target, bit), ~mask);
465 }
466 }
467
468 #ifdef CONFIG_ATOMIC_OPERATIONS_C
469 #include <syscalls/atomic.h>
470 #endif
471 /**
472 * @}
473 */
474
475 #ifdef __cplusplus
476 }
477 #endif
478
479 #endif /* ZEPHYR_INCLUDE_SYS_ATOMIC_H_ */
480