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