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