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> **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