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// [the Go memory model]: https://go.dev/ref/mem 49package atomic 50 51import ( 52 "unsafe" 53) 54 55// BUG(rsc): On 386, the 64-bit functions use instructions unavailable before the Pentium MMX. 56// 57// On non-Linux ARM, the 64-bit functions use instructions unavailable before the ARMv6k core. 58// 59// On ARM, 386, and 32-bit MIPS, it is the caller's responsibility to arrange 60// for 64-bit alignment of 64-bit words accessed atomically via the primitive 61// atomic functions (types [Int64] and [Uint64] are automatically aligned). 62// The first word in an allocated struct, array, or slice; in a global 63// variable; or in a local variable (because the subject of all atomic operations 64// will escape to the heap) can be relied upon to be 64-bit aligned. 65 66// SwapInt32 atomically stores new into *addr and returns the previous *addr value. 67// Consider using the more ergonomic and less error-prone [Int32.Swap] instead. 68func SwapInt32(addr *int32, new int32) (old int32) 69 70// SwapInt64 atomically stores new into *addr and returns the previous *addr value. 71// Consider using the more ergonomic and less error-prone [Int64.Swap] instead 72// (particularly if you target 32-bit platforms; see the bugs section). 73func SwapInt64(addr *int64, new int64) (old int64) 74 75// SwapUint32 atomically stores new into *addr and returns the previous *addr value. 76// Consider using the more ergonomic and less error-prone [Uint32.Swap] instead. 77func SwapUint32(addr *uint32, new uint32) (old uint32) 78 79// SwapUint64 atomically stores new into *addr and returns the previous *addr value. 80// Consider using the more ergonomic and less error-prone [Uint64.Swap] instead 81// (particularly if you target 32-bit platforms; see the bugs section). 82func SwapUint64(addr *uint64, new uint64) (old uint64) 83 84// SwapUintptr atomically stores new into *addr and returns the previous *addr value. 85// Consider using the more ergonomic and less error-prone [Uintptr.Swap] instead. 86func SwapUintptr(addr *uintptr, new uintptr) (old uintptr) 87 88// SwapPointer atomically stores new into *addr and returns the previous *addr value. 89// Consider using the more ergonomic and less error-prone [Pointer.Swap] instead. 90func SwapPointer(addr *unsafe.Pointer, new unsafe.Pointer) (old unsafe.Pointer) 91 92// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value. 93// Consider using the more ergonomic and less error-prone [Int32.CompareAndSwap] instead. 94func CompareAndSwapInt32(addr *int32, old, new int32) (swapped bool) 95 96// CompareAndSwapInt64 executes the compare-and-swap operation for an int64 value. 97// Consider using the more ergonomic and less error-prone [Int64.CompareAndSwap] instead 98// (particularly if you target 32-bit platforms; see the bugs section). 99func CompareAndSwapInt64(addr *int64, old, new int64) (swapped bool) 100 101// CompareAndSwapUint32 executes the compare-and-swap operation for a uint32 value. 102// Consider using the more ergonomic and less error-prone [Uint32.CompareAndSwap] instead. 103func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool) 104 105// CompareAndSwapUint64 executes the compare-and-swap operation for a uint64 value. 106// Consider using the more ergonomic and less error-prone [Uint64.CompareAndSwap] instead 107// (particularly if you target 32-bit platforms; see the bugs section). 108func CompareAndSwapUint64(addr *uint64, old, new uint64) (swapped bool) 109 110// CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value. 111// Consider using the more ergonomic and less error-prone [Uintptr.CompareAndSwap] instead. 112func CompareAndSwapUintptr(addr *uintptr, old, new uintptr) (swapped bool) 113 114// CompareAndSwapPointer executes the compare-and-swap operation for a unsafe.Pointer value. 115// Consider using the more ergonomic and less error-prone [Pointer.CompareAndSwap] instead. 116func CompareAndSwapPointer(addr *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool) 117 118// AddInt32 atomically adds delta to *addr and returns the new value. 119// Consider using the more ergonomic and less error-prone [Int32.Add] instead. 120func AddInt32(addr *int32, delta int32) (new int32) 121 122// AddUint32 atomically adds delta to *addr and returns the new value. 123// To subtract a signed positive constant value c from x, do AddUint32(&x, ^uint32(c-1)). 124// In particular, to decrement x, do AddUint32(&x, ^uint32(0)). 125// Consider using the more ergonomic and less error-prone [Uint32.Add] instead. 126func AddUint32(addr *uint32, delta uint32) (new uint32) 127 128// AddInt64 atomically adds delta to *addr and returns the new value. 129// Consider using the more ergonomic and less error-prone [Int64.Add] instead 130// (particularly if you target 32-bit platforms; see the bugs section). 131func AddInt64(addr *int64, delta int64) (new int64) 132 133// AddUint64 atomically adds delta to *addr and returns the new value. 134// To subtract a signed positive constant value c from x, do AddUint64(&x, ^uint64(c-1)). 135// In particular, to decrement x, do AddUint64(&x, ^uint64(0)). 136// Consider using the more ergonomic and less error-prone [Uint64.Add] instead 137// (particularly if you target 32-bit platforms; see the bugs section). 138func AddUint64(addr *uint64, delta uint64) (new uint64) 139 140// AddUintptr atomically adds delta to *addr and returns the new value. 141// Consider using the more ergonomic and less error-prone [Uintptr.Add] instead. 142func AddUintptr(addr *uintptr, delta uintptr) (new uintptr) 143 144// AndInt32 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 [Int32.And] instead. 147func AndInt32(addr *int32, mask int32) (old int32) 148 149// AndUint32 atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 150// and returns the old value. 151// Consider using the more ergonomic and less error-prone [Uint32.And] instead. 152func AndUint32(addr *uint32, mask uint32) (old uint32) 153 154// AndInt64 atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 155// and returns the old value. 156// Consider using the more ergonomic and less error-prone [Int64.And] instead. 157func AndInt64(addr *int64, mask int64) (old int64) 158 159// AndUint64 atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 160// and returns the old. 161// Consider using the more ergonomic and less error-prone [Uint64.And] instead. 162func AndUint64(addr *uint64, mask uint64) (old uint64) 163 164// AndUintptr atomically performs a bitwise AND operation on *addr using the bitmask provided as mask 165// and returns the old value. 166// Consider using the more ergonomic and less error-prone [Uintptr.And] instead. 167func AndUintptr(addr *uintptr, mask uintptr) (old uintptr) 168 169// OrInt32 atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 170// and returns the old value. 171// Consider using the more ergonomic and less error-prone [Int32.Or] instead. 172func OrInt32(addr *int32, mask int32) (old int32) 173 174// OrUint32 atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 175// and returns the old value. 176// Consider using the more ergonomic and less error-prone [Uint32.Or] instead. 177func OrUint32(addr *uint32, mask uint32) (old uint32) 178 179// OrInt64 atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 180// and returns the old value. 181// Consider using the more ergonomic and less error-prone [Int64.Or] instead. 182func OrInt64(addr *int64, mask int64) (old int64) 183 184// OrUint64 atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 185// and returns the old value. 186// Consider using the more ergonomic and less error-prone [Uint64.Or] instead. 187func OrUint64(addr *uint64, mask uint64) (old uint64) 188 189// OrUintptr atomically performs a bitwise OR operation on *addr using the bitmask provided as mask 190// and returns the old value. 191// Consider using the more ergonomic and less error-prone [Uintptr.Or] instead. 192func OrUintptr(addr *uintptr, mask uintptr) (old uintptr) 193 194// LoadInt32 atomically loads *addr. 195// Consider using the more ergonomic and less error-prone [Int32.Load] instead. 196func LoadInt32(addr *int32) (val int32) 197 198// LoadInt64 atomically loads *addr. 199// Consider using the more ergonomic and less error-prone [Int64.Load] instead 200// (particularly if you target 32-bit platforms; see the bugs section). 201func LoadInt64(addr *int64) (val int64) 202 203// LoadUint32 atomically loads *addr. 204// Consider using the more ergonomic and less error-prone [Uint32.Load] instead. 205func LoadUint32(addr *uint32) (val uint32) 206 207// LoadUint64 atomically loads *addr. 208// Consider using the more ergonomic and less error-prone [Uint64.Load] instead 209// (particularly if you target 32-bit platforms; see the bugs section). 210func LoadUint64(addr *uint64) (val uint64) 211 212// LoadUintptr atomically loads *addr. 213// Consider using the more ergonomic and less error-prone [Uintptr.Load] instead. 214func LoadUintptr(addr *uintptr) (val uintptr) 215 216// LoadPointer atomically loads *addr. 217// Consider using the more ergonomic and less error-prone [Pointer.Load] instead. 218func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer) 219 220// StoreInt32 atomically stores val into *addr. 221// Consider using the more ergonomic and less error-prone [Int32.Store] instead. 222func StoreInt32(addr *int32, val int32) 223 224// StoreInt64 atomically stores val into *addr. 225// Consider using the more ergonomic and less error-prone [Int64.Store] instead 226// (particularly if you target 32-bit platforms; see the bugs section). 227func StoreInt64(addr *int64, val int64) 228 229// StoreUint32 atomically stores val into *addr. 230// Consider using the more ergonomic and less error-prone [Uint32.Store] instead. 231func StoreUint32(addr *uint32, val uint32) 232 233// StoreUint64 atomically stores val into *addr. 234// Consider using the more ergonomic and less error-prone [Uint64.Store] instead 235// (particularly if you target 32-bit platforms; see the bugs section). 236func StoreUint64(addr *uint64, val uint64) 237 238// StoreUintptr atomically stores val into *addr. 239// Consider using the more ergonomic and less error-prone [Uintptr.Store] instead. 240func StoreUintptr(addr *uintptr, val uintptr) 241 242// StorePointer atomically stores val into *addr. 243// Consider using the more ergonomic and less error-prone [Pointer.Store] instead. 244func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer) 245