summaryrefslogtreecommitdiffstats
path: root/share
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2000-11-13 20:08:17 +0000
committerjhb <jhb@FreeBSD.org>2000-11-13 20:08:17 +0000
commit6e89ba0697fd1827c140661b520f6725d0df0795 (patch)
treec129b95a179857bcb201d128c9fb86ec26a02c57 /share
parent7e6e41a3824ce33a72e1f2aee5745a5babac7d29 (diff)
downloadFreeBSD-src-6e89ba0697fd1827c140661b520f6725d0df0795.zip
FreeBSD-src-6e89ba0697fd1827c140661b520f6725d0df0795.tar.gz
Add a manpage to document the atomic operations including a quick treatment
of memory barriers and the newish atomic variants that include them. Reviewed by: sheldonh
Diffstat (limited to 'share')
-rw-r--r--share/man/man9/Makefile10
-rw-r--r--share/man/man9/atomic.9286
2 files changed, 295 insertions, 1 deletions
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index a4d3008..7421c10 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -11,7 +11,7 @@ MAN9= CONDSPLASSERT.9 KASSERT.9 MD5.9 SPLASSERT.9 \
VOP_PATHCONF.9 VOP_PRINT.9 VOP_RDWR.9 VOP_READDIR.9 \
VOP_READLINK.9 VOP_REALLOCBLKS.9 VOP_REMOVE.9 VOP_RENAME.9 \
VOP_STRATEGY.9 \
- at_exit.9 at_fork.9 bios.9 boot.9 buf.9 cd.9 copy.9 \
+ at_exit.9 at_fork.9 atomic.9 bios.9 boot.9 buf.9 cd.9 copy.9 \
devfs_add_devswf.9 devfs_link.9 devfs_remove_dev.9 devstat.9 \
devtoname.9 fetch.9 ifnet.9 inittodr.9 intro.9 kernacc.9 malloc.9 \
make_dev.9 microseq.9 mi_switch.9 mutex.9 namei.9 panic.9 pfil.9 physio.9 \
@@ -56,6 +56,14 @@ MLINKS+=VOP_OPENCLOSE.9 VOP_OPEN.9
MLINKS+=VOP_RDWR.9 VOP_READ.9
MLINKS+=VOP_RDWR.9 VOP_WRITE.9
MLINKS+=VOP_REMOVE.9 VOP_RMDIR.9
+MLINKS+=atomic.9 atomic_add.9
+MLINKS+=atomic.9 atomic_clear.9
+MLINKS+=atomic.9 atomic_cmpset.9
+MLINKS+=atomic.9 atomic_load.9
+MLINKS+=atomic.9 atomic_readandclear.9
+MLINKS+=atomic.9 atomic_set.9
+MLINKS+=atomic.9 atomic_subtract.9
+MLINKS+=atomic.9 atomic_store.9
MLINKS+=at_exit.9 rm_at_exit.9
MLINKS+=at_fork.9 rm_at_fork.9
MLINKS+=copy.9 copyin.9 copy.9 copyinstr.9 copy.9 copyout.9 copy.9 copystr.9
diff --git a/share/man/man9/atomic.9 b/share/man/man9/atomic.9
new file mode 100644
index 0000000..eae8712
--- /dev/null
+++ b/share/man/man9/atomic.9
@@ -0,0 +1,286 @@
+.\" Copyright (c) 2000 John H. Baldwin
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 27, 2000
+.Os
+.Dt ATOMIC 9
+.Sh NAME
+.Nm atomic_add ,
+.Nm atomic_clear ,
+.Nm atomic_cmpset ,
+.Nm atomic_load ,
+.Nm atomic_readandclear ,
+.Nm atomic_set ,
+.Nm atomic_subtract ,
+.Nm atomic_store
+.Nd atomic operations
+.Sh SYNOPSIS
+.Fd #include <machine/atomic.h>
+.Ft void
+.Fn atomic_add{acq_,rel_,}_<type> "volatile <type> *p" "<type> v"
+.Ft void
+.Fn atomic_clear{acq_,rel_,}_<type> "volatile <type> *p" "<type> v"
+.Ft int
+.Fo atomic_cmpset{acq_,rel_,}_<type>
+.Fa "volatile <type> *dst"
+.Fa "<type> old"
+.Fa "<type> new"
+.Fc
+.Ft <type>
+.Fn atomic_load_acq_<type> "volatile <type> *p"
+.Ft <type>
+.Fn atomic_readandclear_<type> "volatile <type> *p"
+.Ft void
+.Fn atomic_set{acq_,rel_,}_<type> "volatile <type> *p" "<type> v"
+.Ft void
+.Fn atomic_subtract{acq_,rel_},_<type> "volatile <type> *p" "<type> v"
+.Ft void
+.Fn atomic_store_rel_<type> "volatile <type> *p" "<type> v"
+.Sh DESCRIPTION
+Each of the atomic operations is guaranteed to be atomic in the presence of
+interrupts.
+They can be used to implement reference counts or as building blocks for more
+advanced synchronization primitives such as mutexes.
+.Ss Types
+Each atomic operation operates on a specific type.
+The type to use is indicated in the function name.
+The available types that can be used are:
+.Bl -tag -offset indent -width short
+.It char
+unsigned character
+.It short
+unsigned short integer
+.It int
+unsigned integer
+.It long
+unsigned long integer
+.It ptr
+unsigned integer the size of a pointer
+.It 8
+unsigned 8-bit integer
+.It 16
+unsigned 16-bit integer
+.It 32
+unsigned 32-bit integer
+.It 64
+unsigned 64-bit integer
+.El
+.Pp
+For example, the function to atomically add two integers is called
+.Fn atomic_add_int .
+.Ss Memory Barriers
+Memory barriers are used to guarantee the order the order of data accesses in
+two ways.
+First, they specify hints to the compiler to not re-order or optimize the
+operations.
+Secondly, on architectures that do not guarantee ordered data accesses,
+special instructions or special variants of instructions are used to indicate
+to the processor that data accesses need to occur in a certain order.
+As a result, most of the atomic operations have three variants in order to
+include optional memory barriers.
+The first form just performs the operation without any explicit barriers.
+The second form uses a read memory barrier, and the final variant uses a write
+memory barrier.
+.Pp
+The second variant of each operation includes a read memory barrier.
+This barrier ensures that the effects of this operation are completed before the
+effects of any later data accesses.
+As a result, the operation is said to have acquire semantics as it acquires a
+pseudo-lock requiring further operations to wait until it has completed.
+To denote this, the suffix
+.Dq _acq
+is inserted into the function name immediately prior to the
+.Em _type
+suffix.
+For example, to subtract two integers ensuring that any later writes will
+happen after the subtraction is performed, use
+.Fn atomic_subtract_acq_int .
+.Pp
+The third variant of each operation includes a write memory barrier.
+This ensures that all effects of all previous data accesses are completed
+before this operation takes place.
+As a result, the operation is said to have release semantics as it releases
+any pending data accesses to be completed before its operation is performed.
+To denote this, the suffix
+.Dq _rel
+is inserted into the function name immediately prior to the
+.Em _type
+suffix.
+For example, to add two long integers ensuring that all previous
+writes will happen first, use
+.Fn atomic_add_rel_long .
+.Pp
+A practical example of using memory barriers is to ensure that data accesses
+that are protected by a lock are all performed while the lock is held.
+To achieve this, one would use a read barrier when acquiring the lock to
+guarantee that the lock is held before any protected operations are performed.
+Finally, one would use a write barrier when releasing the lock to ensure that
+all of the protected operations are completed before the lock is released.
+.Pp
+.Ss Multiple Processors
+The current set of atomic operations do not necessarily guarantee atomicity
+across multiple processors.
+To guarantee atomicity across processors, not only does the individual
+operation need to be atomic on the processor performing the operation, but the
+the result of the operation needs to be pushed out to stable storage and the
+caches of all other processors on the system need to invalidate any cache
+lines that include the affected memory region.
+On the
+.Tn i386
+architecture, the cache coherency model requires that the hardware perform
+this task, thus the atomic operations are atomic across multiple processors.
+On the
+.Tn ia64
+architecture, coherency is only guaranteed for pages that are configured to
+using a caching policy of either uncached or write back.
+.Ss Semantics
+This section describes the semantics of each operation using a C like notation.
+.Bl -hang
+.It Fn atomic_add "p" "v"
+.Bd -literal
+*p += v;
+.Ed
+.It Fn atomic_clear "p" "v"
+.Bd -literal
+*p &= ~v;
+.Ed
+.It Fn atomic_cmpset "dst" "old" "new"
+.Bd -literal
+if (*dst == old) {
+ *dst = new;
+ return 1;
+} else
+ return 0;
+.Ed
+.El
+.Pp
+The
+.Fn atomic_cmpset
+functions are not implemented for the types char, short, 8, and 16.
+.Bl -hang
+.It Fn atomic_load "addr"
+.Bd -literal
+return (*addr)
+.Ed
+.El
+.Pp
+The
+.Fn atomic_load
+functions always have acquire semantics.
+.Bl -hang
+.It Fn atomic_readandclear "addr"
+.Bd -literal
+temp = *addr;
+*addr = 0;
+return (temp);
+.Ed
+.El
+.Pp
+The
+.Fn atomic_readandclear
+functions are not implemented for the types char, short, ptr, 8, and 16 and do
+not have any variants with memory barriers at this time.
+.Bl -hang
+.It Fn atomic_set "p" "v"
+.Bd -literal
+*p |= v;
+.Ed
+.It Fn atomic_subtract "p" "v"
+.Bd -literal
+*p -= v;
+.Ed
+.It Fn atomic_store "p" "v"
+.Bd -literal
+*p = v;
+.Ed
+.El
+.Pp
+The
+.Fn atomic_store
+functions always have release semantics.
+.Pp
+The type
+.Dq 64
+is currently not implemented for any of the atomic operations on the
+.Tn i386
+architecture.
+.Sh RETURN VALUES
+.Fn atomic_cmpset
+returns the result of the compare operation.
+.Fn atomic_load
+and
+.Fn atomic_readandclear
+return the value at the specified address.
+.Sh EXAMPLES
+This example uses the
+.Fn atomic_cmpset_acq_ptr
+and
+.Fn atomic_set_ptr
+functions to obtain a sleep mutex and handle recursion.
+Since the
+.Va mtx_lock
+member of a
+.Li struct mtx
+is a pointer, the
+.Dq ptr
+type is used.
+.Bd -literal
+#define _obtain_lock(mp, tid) \\
+ atomic_cmpset_acq_ptr(&(mp)->mtx_lock, (void *)MTX_UNOWNED, (tid))
+
+/* Get a sleep lock, deal with recursion inline. */
+#define _getlock_sleep(mp, tid, type) do { \\
+ if (!_obtain_lock(mp, tid)) { \\
+ if (((mp)->mtx_lock & MTX_FLAGMASK) != ((uintptr_t)(tid)))\\
+ mtx_enter_hard(mp, (type) & MTX_HARDOPTS, 0); \\
+ else { \\
+ atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSE); \\
+ (mp)->mtx_recurse++; \\
+ } \\
+ } \\
+} while (0)
+.Ed
+.Sh HISTORY
+The
+.Fn atomic_add ,
+.Fn atomic_clear ,
+.Fn atomic_set ,
+and
+.Fn atomic_subtract
+operations were first introduced in
+.Fx 3.0 .
+This first set only suppored the types char, short, int, and long.
+The
+.Fn atomic_cmpset ,
+.Fn atomic_load ,
+.Fn atomic_readandclear ,
+and
+.Fn atomic_store
+operations were added in
+.Fx 5.0 .
+The types 8, 16, 32, 64, and ptr and all of the acquire and release variants
+were added in
+.Fx 5.0
+as well.
OpenPOWER on IntegriCloud