• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Atomic Operation<a name="EN-US_TOPIC_0000001078876272"></a>
2
3-   [Basic Concepts](#section1792118384594)
4-   [Working Principles](#section1786635117596)
5-   [Development Guidelines](#section2911115308)
6    -   [Available APIs](#section335914201010)
7    -   [How to Develop](#section12207371304)
8    -   [Development Example](#section8538651511)
9
10
11## Basic Concepts<a name="section1792118384594"></a>
12
13In an OS that supports multiple tasks, modifying data in a memory area requires three steps: read data, modify data, and write data. However, data in a same memory area may be simultaneously accessed by multiple tasks. If the data modification is interrupted by another task, the execution result of the operation is unpredictable.
14
15Although you can enable or disable interrupts to ensure that the multi-task execution results meet expectation, the system performance is affected.
16
17The ARMv6 architecture has introduced the  **LDREX**  and  **STREX**  instructions to support more discreet non-blocking synchronization of the shared memory. The atomic operations implemented thereby can ensure that the "read-modify-write" operations on the same data will not be interrupted, that is, the operation atomicity is ensured.
18
19## Working Principles<a name="section1786635117596"></a>
20
21The OpenHarmony system has encapsulated the  **LDREX**  and  **STREX**  in the ARMv6 architecture to provide a set of atomic operation APIs.
22
23-   LDREX Rx, \[Ry\]
24
25    Reads the value in the memory and marks the exclusive access to the memory segment.
26
27    -   Reads the 4-byte memory data pointed by the register  **Ry**  and saves the data to the  **Rx**  register.
28    -   Adds an exclusive access flag to the memory area pointed by  **Ry**.
29
30-   STREX Rf, Rx, \[Ry\]
31
32    Checks whether the memory has an exclusive access flag. If yes, the system updates the memory value and clears the flag. If no, the memory is not updated.
33
34    -   If there is an exclusive access flag, the system:
35        -   Updates the  **Rx**  register value to the memory pointed to by the  **Ry**  register.
36        -   Sets the  **Rf**  register to  **0**.
37
38    -   If there is no exclusive access flag:
39        -   The memory is not updated.
40        -   The system sets the  **Rf**  register to  **1**.
41
42
43-   Flag register
44    -   If the flag register is  **0**, the system exits the loop and the atomic operation is complete.
45    -   If the flag register is  **1**, the system continues the loop and performs the atomic operation again.
46
47
48## Development Guidelines<a name="section2911115308"></a>
49
50### Available APIs<a name="section335914201010"></a>
51
52The following table describes the APIs available for the OpenHarmony LiteOS-A kernel atomic operation module. For more details about the APIs, see the API reference.
53
54**Table  1**  Atomic operation APIs
55
56<a name="table29217519171"></a>
57<table><thead align="left"><tr id="row79375119172"><th class="cellrowborder" valign="top" width="21.21212121212121%" id="mcps1.2.4.1.1"><p id="p159375113174"><a name="p159375113174"></a><a name="p159375113174"></a>Category</p>
58</th>
59<th class="cellrowborder" valign="top" width="33.39333933393339%" id="mcps1.2.4.1.2"><p id="p199385118173"><a name="p199385118173"></a><a name="p199385118173"></a>API</p>
60</th>
61<th class="cellrowborder" valign="top" width="45.3945394539454%" id="mcps1.2.4.1.3"><p id="p18937511175"><a name="p18937511175"></a><a name="p18937511175"></a>Description</p>
62</th>
63</tr>
64</thead>
65<tbody><tr id="row159315151712"><td class="cellrowborder" rowspan="2" valign="top" width="21.21212121212121%" headers="mcps1.2.4.1.1 "><p id="p593135115176"><a name="p593135115176"></a><a name="p593135115176"></a>Read</p>
66</td>
67<td class="cellrowborder" valign="top" width="33.39333933393339%" headers="mcps1.2.4.1.2 "><p id="p1193651181714"><a name="p1193651181714"></a><a name="p1193651181714"></a>LOS_AtomicRead</p>
68</td>
69<td class="cellrowborder" valign="top" width="45.3945394539454%" headers="mcps1.2.4.1.3 "><p id="p09316512178"><a name="p09316512178"></a><a name="p09316512178"></a>Reads 32-bit atomic data.</p>
70</td>
71</tr>
72<tr id="row1493151161719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p119395111718"><a name="p119395111718"></a><a name="p119395111718"></a>LOS_Atomic64Read</p>
73</td>
74<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p49311514178"><a name="p49311514178"></a><a name="p49311514178"></a>Reads 64-bit atomic data.</p>
75</td>
76</tr>
77<tr id="row69365111712"><td class="cellrowborder" rowspan="2" valign="top" width="21.21212121212121%" headers="mcps1.2.4.1.1 "><p id="p199355111175"><a name="p199355111175"></a><a name="p199355111175"></a>Write</p>
78</td>
79<td class="cellrowborder" valign="top" width="33.39333933393339%" headers="mcps1.2.4.1.2 "><p id="p1693175191714"><a name="p1693175191714"></a><a name="p1693175191714"></a>LOS_AtomicSet</p>
80</td>
81<td class="cellrowborder" valign="top" width="45.3945394539454%" headers="mcps1.2.4.1.3 "><p id="p129320516173"><a name="p129320516173"></a><a name="p129320516173"></a>Sets 32-bit atomic data.</p>
82</td>
83</tr>
84<tr id="row1593651111718"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p7944510176"><a name="p7944510176"></a><a name="p7944510176"></a>LOS_Atomic64Set</p>
85</td>
86<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p294115191713"><a name="p294115191713"></a><a name="p294115191713"></a>Sets 64-bit atomic data.</p>
87</td>
88</tr>
89<tr id="row149495114177"><td class="cellrowborder" rowspan="6" valign="top" width="21.21212121212121%" headers="mcps1.2.4.1.1 "><p id="p1394165151718"><a name="p1394165151718"></a><a name="p1394165151718"></a>Add</p>
90</td>
91<td class="cellrowborder" valign="top" width="33.39333933393339%" headers="mcps1.2.4.1.2 "><p id="p494115112179"><a name="p494115112179"></a><a name="p494115112179"></a>LOS_AtomicAdd</p>
92</td>
93<td class="cellrowborder" valign="top" width="45.3945394539454%" headers="mcps1.2.4.1.3 "><p id="p1694155120174"><a name="p1694155120174"></a><a name="p1694155120174"></a>Adds 32-bit atomic data.</p>
94</td>
95</tr>
96<tr id="row394651101719"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p179435113171"><a name="p179435113171"></a><a name="p179435113171"></a>LOS_Atomic64Add</p>
97</td>
98<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p594851181718"><a name="p594851181718"></a><a name="p594851181718"></a>Adds 64-bit atomic data.</p>
99</td>
100</tr>
101<tr id="row294185110171"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1834102212615"><a name="p1834102212615"></a><a name="p1834102212615"></a>LOS_AtomicInc</p>
102</td>
103<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p129413519173"><a name="p129413519173"></a><a name="p129413519173"></a>Adds 1 to 32-bit atomic data.</p>
104</td>
105</tr>
106<tr id="row1894175101713"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1981302213264"><a name="p1981302213264"></a><a name="p1981302213264"></a>LOS_Atomic64Inc</p>
107</td>
108<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p167671640113316"><a name="p167671640113316"></a><a name="p167671640113316"></a>Adds 1 to 64-bit atomic data.</p>
109</td>
110</tr>
111<tr id="row12946512178"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1994051181716"><a name="p1994051181716"></a><a name="p1994051181716"></a>LOS_AtomicIncRet</p>
112</td>
113<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p59414511172"><a name="p59414511172"></a><a name="p59414511172"></a>Adds 1 to 32-bit atomic data and returns the data.</p>
114</td>
115</tr>
116<tr id="row1994551101712"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p129414519173"><a name="p129414519173"></a><a name="p129414519173"></a>LOS_Atomic64IncRet</p>
117</td>
118<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1194951111713"><a name="p1194951111713"></a><a name="p1194951111713"></a>Adds 1 to 64-bit atomic data and returns the data.</p>
119</td>
120</tr>
121<tr id="row1794451121719"><td class="cellrowborder" rowspan="6" valign="top" width="21.21212121212121%" headers="mcps1.2.4.1.1 "><p id="p179412517173"><a name="p179412517173"></a><a name="p179412517173"></a>Subtract</p>
122</td>
123<td class="cellrowborder" valign="top" width="33.39333933393339%" headers="mcps1.2.4.1.2 "><p id="p89495115176"><a name="p89495115176"></a><a name="p89495115176"></a>LOS_AtomicSub</p>
124</td>
125<td class="cellrowborder" valign="top" width="45.3945394539454%" headers="mcps1.2.4.1.3 "><p id="p18220416345"><a name="p18220416345"></a><a name="p18220416345"></a>Performs subtraction on 32-bit atomic data.</p>
126</td>
127</tr>
128<tr id="row139485131718"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1894195116176"><a name="p1894195116176"></a><a name="p1894195116176"></a>LOS_Atomic64Sub</p>
129</td>
130<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p20822124173415"><a name="p20822124173415"></a><a name="p20822124173415"></a>Performs subtraction on 64-bit atomic data.</p>
131</td>
132</tr>
133<tr id="row209505110175"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p7951051141713"><a name="p7951051141713"></a><a name="p7951051141713"></a>LOS_AtomicDec</p>
134</td>
135<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p382234117340"><a name="p382234117340"></a><a name="p382234117340"></a>Subtracts 1 from 32-bit atomic data.</p>
136</td>
137</tr>
138<tr id="row995151171711"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p395151131715"><a name="p395151131715"></a><a name="p395151131715"></a>LOS_Atomic64Dec</p>
139</td>
140<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1982244117340"><a name="p1982244117340"></a><a name="p1982244117340"></a>Subtracts 1 from 64-bit atomic data.</p>
141</td>
142</tr>
143<tr id="row895155117179"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p395155151719"><a name="p395155151719"></a><a name="p395155151719"></a>LOS_AtomicDecRet</p>
144</td>
145<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p198222414349"><a name="p198222414349"></a><a name="p198222414349"></a>Subtracts 1 from 32-bit atomic data and returns the result.</p>
146</td>
147</tr>
148<tr id="row59511518170"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1495125119175"><a name="p1495125119175"></a><a name="p1495125119175"></a>LOS_Atomic64DecRet</p>
149</td>
150<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p198221841103419"><a name="p198221841103419"></a><a name="p198221841103419"></a>Subtracts 1 from 64-bit atomic data and returns the result.</p>
151</td>
152</tr>
153<tr id="row159575131714"><td class="cellrowborder" rowspan="4" valign="top" width="21.21212121212121%" headers="mcps1.2.4.1.1 "><p id="p159585110177"><a name="p159585110177"></a><a name="p159585110177"></a>Swap</p>
154</td>
155<td class="cellrowborder" valign="top" width="33.39333933393339%" headers="mcps1.2.4.1.2 "><p id="p29515114174"><a name="p29515114174"></a><a name="p29515114174"></a>LOS_AtomicXchgByte</p>
156</td>
157<td class="cellrowborder" valign="top" width="45.3945394539454%" headers="mcps1.2.4.1.3 "><p id="p6956510177"><a name="p6956510177"></a><a name="p6956510177"></a>Swaps 8-bit memory data.</p>
158</td>
159</tr>
160<tr id="row14951451111710"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p8952514173"><a name="p8952514173"></a><a name="p8952514173"></a>LOS_AtomicXchg16bits</p>
161</td>
162<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p12334173143919"><a name="p12334173143919"></a><a name="p12334173143919"></a>Swaps 16-bit memory data.</p>
163</td>
164</tr>
165<tr id="row595251131716"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1495145117171"><a name="p1495145117171"></a><a name="p1495145117171"></a>LOS_AtomicXchg32bits</p>
166</td>
167<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p9951513173"><a name="p9951513173"></a><a name="p9951513173"></a>Swaps 32-bit memory data.</p>
168</td>
169</tr>
170<tr id="row195165131718"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p18951151141717"><a name="p18951151141717"></a><a name="p18951151141717"></a>LOS_AtomicXchg64bits</p>
171</td>
172<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p169685115172"><a name="p169685115172"></a><a name="p169685115172"></a>Swaps 64-bit memory data.</p>
173</td>
174</tr>
175<tr id="row149616511175"><td class="cellrowborder" rowspan="4" valign="top" width="21.21212121212121%" headers="mcps1.2.4.1.1 "><p id="p49615120172"><a name="p49615120172"></a><a name="p49615120172"></a>Compare and swap</p>
176</td>
177<td class="cellrowborder" valign="top" width="33.39333933393339%" headers="mcps1.2.4.1.2 "><p id="p129605112171"><a name="p129605112171"></a><a name="p129605112171"></a>LOS_AtomicCmpXchgByte</p>
178</td>
179<td class="cellrowborder" valign="top" width="45.3945394539454%" headers="mcps1.2.4.1.3 "><p id="p6965510178"><a name="p6965510178"></a><a name="p6965510178"></a>Compares and swaps 8-bit memory data.</p>
180</td>
181</tr>
182<tr id="row99605171713"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p109675131711"><a name="p109675131711"></a><a name="p109675131711"></a>LOS_AtomicCmpXchg16bits</p>
183</td>
184<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p17961951191719"><a name="p17961951191719"></a><a name="p17961951191719"></a>Compares and swaps 16-bit memory data.</p>
185</td>
186</tr>
187<tr id="row169614513177"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p49645115172"><a name="p49645115172"></a><a name="p49645115172"></a>LOS_AtomicCmpXchg32bits</p>
188</td>
189<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p129611512175"><a name="p129611512175"></a><a name="p129611512175"></a>Compares and swaps 32-bit memory data.</p>
190</td>
191</tr>
192<tr id="row696175110179"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p16961051161715"><a name="p16961051161715"></a><a name="p16961051161715"></a>LOS_AtomicCmpXchg64bits</p>
193</td>
194<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1296205118179"><a name="p1296205118179"></a><a name="p1296205118179"></a>Compares and swaps 64-bit memory data.</p>
195</td>
196</tr>
197</tbody>
198</table>
199
200### How to Develop<a name="section12207371304"></a>
201
202When multiple tasks perform addition, subtraction, and swap operations on the same memory data, use atomic operations to ensure predictability of results.
203
204>![](../public_sys-resources/icon-note.gif) **NOTE:**
205>Atomic operation APIs support only integer data.
206
207### Development Example<a name="section8538651511"></a>
208
209Example Description
210
211Call the atomic operation APIs and observe the result.
212
2131.  Create two tasks.
214    -   Task 1: Call  **LOS\_AtomicInc**  to add the global variables 100 times.
215    -   Task 2: Call  **LOS\_AtomicDec**  to subtract the global variables 100 times.
216
2172.  After the subtasks are complete, print the values of the global variables in the main task.
218
219**Sample Code**
220
221The sample code is as follows:
222
223```
224#include "los_hwi.h"
225#include "los_atomic.h"
226#include "los_task.h"
227
228UINT32 g_testTaskId01;
229UINT32 g_testTaskId02;
230Atomic g_sum;
231Atomic g_count;
232
233UINT32 Example_Atomic01(VOID)
234{
235    int i = 0;
236    for(i = 0; i < 100; ++i) {
237        LOS_AtomicInc(&g_sum);
238    }
239
240    LOS_AtomicInc(&g_count);
241    return LOS_OK;
242}
243
244UINT32 Example_Atomic02(VOID)
245{
246    int i = 0;
247    for(i = 0; i < 100; ++i) {
248        LOS_AtomicDec(&g_sum);
249    }
250
251    LOS_AtomicInc(&g_count);
252    return LOS_OK;
253}
254
255UINT32 Example_AtomicTaskEntry(VOID)
256{
257    TSK_INIT_PARAM_S stTask1={0};
258    stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Atomic01;
259    stTask1.pcName       = "TestAtomicTsk1";
260    stTask1.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
261    stTask1.usTaskPrio   = 4;
262    stTask1.uwResved     = LOS_TASK_STATUS_DETACHED;
263
264    TSK_INIT_PARAM_S stTask2={0};
265    stTask2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Atomic02;
266    stTask2.pcName       = "TestAtomicTsk2";
267    stTask2.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
268    stTask2.usTaskPrio   = 4;
269    stTask2.uwResved     = LOS_TASK_STATUS_DETACHED;
270
271    LOS_TaskLock();
272    LOS_TaskCreate(&g_testTaskId01, &stTask1);
273    LOS_TaskCreate(&g_testTaskId02, &stTask2);
274    LOS_TaskUnlock();
275
276    while(LOS_AtomicRead(&g_count) != 2);
277    PRINTK("g_sum = %d\n", g_sum);
278
279    return LOS_OK;
280}
281```
282
283**Verification**
284
285```
286g_sum = 0
287```
288
289