LCOV - code coverage report
Current view: top level - zephyr/sys - atomic.h Hit Total Coverage
Test: new.info Lines: 26 27 96.3 %
Date: 2024-12-22 00:14:23

          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 1.14