1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package atomic provides low-level atomic memory primitives 6 // useful for implementing synchronization algorithms. 7 // 8 // These functions require great care to be used correctly. 9 // Except for special, low-level applications, synchronization is better 10 // done with channels or the facilities of the [sync] package. 11 // Share memory by communicating; 12 // don't communicate by sharing memory. 13 // 14 // The swap operation, implemented by the SwapT functions, is the atomic 15 // equivalent of: 16 // 17 // old = *addr 18 // *addr = new 19 // return old 20 // 21 // The compare-and-swap operation, implemented by the CompareAndSwapT 22 // functions, is the atomic equivalent of: 23 // 24 // if *addr == old { 25 // *addr = new 26 // return true 27 // } 28 // return false 29 // 30 // The add operation, implemented by the AddT functions, is the atomic 31 // equivalent of: 32 // 33 // *addr += delta 34 // return *addr 35 // 36 // The load and store operations, implemented by the LoadT and StoreT 37 // functions, are the atomic equivalents of "return *addr" and 38 // "*addr = val". 39 // 40 // In the terminology of [the Go memory model], if the effect of 41 // an atomic operation A is observed by atomic operation B, 42 // then A “synchronizes before” B. 43 // Additionally, all the atomic operations executed in a program 44 // behave as though executed in some sequentially consistent order. 45 // This definition provides the same semantics as 46 // C++'s sequentially consistent atomics and Java's volatile variables. 47 // 48 // Only a few integer sizes are supported: on many architectures, 49 // atomic operations on non-word-sized integers are inefficient or 50 // infeasible. For example, a [Bool] may be larger than a built-in bool. 51 // 52 // [the Go memory model]: https://go.dev/ref/mem 53 package atomic 54 55 import ( 56 "unsafe" 57 ) 58 59 // BUG(rsc): On 386, the 64-bit functions use instructions unavailable before the Pentium MMX. 60 // 61 // On non-Linux ARM, the 64-bit functions use instructions unavailable before the ARMv6k core. 62 // 63 // On ARM, 386, and 32-bit MIPS, it is the caller's responsibility to arrange 64 // for 64-bit alignment of 64-bit words accessed atomically via the primitive 65 // atomic functions (types [Int64] and [Uint64] are automatically aligned). 66 // The first word in an allocated struct, array, or slice; in a global 67 // variable; or in a local variable (because on 32-bit architectures, the 68 // subject of 64-bit atomic operations will escape to the heap) can be 69 // relied upon to be 64-bit aligned. 70 71 // SwapInt32 atomically stores new into *addr and returns the previous *addr value. 72 // Consider using the more ergonomic and less error-prone [Int32.Swap] instead. 73 // 74 //go:noescape 75 func SwapInt32(addr *int32, new int32) (old int32) 76 77 // SwapUint32 atomically stores new into *addr and returns the previous *addr value. 78 // Consider using the more ergonomic and less error-prone [Uint32.Swap] instead. 79 // 80 //go:noescape 81 func SwapUint32(addr *uint32, new uint32) (old uint32) 82 83 // SwapUintptr atomically stores new into *addr and returns the previous *addr value. 84 // Consider using the more ergonomic and less error-prone [Uintptr.Swap] instead. 85 // 86 //go:noescape 87 //go:linknamestd SwapUintptr 88 func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) 89 90 // SwapPointer atomically stores new into *addr and returns the previous *addr value. 91 // Consider using the more ergonomic and less error-prone [Pointer.Swap] instead. 92 func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) 93 94 // CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value. 95 // Consider using the more ergonomic and less error-prone [Int32.CompareAndSwap] instead. 96 // 97 //go:noescape 98 func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) 99 100 // CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value. 101 // Consider using the more ergonomic and less error-prone [Uint32.CompareAndSwap] instead. 102 // 103 //go:noescape 104 func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool) 105 106 // CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value. 107 // Consider using the more ergonomic and less error-prone [Uintptr.CompareAndSwap] instead. 108 // 109 //go:noescape 110 //go:linknamestd CompareAndSwapUintptr 111 func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool) 112 113 // CompareAndSwapPointer executes the compare-and-swap operation for a unsafe.Pointer value. 114 // Consider using the more ergonomic and less error-prone [Pointer.CompareAndSwap] instead. 115 func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) 116 117 // AddInt32 atomically adds delta to *addr and returns the new value. 118 // Consider using the more ergonomic and less error-prone [Int32.Add] instead. 119 // 120 //go:noescape 121 func AddInt32(addr *int32, delta int32) (new int32) 122 123 // AddUint32 atomically adds delta to *addr and returns the new value. 124 // To subtract a signed positive constant value c from x, do AddUint32(&x, ^uint32(c-1)). 125 // In particular, to decrement x, do AddUint32(&x, ^uint32(0)). 126 // Consider using the more ergonomic and less error-prone [Uint32.Add] instead. 127 // 128 //go:noescape 129 func AddUint32(addr *uint32, delta uint32) (new uint32) 130 131 // AddUintptr atomically adds delta to *addr and returns the new value. 132 // Consider using the more ergonomic and less error-prone [Uintptr.Add] instead. 133 // 134 //go:noescape 135 func AddUintptr(addr *uintptr, delta uintptr) (new uintptr) 136 137 // AndInt32 atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 138 // and returns the old value. 139 // Consider using the more ergonomic and less error-prone [Int32.And] instead. 140 // 141 //go:noescape 142 func AndInt32(addr *int32, mask int32) (old int32) 143 144 // AndUint32 atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 145 // and returns the old value. 146 // Consider using the more ergonomic and less error-prone [Uint32.And] instead. 147 // 148 //go:noescape 149 func AndUint32(addr *uint32, mask uint32) (old uint32) 150 151 // AndUintptr atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 152 // and returns the old value. 153 // Consider using the more ergonomic and less error-prone [Uintptr.And] instead. 154 // 155 //go:noescape 156 func AndUintptr(addr *uintptr, mask uintptr) (old uintptr) 157 158 // OrInt32 atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 159 // and returns the old value. 160 // Consider using the more ergonomic and less error-prone [Int32.Or] instead. 161 // 162 //go:noescape 163 func OrInt32(addr *int32, mask int32) (old int32) 164 165 // OrUint32 atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 166 // and returns the old value. 167 // Consider using the more ergonomic and less error-prone [Uint32.Or] instead. 168 // 169 //go:noescape 170 func OrUint32(addr *uint32, mask uint32) (old uint32) 171 172 // OrUintptr atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 173 // and returns the old value. 174 // Consider using the more ergonomic and less error-prone [Uintptr.Or] instead. 175 // 176 //go:noescape 177 func OrUintptr(addr *uintptr, mask uintptr) (old uintptr) 178 179 // LoadInt32 atomically loads *addr. 180 // Consider using the more ergonomic and less error-prone [Int32.Load] instead. 181 // 182 //go:noescape 183 func LoadInt32(addr *int32) (val int32) 184 185 // LoadUint32 atomically loads *addr. 186 // Consider using the more ergonomic and less error-prone [Uint32.Load] instead. 187 // 188 //go:noescape 189 func LoadUint32(addr *uint32) (val uint32) 190 191 // LoadUintptr atomically loads *addr. 192 // Consider using the more ergonomic and less error-prone [Uintptr.Load] instead. 193 // 194 //go:noescape 195 func LoadUintptr(addr *uintptr) (val uintptr) 196 197 // LoadPointer atomically loads *addr. 198 // Consider using the more ergonomic and less error-prone [Pointer.Load] instead. 199 func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) 200 201 // StoreInt32 atomically stores val into *addr. 202 // Consider using the more ergonomic and less error-prone [Int32.Store] instead. 203 // 204 //go:noescape 205 func StoreInt32(addr *int32, val int32) 206 207 // StoreUint32 atomically stores val into *addr. 208 // Consider using the more ergonomic and less error-prone [Uint32.Store] instead. 209 // 210 //go:noescape 211 func StoreUint32(addr *uint32, val uint32) 212 213 // StoreUintptr atomically stores val into *addr. 214 // Consider using the more ergonomic and less error-prone [Uintptr.Store] instead. 215 // 216 //go:noescape 217 //go:linknamestd StoreUintptr 218 func StoreUintptr(addr *uintptr, val uintptr) 219 220 // StorePointer atomically stores val into *addr. 221 // Consider using the more ergonomic and less error-prone [Pointer.Store] instead. 222 func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) 223