xref: /dflybsd-src/share/man/man9/atomic.9 (revision d42a763b067d6e9f0805fbc592ed727cec49df2c)
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.\"
26*d42a763bSAaron LI.Dd January 14, 2024
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>
56*d42a763bSAaron LI.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
64*d42a763bSAaron LI.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
767cecd65aSzrj.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.It Fn atomic_readandclear addr
226cb0ac91aSSascha Wildner.Bd -literal -compact
227cb0ac91aSSascha Wildnertemp = *addr;
228cb0ac91aSSascha Wildner*addr = 0;
229cb0ac91aSSascha Wildnerreturn (temp);
230cb0ac91aSSascha Wildner.Ed
231cb0ac91aSSascha Wildner.El
232cb0ac91aSSascha Wildner.Pp
233cb0ac91aSSascha WildnerThe
234cb0ac91aSSascha Wildner.Fn atomic_readandclear
235cb0ac91aSSascha Wildnerfunctions are not implemented for the types
236cb0ac91aSSascha Wildner.Dq Li char ,
237cb0ac91aSSascha Wildner.Dq Li short ,
238cb0ac91aSSascha Wildner.Dq Li ptr ,
239cb0ac91aSSascha Wildner.Dq Li 8 ,
240619596bfSSascha Wildner.Dq Li 16 ,
241cb0ac91aSSascha Wildnerand
242619596bfSSascha Wildner.Dq Li cpumask
243cb0ac91aSSascha Wildnerand do
244cb0ac91aSSascha Wildnernot have any variants with memory barriers at this time.
245cb0ac91aSSascha Wildner.Bl -hang
246cb0ac91aSSascha Wildner.It Fn atomic_set p v
247cb0ac91aSSascha Wildner.Bd -literal -compact
248cb0ac91aSSascha Wildner*p |= v;
249cb0ac91aSSascha Wildner.Ed
250cb0ac91aSSascha Wildner.It Fn atomic_subtract p v
251cb0ac91aSSascha Wildner.Bd -literal -compact
252cb0ac91aSSascha Wildner*p -= v;
253cb0ac91aSSascha Wildner.Ed
254619596bfSSascha Wildner.El
255619596bfSSascha Wildner.Pp
256619596bfSSascha WildnerThe
257619596bfSSascha Wildner.Fn atomic_subtract
258619596bfSSascha Wildnerfunctions are not implemented for the type
259619596bfSSascha Wildner.Dq Li cpumask .
260619596bfSSascha Wildner.Bl -hang
261cb0ac91aSSascha Wildner.It Fn atomic_store p v
262cb0ac91aSSascha Wildner.Bd -literal -compact
263cb0ac91aSSascha Wildner*p = v;
264cb0ac91aSSascha Wildner.Ed
265cb0ac91aSSascha Wildner.El
266cb0ac91aSSascha Wildner.Sh RETURN VALUES
267cb0ac91aSSascha WildnerThe
268cb0ac91aSSascha Wildner.Fn atomic_cmpset
269cb0ac91aSSascha Wildnerfunction
270cb0ac91aSSascha Wildnerreturns the result of the compare operation.
271cb0ac91aSSascha WildnerThe
272cb0ac91aSSascha Wildner.Fn atomic_fetchadd ,
273cb0ac91aSSascha Wildner.Fn atomic_load ,
274cb0ac91aSSascha Wildnerand
275cb0ac91aSSascha Wildner.Fn atomic_readandclear
276cb0ac91aSSascha Wildnerfunctions
277cb0ac91aSSascha Wildnerreturn the value at the specified address.
278cb0ac91aSSascha Wildner.\".Sh EXAMPLES
279cb0ac91aSSascha Wildner.\"This example uses the
280cb0ac91aSSascha Wildner.\".Fn atomic_cmpset_acq_ptr
281cb0ac91aSSascha Wildner.\"and
282cb0ac91aSSascha Wildner.\".Fn atomic_set_ptr
283cb0ac91aSSascha Wildner.\"functions to obtain a sleep mutex and handle recursion.
284cb0ac91aSSascha Wildner.\"Since the
285cb0ac91aSSascha Wildner.\".Va mtx_lock
286cb0ac91aSSascha Wildner.\"member of a
287cb0ac91aSSascha Wildner.\".Vt "struct mtx"
288cb0ac91aSSascha Wildner.\"is a pointer, the
289cb0ac91aSSascha Wildner.\".Dq Li ptr
290cb0ac91aSSascha Wildner.\"type is used.
291cb0ac91aSSascha Wildner.\".Bd -literal
292cb0ac91aSSascha Wildner.\"/* Try to obtain mtx_lock once. */
293cb0ac91aSSascha Wildner.\"#define _obtain_lock(mp, tid)						\\
294cb0ac91aSSascha Wildner.\"	atomic_cmpset_acq_ptr(&(mp)->mtx_lock, MTX_UNOWNED, (tid))
295cb0ac91aSSascha Wildner.\"
296cb0ac91aSSascha Wildner.\"/* Get a sleep lock, deal with recursion inline. */
297cb0ac91aSSascha Wildner.\"#define _get_sleep_lock(mp, tid, opts, file, line) do {			\\
298cb0ac91aSSascha Wildner.\"	uintptr_t _tid = (uintptr_t)(tid);				\\
299cb0ac91aSSascha Wildner.\"									\\
300cb0ac91aSSascha Wildner.\"	if (!_obtain_lock(mp, tid)) {					\\
301cb0ac91aSSascha Wildner.\"		if (((mp)->mtx_lock & MTX_FLAGMASK) != _tid)		\\
302cb0ac91aSSascha Wildner.\"			_mtx_lock_sleep((mp), _tid, (opts), (file), (line));\\
303cb0ac91aSSascha Wildner.\"		else {							\\
304cb0ac91aSSascha Wildner.\"			atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSE);	\\
305cb0ac91aSSascha Wildner.\"			(mp)->mtx_recurse++;				\\
306cb0ac91aSSascha Wildner.\"		}							\\
307cb0ac91aSSascha Wildner.\"	}								\\
308cb0ac91aSSascha Wildner.\"} while (0)
309cb0ac91aSSascha Wildner.\".Ed
310cb0ac91aSSascha Wildner.Sh HISTORY
311cb0ac91aSSascha WildnerThe
312cb0ac91aSSascha Wildner.Fn atomic_add ,
313cb0ac91aSSascha Wildner.Fn atomic_clear ,
314cb0ac91aSSascha Wildner.Fn atomic_set ,
315cb0ac91aSSascha Wildnerand
316cb0ac91aSSascha Wildner.Fn atomic_subtract
317cb0ac91aSSascha Wildneroperations were first introduced in
318cb0ac91aSSascha Wildner.Fx 3.0 .
319cb0ac91aSSascha WildnerThis first set only supported the types
320cb0ac91aSSascha Wildner.Dq Li char ,
321cb0ac91aSSascha Wildner.Dq Li short ,
322cb0ac91aSSascha Wildner.Dq Li int ,
323cb0ac91aSSascha Wildnerand
324cb0ac91aSSascha Wildner.Dq Li long .
325*d42a763bSAaron LI.Pp
326cb0ac91aSSascha WildnerThe
327cb0ac91aSSascha Wildner.Fn atomic_cmpset ,
328cb0ac91aSSascha Wildner.Fn atomic_load ,
329cb0ac91aSSascha Wildner.Fn atomic_readandclear ,
330cb0ac91aSSascha Wildnerand
331cb0ac91aSSascha Wildner.Fn atomic_store
332cb0ac91aSSascha Wildneroperations were added in
333cb0ac91aSSascha Wildner.Fx 5.0 .
334cb0ac91aSSascha WildnerThe types
335cb0ac91aSSascha Wildner.Dq Li 8 ,
336cb0ac91aSSascha Wildner.Dq Li 16 ,
337cb0ac91aSSascha Wildner.Dq Li 32 ,
338cb0ac91aSSascha Wildner.\".Dq Li 64 ,
339cb0ac91aSSascha Wildnerand
340cb0ac91aSSascha Wildner.Dq Li ptr
341cb0ac91aSSascha Wildnerand all of the acquire and release variants
342cb0ac91aSSascha Wildnerwere added in
343cb0ac91aSSascha Wildner.Fx 5.0
344cb0ac91aSSascha Wildneras well.
345*d42a763bSAaron LI.Pp
346cb0ac91aSSascha WildnerThe
347cb0ac91aSSascha Wildner.Fn atomic_fetchadd
348cb0ac91aSSascha Wildneroperations were added in
349cb0ac91aSSascha Wildner.Fx 6.0 .
350*d42a763bSAaron LI.Pp
351*d42a763bSAaron LIThe relaxed variants of
352*d42a763bSAaron LI.Fn atomic_load
353*d42a763bSAaron LIand
354*d42a763bSAaron LI.Fn atomic_store
355*d42a763bSAaron LIwere added in
356*d42a763bSAaron LI.Fx 12.0
357*d42a763bSAaron LIand
358*d42a763bSAaron LI.Dx 6.5 .
359