1cb0ac91aSSascha Wildner.\" Copyright (c) 2000-2001 John H. Baldwin <jhb@FreeBSD.org> 2cb0ac91aSSascha Wildner.\" All rights reserved. 3cb0ac91aSSascha Wildner.\" 4cb0ac91aSSascha Wildner.\" Redistribution and use in source and binary forms, with or without 5cb0ac91aSSascha Wildner.\" modification, are permitted provided that the following conditions 6cb0ac91aSSascha Wildner.\" are met: 7cb0ac91aSSascha Wildner.\" 1. Redistributions of source code must retain the above copyright 8cb0ac91aSSascha Wildner.\" notice, this list of conditions and the following disclaimer. 9cb0ac91aSSascha Wildner.\" 2. Redistributions in binary form must reproduce the above copyright 10cb0ac91aSSascha Wildner.\" notice, this list of conditions and the following disclaimer in the 11cb0ac91aSSascha Wildner.\" documentation and/or other materials provided with the distribution. 12cb0ac91aSSascha Wildner.\" 13cb0ac91aSSascha Wildner.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 14cb0ac91aSSascha Wildner.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15cb0ac91aSSascha Wildner.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16cb0ac91aSSascha Wildner.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 17cb0ac91aSSascha Wildner.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18cb0ac91aSSascha Wildner.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19cb0ac91aSSascha Wildner.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20cb0ac91aSSascha Wildner.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21cb0ac91aSSascha Wildner.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22cb0ac91aSSascha Wildner.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23cb0ac91aSSascha Wildner.\" 24cb0ac91aSSascha Wildner.\" $FreeBSD: src/share/man/man9/atomic.9,v 1.17 2010/05/27 13:56:27 uqs Exp $ 25cb0ac91aSSascha Wildner.\" 26cb0ac91aSSascha Wildner.Dd June 13, 2012 27cb0ac91aSSascha Wildner.Dt ATOMIC 9 28cb0ac91aSSascha Wildner.Os 29cb0ac91aSSascha Wildner.Sh NAME 30cb0ac91aSSascha Wildner.Nm atomic_add , 31cb0ac91aSSascha Wildner.Nm atomic_clear , 32cb0ac91aSSascha Wildner.Nm atomic_cmpset , 33cb0ac91aSSascha Wildner.Nm atomic_fetchadd , 34cb0ac91aSSascha Wildner.Nm atomic_load , 35cb0ac91aSSascha Wildner.Nm atomic_readandclear , 36cb0ac91aSSascha Wildner.Nm atomic_set , 37cb0ac91aSSascha Wildner.Nm atomic_subtract , 38cb0ac91aSSascha Wildner.Nm atomic_store 39cb0ac91aSSascha Wildner.Nd atomic operations 40cb0ac91aSSascha Wildner.Sh SYNOPSIS 41cb0ac91aSSascha Wildner.In sys/types.h 42cb0ac91aSSascha Wildner.In machine/atomic.h 43cb0ac91aSSascha Wildner.Ft void 44cb0ac91aSSascha Wildner.Fn atomic_add_[acq_|rel_]<type> "volatile <type> *p" "<type> v" 45cb0ac91aSSascha Wildner.Ft void 46cb0ac91aSSascha Wildner.Fn atomic_clear_[acq_|rel_]<type> "volatile <type> *p" "<type> v" 47cb0ac91aSSascha Wildner.Ft int 48cb0ac91aSSascha Wildner.Fo atomic_cmpset_[acq_|rel_]<type> 49cb0ac91aSSascha Wildner.Fa "volatile <type> *dst" 50cb0ac91aSSascha Wildner.Fa "<type> old" 51cb0ac91aSSascha Wildner.Fa "<type> new" 52cb0ac91aSSascha Wildner.Fc 53cb0ac91aSSascha Wildner.Ft <type> 54cb0ac91aSSascha Wildner.Fn atomic_fetchadd_<type> "volatile <type> *p" "<type> v" 55cb0ac91aSSascha Wildner.Ft <type> 56cb0ac91aSSascha Wildner.Fn atomic_load_acq_<type> "volatile <type> *p" 57cb0ac91aSSascha Wildner.Ft <type> 58cb0ac91aSSascha Wildner.Fn atomic_readandclear_<type> "volatile <type> *p" 59cb0ac91aSSascha Wildner.Ft void 60cb0ac91aSSascha Wildner.Fn atomic_set_[acq_|rel_]<type> "volatile <type> *p" "<type> v" 61cb0ac91aSSascha Wildner.Ft void 62cb0ac91aSSascha Wildner.Fn atomic_subtract_[acq_|rel_]<type> "volatile <type> *p" "<type> v" 63cb0ac91aSSascha Wildner.Ft void 64cb0ac91aSSascha Wildner.Fn atomic_store_rel_<type> "volatile <type> *p" "<type> v" 65cb0ac91aSSascha Wildner.Sh DESCRIPTION 66cb0ac91aSSascha WildnerEach of the atomic operations is guaranteed to be atomic in the presence of 67cb0ac91aSSascha Wildnerinterrupts. 68cb0ac91aSSascha WildnerThey can be used to implement reference counts or as building blocks for more 69cb0ac91aSSascha Wildneradvanced synchronization primitives such as mutexes. 70cb0ac91aSSascha Wildner.Ss Types 71cb0ac91aSSascha WildnerEach atomic operation operates on a specific 72cb0ac91aSSascha Wildner.Fa type . 73cb0ac91aSSascha WildnerThe type to use is indicated in the function name. 74cb0ac91aSSascha WildnerThe available types that can be used are: 75cb0ac91aSSascha Wildner.Pp 76*7cecd65aSzrj.Bl -tag -offset indent -width ".Li cpumask" -compact 77619596bfSSascha Wildner.It Li cpumask 78619596bfSSascha WildnerCPU mask (cpumask_t) 79cb0ac91aSSascha Wildner.It Li int 80cb0ac91aSSascha Wildnerunsigned integer 81cb0ac91aSSascha Wildner.It Li long 82cb0ac91aSSascha Wildnerunsigned long integer 83cb0ac91aSSascha Wildner.It Li ptr 84cb0ac91aSSascha Wildnerunsigned integer the size of a pointer 85cb0ac91aSSascha Wildner.It Li 32 86cb0ac91aSSascha Wildnerunsigned 32-bit integer 87cb0ac91aSSascha Wildner.\".It Li 64 88cb0ac91aSSascha Wildner.\"unsigned 64-bit integer 89cb0ac91aSSascha Wildner.El 90cb0ac91aSSascha Wildner.Pp 91cb0ac91aSSascha WildnerFor example, the function to atomically add two integers is called 92cb0ac91aSSascha Wildner.Fn atomic_add_int . 93cb0ac91aSSascha Wildner.Pp 94cb0ac91aSSascha WildnerCertain architectures also provide operations for types smaller than 95cb0ac91aSSascha Wildner.Dq Li int . 96cb0ac91aSSascha Wildner.Pp 97cb0ac91aSSascha Wildner.Bl -tag -offset indent -width short -compact 98cb0ac91aSSascha Wildner.It Li char 99cb0ac91aSSascha Wildnerunsigned character 100cb0ac91aSSascha Wildner.It Li short 101cb0ac91aSSascha Wildnerunsigned short integer 102cb0ac91aSSascha Wildner.It Li 8 103cb0ac91aSSascha Wildnerunsigned 8-bit integer 104cb0ac91aSSascha Wildner.It Li 16 105cb0ac91aSSascha Wildnerunsigned 16-bit integer 106cb0ac91aSSascha Wildner.El 107cb0ac91aSSascha Wildner.Pp 108cb0ac91aSSascha WildnerThese must not be used in MI code because the instructions to implement them 109cb0ac91aSSascha Wildnerefficiently may not be available. 110cb0ac91aSSascha Wildner.Ss Memory Barriers 111cb0ac91aSSascha WildnerMemory barriers are used to guarantee the order of data accesses in 112cb0ac91aSSascha Wildnertwo ways. 113cb0ac91aSSascha WildnerFirst, they specify hints to the compiler to not re-order or optimize the 114cb0ac91aSSascha Wildneroperations. 115cb0ac91aSSascha WildnerSecond, on architectures that do not guarantee ordered data accesses, 116cb0ac91aSSascha Wildnerspecial instructions or special variants of instructions are used to indicate 117cb0ac91aSSascha Wildnerto the processor that data accesses need to occur in a certain order. 118cb0ac91aSSascha WildnerAs a result, most of the atomic operations have three variants in order to 119cb0ac91aSSascha Wildnerinclude optional memory barriers. 120cb0ac91aSSascha WildnerThe first form just performs the operation without any explicit barriers. 121cb0ac91aSSascha WildnerThe second form uses a read memory barrier, and the third variant uses a write 122cb0ac91aSSascha Wildnermemory barrier. 123cb0ac91aSSascha Wildner.Pp 124cb0ac91aSSascha WildnerThe second variant of each operation includes a read memory barrier. 125cb0ac91aSSascha WildnerThis barrier ensures that the effects of this operation are completed before the 126cb0ac91aSSascha Wildnereffects of any later data accesses. 127cb0ac91aSSascha WildnerAs a result, the operation is said to have acquire semantics as it acquires a 128cb0ac91aSSascha Wildnerpseudo-lock requiring further operations to wait until it has completed. 129cb0ac91aSSascha WildnerTo denote this, the suffix 130cb0ac91aSSascha Wildner.Dq Li _acq 131cb0ac91aSSascha Wildneris inserted into the function name immediately prior to the 132cb0ac91aSSascha Wildner.Dq Li _ Ns Aq Fa type 133cb0ac91aSSascha Wildnersuffix. 134cb0ac91aSSascha WildnerFor example, to subtract two integers ensuring that any later writes will 135cb0ac91aSSascha Wildnerhappen after the subtraction is performed, use 136cb0ac91aSSascha Wildner.Fn atomic_subtract_acq_int . 137cb0ac91aSSascha Wildner.Pp 138cb0ac91aSSascha WildnerThe third variant of each operation includes a write memory barrier. 139cb0ac91aSSascha WildnerThis ensures that all effects of all previous data accesses are completed 140cb0ac91aSSascha Wildnerbefore this operation takes place. 141cb0ac91aSSascha WildnerAs a result, the operation is said to have release semantics as it releases 142cb0ac91aSSascha Wildnerany pending data accesses to be completed before its operation is performed. 143cb0ac91aSSascha WildnerTo denote this, the suffix 144cb0ac91aSSascha Wildner.Dq Li _rel 145cb0ac91aSSascha Wildneris inserted into the function name immediately prior to the 146cb0ac91aSSascha Wildner.Dq Li _ Ns Aq Fa type 147cb0ac91aSSascha Wildnersuffix. 148cb0ac91aSSascha WildnerFor example, to add two long integers ensuring that all previous 149cb0ac91aSSascha Wildnerwrites will happen first, use 150cb0ac91aSSascha Wildner.Fn atomic_add_rel_long . 151cb0ac91aSSascha Wildner.Pp 152cb0ac91aSSascha WildnerA practical example of using memory barriers is to ensure that data accesses 153cb0ac91aSSascha Wildnerthat are protected by a lock are all performed while the lock is held. 154cb0ac91aSSascha WildnerTo achieve this, one would use a read barrier when acquiring the lock to 155cb0ac91aSSascha Wildnerguarantee that the lock is held before any protected operations are performed. 156cb0ac91aSSascha WildnerFinally, one would use a write barrier when releasing the lock to ensure that 157cb0ac91aSSascha Wildnerall of the protected operations are completed before the lock is released. 158cb0ac91aSSascha Wildner.Ss Multiple Processors 159cb0ac91aSSascha WildnerThe current set of atomic operations do not necessarily guarantee atomicity 160cb0ac91aSSascha Wildneracross multiple processors. 161cb0ac91aSSascha WildnerTo guarantee atomicity across processors, not only does the individual 162cb0ac91aSSascha Wildneroperation need to be atomic on the processor performing the operation, but 163cb0ac91aSSascha Wildnerthe result of the operation needs to be pushed out to stable storage and the 164cb0ac91aSSascha Wildnercaches of all other processors on the system need to invalidate any cache 165cb0ac91aSSascha Wildnerlines that include the affected memory region. 166cb0ac91aSSascha Wildner.Ss Semantics 167cb0ac91aSSascha WildnerThis section describes the semantics of each operation using a C like notation. 168cb0ac91aSSascha Wildner.Bl -hang 169cb0ac91aSSascha Wildner.It Fn atomic_add p v 170cb0ac91aSSascha Wildner.Bd -literal -compact 171cb0ac91aSSascha Wildner*p += v; 172cb0ac91aSSascha Wildner.Ed 173619596bfSSascha Wildner.El 174619596bfSSascha Wildner.Pp 175619596bfSSascha WildnerThe 176619596bfSSascha Wildner.Fn atomic_add 177619596bfSSascha Wildnerfunctions are not implemented for the type 178619596bfSSascha Wildner.Dq Li cpumask . 179619596bfSSascha Wildner.Bl -hang 180cb0ac91aSSascha Wildner.It Fn atomic_clear p v 181cb0ac91aSSascha Wildner.Bd -literal -compact 182cb0ac91aSSascha Wildner*p &= ~v; 183cb0ac91aSSascha Wildner.Ed 184cb0ac91aSSascha Wildner.It Fn atomic_cmpset dst old new 185cb0ac91aSSascha Wildner.Bd -literal -compact 186cb0ac91aSSascha Wildnerif (*dst == old) { 187cb0ac91aSSascha Wildner *dst = new; 188cb0ac91aSSascha Wildner return 1; 1898dae8275SJoris GIOVANNANGELI} else { 190cb0ac91aSSascha Wildner return 0; 1918dae8275SJoris GIOVANNANGELI} 192cb0ac91aSSascha Wildner.Ed 193cb0ac91aSSascha Wildner.El 194cb0ac91aSSascha Wildner.Pp 195cb0ac91aSSascha WildnerThe 196cb0ac91aSSascha Wildner.Fn atomic_cmpset 197cb0ac91aSSascha Wildnerfunctions are not implemented for the types 198cb0ac91aSSascha Wildner.Dq Li char , 199cb0ac91aSSascha Wildner.Dq Li short , 200cb0ac91aSSascha Wildner.Dq Li 8 , 201cb0ac91aSSascha Wildnerand 202cb0ac91aSSascha Wildner.Dq Li 16 . 203cb0ac91aSSascha Wildner.Bl -hang 204cb0ac91aSSascha Wildner.It Fn atomic_fetchadd p v 205cb0ac91aSSascha Wildner.Bd -literal -compact 206cb0ac91aSSascha Wildnertmp = *p; 207cb0ac91aSSascha Wildner*p += v; 208cb0ac91aSSascha Wildnerreturn tmp; 209cb0ac91aSSascha Wildner.Ed 210cb0ac91aSSascha Wildner.El 211cb0ac91aSSascha Wildner.Pp 212cb0ac91aSSascha WildnerThe 213cb0ac91aSSascha Wildner.Fn atomic_fetchadd 214cb0ac91aSSascha Wildnerfunctions are only implemented for the types 215cb0ac91aSSascha Wildner.Dq Li int , 216cb0ac91aSSascha Wildner.Dq Li long 217cb0ac91aSSascha Wildnerand 218cb0ac91aSSascha Wildner.Dq Li 32 219cb0ac91aSSascha Wildnerand do not have any variants with memory barriers at this time. 220cb0ac91aSSascha Wildner.Bl -hang 221cb0ac91aSSascha Wildner.It Fn atomic_load addr 222cb0ac91aSSascha Wildner.Bd -literal -compact 223cb0ac91aSSascha Wildnerreturn (*addr) 224cb0ac91aSSascha Wildner.Ed 225cb0ac91aSSascha Wildner.El 226cb0ac91aSSascha Wildner.Pp 227cb0ac91aSSascha WildnerThe 228cb0ac91aSSascha Wildner.Fn atomic_load 229cb0ac91aSSascha Wildnerfunctions are only provided with acquire memory barriers. 230cb0ac91aSSascha Wildner.Bl -hang 231cb0ac91aSSascha Wildner.It Fn atomic_readandclear addr 232cb0ac91aSSascha Wildner.Bd -literal -compact 233cb0ac91aSSascha Wildnertemp = *addr; 234cb0ac91aSSascha Wildner*addr = 0; 235cb0ac91aSSascha Wildnerreturn (temp); 236cb0ac91aSSascha Wildner.Ed 237cb0ac91aSSascha Wildner.El 238cb0ac91aSSascha Wildner.Pp 239cb0ac91aSSascha WildnerThe 240cb0ac91aSSascha Wildner.Fn atomic_readandclear 241cb0ac91aSSascha Wildnerfunctions are not implemented for the types 242cb0ac91aSSascha Wildner.Dq Li char , 243cb0ac91aSSascha Wildner.Dq Li short , 244cb0ac91aSSascha Wildner.Dq Li ptr , 245cb0ac91aSSascha Wildner.Dq Li 8 , 246619596bfSSascha Wildner.Dq Li 16 , 247cb0ac91aSSascha Wildnerand 248619596bfSSascha Wildner.Dq Li cpumask 249cb0ac91aSSascha Wildnerand do 250cb0ac91aSSascha Wildnernot have any variants with memory barriers at this time. 251cb0ac91aSSascha Wildner.Bl -hang 252cb0ac91aSSascha Wildner.It Fn atomic_set p v 253cb0ac91aSSascha Wildner.Bd -literal -compact 254cb0ac91aSSascha Wildner*p |= v; 255cb0ac91aSSascha Wildner.Ed 256cb0ac91aSSascha Wildner.It Fn atomic_subtract p v 257cb0ac91aSSascha Wildner.Bd -literal -compact 258cb0ac91aSSascha Wildner*p -= v; 259cb0ac91aSSascha Wildner.Ed 260619596bfSSascha Wildner.El 261619596bfSSascha Wildner.Pp 262619596bfSSascha WildnerThe 263619596bfSSascha Wildner.Fn atomic_subtract 264619596bfSSascha Wildnerfunctions are not implemented for the type 265619596bfSSascha Wildner.Dq Li cpumask . 266619596bfSSascha Wildner.Bl -hang 267cb0ac91aSSascha Wildner.It Fn atomic_store p v 268cb0ac91aSSascha Wildner.Bd -literal -compact 269cb0ac91aSSascha Wildner*p = v; 270cb0ac91aSSascha Wildner.Ed 271cb0ac91aSSascha Wildner.El 272cb0ac91aSSascha Wildner.Pp 273cb0ac91aSSascha WildnerThe 274cb0ac91aSSascha Wildner.Fn atomic_store 275cb0ac91aSSascha Wildnerfunctions are only provided with release memory barriers. 276cb0ac91aSSascha Wildner.Sh RETURN VALUES 277cb0ac91aSSascha WildnerThe 278cb0ac91aSSascha Wildner.Fn atomic_cmpset 279cb0ac91aSSascha Wildnerfunction 280cb0ac91aSSascha Wildnerreturns the result of the compare operation. 281cb0ac91aSSascha WildnerThe 282cb0ac91aSSascha Wildner.Fn atomic_fetchadd , 283cb0ac91aSSascha Wildner.Fn atomic_load , 284cb0ac91aSSascha Wildnerand 285cb0ac91aSSascha Wildner.Fn atomic_readandclear 286cb0ac91aSSascha Wildnerfunctions 287cb0ac91aSSascha Wildnerreturn the value at the specified address. 288cb0ac91aSSascha Wildner.\".Sh EXAMPLES 289cb0ac91aSSascha Wildner.\"This example uses the 290cb0ac91aSSascha Wildner.\".Fn atomic_cmpset_acq_ptr 291cb0ac91aSSascha Wildner.\"and 292cb0ac91aSSascha Wildner.\".Fn atomic_set_ptr 293cb0ac91aSSascha Wildner.\"functions to obtain a sleep mutex and handle recursion. 294cb0ac91aSSascha Wildner.\"Since the 295cb0ac91aSSascha Wildner.\".Va mtx_lock 296cb0ac91aSSascha Wildner.\"member of a 297cb0ac91aSSascha Wildner.\".Vt "struct mtx" 298cb0ac91aSSascha Wildner.\"is a pointer, the 299cb0ac91aSSascha Wildner.\".Dq Li ptr 300cb0ac91aSSascha Wildner.\"type is used. 301cb0ac91aSSascha Wildner.\".Bd -literal 302cb0ac91aSSascha Wildner.\"/* Try to obtain mtx_lock once. */ 303cb0ac91aSSascha Wildner.\"#define _obtain_lock(mp, tid) \\ 304cb0ac91aSSascha Wildner.\" atomic_cmpset_acq_ptr(&(mp)->mtx_lock, MTX_UNOWNED, (tid)) 305cb0ac91aSSascha Wildner.\" 306cb0ac91aSSascha Wildner.\"/* Get a sleep lock, deal with recursion inline. */ 307cb0ac91aSSascha Wildner.\"#define _get_sleep_lock(mp, tid, opts, file, line) do { \\ 308cb0ac91aSSascha Wildner.\" uintptr_t _tid = (uintptr_t)(tid); \\ 309cb0ac91aSSascha Wildner.\" \\ 310cb0ac91aSSascha Wildner.\" if (!_obtain_lock(mp, tid)) { \\ 311cb0ac91aSSascha Wildner.\" if (((mp)->mtx_lock & MTX_FLAGMASK) != _tid) \\ 312cb0ac91aSSascha Wildner.\" _mtx_lock_sleep((mp), _tid, (opts), (file), (line));\\ 313cb0ac91aSSascha Wildner.\" else { \\ 314cb0ac91aSSascha Wildner.\" atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSE); \\ 315cb0ac91aSSascha Wildner.\" (mp)->mtx_recurse++; \\ 316cb0ac91aSSascha Wildner.\" } \\ 317cb0ac91aSSascha Wildner.\" } \\ 318cb0ac91aSSascha Wildner.\"} while (0) 319cb0ac91aSSascha Wildner.\".Ed 320cb0ac91aSSascha Wildner.Sh HISTORY 321cb0ac91aSSascha WildnerThe 322cb0ac91aSSascha Wildner.Fn atomic_add , 323cb0ac91aSSascha Wildner.Fn atomic_clear , 324cb0ac91aSSascha Wildner.Fn atomic_set , 325cb0ac91aSSascha Wildnerand 326cb0ac91aSSascha Wildner.Fn atomic_subtract 327cb0ac91aSSascha Wildneroperations were first introduced in 328cb0ac91aSSascha Wildner.Fx 3.0 . 329cb0ac91aSSascha WildnerThis first set only supported the types 330cb0ac91aSSascha Wildner.Dq Li char , 331cb0ac91aSSascha Wildner.Dq Li short , 332cb0ac91aSSascha Wildner.Dq Li int , 333cb0ac91aSSascha Wildnerand 334cb0ac91aSSascha Wildner.Dq Li long . 335cb0ac91aSSascha WildnerThe 336cb0ac91aSSascha Wildner.Fn atomic_cmpset , 337cb0ac91aSSascha Wildner.Fn atomic_load , 338cb0ac91aSSascha Wildner.Fn atomic_readandclear , 339cb0ac91aSSascha Wildnerand 340cb0ac91aSSascha Wildner.Fn atomic_store 341cb0ac91aSSascha Wildneroperations were added in 342cb0ac91aSSascha Wildner.Fx 5.0 . 343cb0ac91aSSascha WildnerThe types 344cb0ac91aSSascha Wildner.Dq Li 8 , 345cb0ac91aSSascha Wildner.Dq Li 16 , 346cb0ac91aSSascha Wildner.Dq Li 32 , 347cb0ac91aSSascha Wildner.\".Dq Li 64 , 348cb0ac91aSSascha Wildnerand 349cb0ac91aSSascha Wildner.Dq Li ptr 350cb0ac91aSSascha Wildnerand all of the acquire and release variants 351cb0ac91aSSascha Wildnerwere added in 352cb0ac91aSSascha Wildner.Fx 5.0 353cb0ac91aSSascha Wildneras well. 354cb0ac91aSSascha WildnerThe 355cb0ac91aSSascha Wildner.Fn atomic_fetchadd 356cb0ac91aSSascha Wildneroperations were added in 357cb0ac91aSSascha Wildner.Fx 6.0 . 358