• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Atomic Operation
2
3
4## Basic Concepts
5
6In 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 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.
7
8Although you can enable or disable interrupts to ensure that the multi-task execution results meet expectations, the system performance is affected.
9
10The 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.
11
12## Working Principles
13
14The OpenHarmony system has encapsulated the  **LDREX**  and  **STREX**  in the ARMv6 architecture to provide a set of atomic operation APIs.
15
16-   LDREX Rx, \[Ry\]
17
18    Reads the value in the memory and marks the exclusive access to the memory segment.
19
20    -   Reads the 4-byte memory data pointed by the register  **Ry**  and saves the data to the  **Rx**  register.
21    -   Adds an exclusive access flag to the memory area pointed by  **Ry**.
22
23-   STREX Rf, Rx, \[Ry\]
24
25    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.
26
27    -   If there is an exclusive access flag, the system:
28        -   Updates the  **Rx**  register value to the memory pointed to by the  **Ry**  register.
29        -   Sets the  **Rf**  register to  **0**.
30
31    -   If there is no exclusive access flag:
32        -   The memory is not updated.
33        -   The system sets the  **Rf**  register to  **1**.
34
35
36-   Flag register
37    -   If the flag register is  **0**, the system exits the loop and the atomic operation is complete.
38    -   If the flag register is  **1**, the system continues the loop and performs the atomic operation again.
39
40
41## Development Guidelines
42
43### Available APIs
44
45The 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.
46
47**Table  1**  Atomic operation APIs
48
49<a name="table29217519171"></a>
50<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>Function</p>
51</th>
52<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>
53</th>
54<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>
55</th>
56</tr>
57</thead>
58<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>
59</td>
60<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>
61</td>
62<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>
63</td>
64</tr>
65<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>
66</td>
67<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>
68</td>
69</tr>
70<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>
71</td>
72<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>
73</td>
74<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>
75</td>
76</tr>
77<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>
78</td>
79<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>
80</td>
81</tr>
82<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>
83</td>
84<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>
85</td>
86<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>
87</td>
88</tr>
89<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>
90</td>
91<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>
92</td>
93</tr>
94<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>
95</td>
96<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>
97</td>
98</tr>
99<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>
100</td>
101<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>
102</td>
103</tr>
104<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>
105</td>
106<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>
107</td>
108</tr>
109<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>
110</td>
111<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>
112</td>
113</tr>
114<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>
115</td>
116<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>
117</td>
118<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>
119</td>
120</tr>
121<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>
122</td>
123<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>
124</td>
125</tr>
126<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>
127</td>
128<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>
129</td>
130</tr>
131<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>
132</td>
133<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>
134</td>
135</tr>
136<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>
137</td>
138<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>
139</td>
140</tr>
141<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>
142</td>
143<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>
144</td>
145</tr>
146<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>
147</td>
148<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>
149</td>
150<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>
151</td>
152</tr>
153<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>
154</td>
155<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>
156</td>
157</tr>
158<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>
159</td>
160<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>
161</td>
162</tr>
163<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>
164</td>
165<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>
166</td>
167</tr>
168<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>
169</td>
170<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>
171</td>
172<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>
173</td>
174</tr>
175<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>
176</td>
177<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>
178</td>
179</tr>
180<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>
181</td>
182<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>
183</td>
184</tr>
185<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>
186</td>
187<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>
188</td>
189</tr>
190</tbody>
191</table>
192
193### How to Develop
194
195When multiple tasks perform addition, subtraction, and swap operations on the same memory data, use atomic operations to ensure predictability of results.
196
197>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
198>Atomic operation APIs support only integer data.
199
200### Development Example<a name="section8538651511"></a>
201
202Example Description
203
204Call the atomic operation APIs and observe the result.
205
2061.  Create two tasks.
207    -   Task 1: Call  **LOS\_AtomicInc**  to add the global variables 100 times.
208    -   Task 2: Call  **LOS\_AtomicDec**  to subtract the global variables 100 times.
209
2102.  After the subtasks are complete, print the values of the global variables in the main task.
211
212**Sample Code**
213
214The sample code is as follows:
215
216```
217#include "los_hwi.h"
218#include "los_atomic.h"
219#include "los_task.h"
220
221UINT32 g_testTaskId01;
222UINT32 g_testTaskId02;
223Atomic g_sum;
224Atomic g_count;
225
226UINT32 Example_Atomic01(VOID)
227{
228    int i = 0;
229    for(i = 0; i < 100; ++i) {
230        LOS_AtomicInc(&g_sum);
231    }
232
233    LOS_AtomicInc(&g_count);
234    return LOS_OK;
235}
236
237UINT32 Example_Atomic02(VOID)
238{
239    int i = 0;
240    for(i = 0; i < 100; ++i) {
241        LOS_AtomicDec(&g_sum);
242    }
243
244    LOS_AtomicInc(&g_count);
245    return LOS_OK;
246}
247
248UINT32 Example_AtomicTaskEntry(VOID)
249{
250    TSK_INIT_PARAM_S stTask1={0};
251    stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Atomic01;
252    stTask1.pcName       = "TestAtomicTsk1";
253    stTask1.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
254    stTask1.usTaskPrio   = 4;
255    stTask1.uwResved     = LOS_TASK_STATUS_DETACHED;
256
257    TSK_INIT_PARAM_S stTask2={0};
258    stTask2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Atomic02;
259    stTask2.pcName       = "TestAtomicTsk2";
260    stTask2.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
261    stTask2.usTaskPrio   = 4;
262    stTask2.uwResved     = LOS_TASK_STATUS_DETACHED;
263
264    LOS_TaskLock();
265    LOS_TaskCreate(&g_testTaskId01, &stTask1);
266    LOS_TaskCreate(&g_testTaskId02, &stTask2);
267    LOS_TaskUnlock();
268
269    while(LOS_AtomicRead(&g_count) != 2);
270    PRINTK("g_sum = %d\n", g_sum);
271
272    return LOS_OK;
273}
274```
275
276**Verification**
277
278```
279g_sum = 0
280```
281
282