LCOV - code coverage report
Current view: top level - zephyr/sys - atomic.h Coverage Total Hit
Test: new.info Lines: 96.3 % 27 26
Test Date: 2025-09-05 16:43:28

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

Generated by: LCOV version 2.0-1