1.. _atomic_v2: 2 3Atomic Services 4############### 5 6An :dfn:`atomic variable` is one that can be read and modified 7by threads and ISRs in an uninterruptible manner. It is a 32-bit variable on 832-bit machines and a 64-bit variable on 64-bit machines. 9 10.. contents:: 11 :local: 12 :depth: 2 13 14Concepts 15******** 16 17Any number of atomic variables can be defined (limited only by available RAM). 18 19Using the kernel's atomic APIs to manipulate an atomic variable 20guarantees that the desired operation occurs correctly, 21even if higher priority contexts also manipulate the same variable. 22 23The kernel also supports the atomic manipulation of a single bit 24in an array of atomic variables. 25 26Implementation 27************** 28 29Defining an Atomic Variable 30=========================== 31 32An atomic variable is defined using a variable of type :c:type:`atomic_t`. 33 34By default an atomic variable is initialized to zero. However, it can be given 35a different value using :c:macro:`ATOMIC_INIT`: 36 37.. code-block:: c 38 39 atomic_t flags = ATOMIC_INIT(0xFF); 40 41Manipulating an Atomic Variable 42=============================== 43 44An atomic variable is manipulated using the APIs listed at the end of 45this section. 46 47The following code shows how an atomic variable can be used to keep track 48of the number of times a function has been invoked. Since the count is 49incremented atomically, there is no risk that it will become corrupted 50in mid-increment if a thread calling the function is interrupted if 51by a higher priority context that also calls the routine. 52 53.. code-block:: c 54 55 atomic_t call_count; 56 57 int call_counting_routine(void) 58 { 59 /* increment invocation counter */ 60 atomic_inc(&call_count); 61 62 /* do rest of routine's processing */ 63 ... 64 } 65 66Manipulating an Array of Atomic Variables 67========================================= 68 69An array of 32-bit atomic variables can be defined in the conventional manner. 70However, you can also define an N-bit array of atomic variables using 71:c:macro:`ATOMIC_DEFINE`. 72 73A single bit in array of atomic variables can be manipulated using 74the APIs listed at the end of this section that end with :c:func:`_bit`. 75 76The following code shows how a set of 200 flag bits can be implemented 77using an array of atomic variables. 78 79.. code-block:: c 80 81 #define NUM_FLAG_BITS 200 82 83 ATOMIC_DEFINE(flag_bits, NUM_FLAG_BITS); 84 85 /* set specified flag bit & return its previous value */ 86 int set_flag_bit(int bit_position) 87 { 88 return (int)atomic_set_bit(flag_bits, bit_position); 89 } 90 91Memory Ordering 92=============== 93 94For consistency and correctness, all Zephyr atomic APIs are expected 95to include a full memory barrier (in the sense of e.g. "serializing" 96instructions on x86, "DMB" on ARM, or a "sequentially consistent" 97operation as defined by the C++ memory model) where needed by hardware 98to guarantee a reliable picture across contexts. Any 99architecture-specific implementations are responsible for ensuring 100this behavior. 101 102Suggested Uses 103************** 104 105Use an atomic variable to implement critical section processing that only 106requires the manipulation of a single 32-bit value. 107 108Use multiple atomic variables to implement critical section processing 109on a set of flag bits in a bit array longer than 32 bits. 110 111.. note:: 112 Using atomic variables is typically far more efficient than using 113 other techniques to implement critical sections such as using a mutex 114 or locking interrupts. 115 116Configuration Options 117********************* 118 119Related configuration options: 120 121* :kconfig:option:`CONFIG_ATOMIC_OPERATIONS_BUILTIN` 122* :kconfig:option:`CONFIG_ATOMIC_OPERATIONS_ARCH` 123* :kconfig:option:`CONFIG_ATOMIC_OPERATIONS_C` 124 125API Reference 126************* 127 128.. important:: 129 All atomic services APIs can be used by both threads and ISRs. 130 131.. doxygengroup:: atomic_apis 132