diff options
Diffstat (limited to 'static/freebsd/man9/atomic.9 3.html')
| -rw-r--r-- | static/freebsd/man9/atomic.9 3.html | 613 |
1 files changed, 0 insertions, 613 deletions
diff --git a/static/freebsd/man9/atomic.9 3.html b/static/freebsd/man9/atomic.9 3.html deleted file mode 100644 index fc10c6fe..00000000 --- a/static/freebsd/man9/atomic.9 3.html +++ /dev/null @@ -1,613 +0,0 @@ -<table class="head"> - <tr> - <td class="head-ltitle">ATOMIC(9)</td> - <td class="head-vol">Kernel Developer's Manual</td> - <td class="head-rtitle">ATOMIC(9)</td> - </tr> -</table> -<div class="manual-text"> -<section class="Sh"> -<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1> -<p class="Pp"><code class="Nm">atomic_add</code>, - <code class="Nm">atomic_clear</code>, <code class="Nm">atomic_cmpset</code>, - <code class="Nm">atomic_fcmpset</code>, - <code class="Nm">atomic_fetchadd</code>, - <code class="Nm">atomic_interrupt_fence</code>, - <code class="Nm">atomic_load</code>, - <code class="Nm">atomic_readandclear</code>, - <code class="Nm">atomic_set</code>, <code class="Nm">atomic_subtract</code>, - <code class="Nm">atomic_store</code>, - <code class="Nm">atomic_thread_fence</code> — <span class="Nd">atomic - operations</span></p> -</section> -<section class="Sh"> -<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1> -<p class="Pp"><code class="In">#include - <<a class="In">machine/atomic.h</a>></code></p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_add_[acq_|rel_]<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_clear_[acq_|rel_]<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">atomic_cmpset_[acq_|rel_]<type></code>(<var class="Fa">volatile - <type> *dst</var>, <var class="Fa"><type> old</var>, - <var class="Fa"><type> new</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">atomic_fcmpset_[acq_|rel_]<type></code>(<var class="Fa">volatile - <type> *dst</var>, <var class="Fa"><type> *old</var>, - <var class="Fa"><type> new</var>);</p> -<p class="Pp"><var class="Ft"><type></var> - <br/> - <code class="Fn">atomic_fetchadd_<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_interrupt_fence</code>(<var class="Fa" style="white-space: nowrap;">void</var>);</p> -<p class="Pp"><var class="Ft"><type></var> - <br/> - <code class="Fn">atomic_load_[acq_]<type></code>(<var class="Fa" style="white-space: nowrap;">const - volatile <type> *p</var>);</p> -<p class="Pp"><var class="Ft"><type></var> - <br/> - <code class="Fn">atomic_readandclear_<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_set_[acq_|rel_]<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_subtract_[acq_|rel_]<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_store_[rel_]<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft"><type></var> - <br/> - <code class="Fn">atomic_swap_<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, - <var class="Fa" style="white-space: nowrap;"><type> v</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">atomic_testandclear_<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, <var class="Fa" style="white-space: nowrap;">u_int - v</var>);</p> -<p class="Pp"><var class="Ft">int</var> - <br/> - <code class="Fn">atomic_testandset_<type></code>(<var class="Fa" style="white-space: nowrap;">volatile - <type> *p</var>, <var class="Fa" style="white-space: nowrap;">u_int - v</var>);</p> -<p class="Pp"><var class="Ft">void</var> - <br/> - <code class="Fn">atomic_thread_fence_[acq|acq_rel|rel|seq_cst]</code>(<var class="Fa" style="white-space: nowrap;">void</var>);</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1> -<p class="Pp">Atomic operations are commonly used to implement reference counts - and as building blocks for synchronization primitives, such as mutexes.</p> -<p class="Pp" id="atomically">All of these operations are performed - <a class="permalink" href="#atomically"><i class="Em">atomically</i></a> - across multiple threads and in the presence of interrupts, meaning that they - are performed in an indivisible manner from the perspective of concurrently - running threads and interrupt handlers.</p> -<p class="Pp">On all architectures supported by <span class="Ux">FreeBSD</span>, - ordinary loads and stores of integers in cache-coherent memory are - inherently atomic if the integer is naturally aligned and its size does not - exceed the processor's word size. However, such loads and stores may be - elided from the program by the compiler, whereas atomic operations are - always performed.</p> -<p class="Pp">When atomic operations are performed on cache-coherent memory, all - operations on the same location are totally ordered.</p> -<p class="Pp" id="torn">When an atomic load is performed on a location in - cache-coherent memory, it reads the entire value that was defined by the - last atomic store to each byte of the location. An atomic load will never - return a value out of thin air. When an atomic store is performed on a - location, no other thread or interrupt handler will observe a - <a class="permalink" href="#torn"><i class="Em">torn write</i></a>, or - partial modification of the location.</p> -<p class="Pp">Except as noted below, the semantics of these operations are - almost identical to the semantics of similarly named C11 atomic - operations.</p> -<section class="Ss"> -<h2 class="Ss" id="Types"><a class="permalink" href="#Types">Types</a></h2> -<p class="Pp">Most atomic operations act upon a specific - <var class="Fa">type</var>. That type is indicated in the function name. In - contrast to C11 atomic operations, <span class="Ux">FreeBSD</span>'s atomic - operations are performed on ordinary integer types. The available types - are:</p> -<p class="Pp"></p> -<div class="Bd-indent"> -<dl class="Bl-tag Bl-compact"> - <dt id="int"><a class="permalink" href="#int"><code class="Li">int</code></a></dt> - <dd>unsigned integer</dd> - <dt id="long"><a class="permalink" href="#long"><code class="Li">long</code></a></dt> - <dd>unsigned long integer</dd> - <dt id="ptr"><a class="permalink" href="#ptr"><code class="Li">ptr</code></a></dt> - <dd>unsigned integer the size of a pointer</dd> - <dt id="32"><a class="permalink" href="#32"><code class="Li">32</code></a></dt> - <dd>unsigned 32-bit integer</dd> - <dt id="64"><a class="permalink" href="#64"><code class="Li">64</code></a></dt> - <dd>unsigned 64-bit integer</dd> -</dl> -</div> -<p class="Pp" id="atomic_add_int">For example, the function to atomically add - two integers is called - <a class="permalink" href="#atomic_add_int"><code class="Fn">atomic_add_int</code></a>().</p> -<p class="Pp">Certain architectures also provide operations for types smaller - than “<code class="Li">int</code>”.</p> -<p class="Pp"></p> -<div class="Bd-indent"> -<dl class="Bl-tag Bl-compact"> - <dt id="char"><a class="permalink" href="#char"><code class="Li">char</code></a></dt> - <dd>unsigned character</dd> - <dt id="short"><a class="permalink" href="#short"><code class="Li">short</code></a></dt> - <dd>unsigned short integer</dd> - <dt id="8"><a class="permalink" href="#8"><code class="Li">8</code></a></dt> - <dd>unsigned 8-bit integer</dd> - <dt id="16"><a class="permalink" href="#16"><code class="Li">16</code></a></dt> - <dd>unsigned 16-bit integer</dd> -</dl> -</div> -<p class="Pp">These types must not be used in machine-independent code.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Acquire_and_Release_Operations"><a class="permalink" href="#Acquire_and_Release_Operations">Acquire - and Release Operations</a></h2> -<p class="Pp">By default, a thread's accesses to different memory locations - might not be performed in - <a class="permalink" href="#program"><i class="Em" id="program">program - order</i></a>, that is, the order in which the accesses appear in the source - code. To optimize the program's execution, both the compiler and processor - might reorder the thread's accesses. However, both ensure that their - reordering of the accesses is not visible to the thread. Otherwise, the - traditional memory model that is expected by single-threaded programs would - be violated. Nonetheless, other threads in a multithreaded program, such as - the <span class="Ux">FreeBSD</span> kernel, might observe the reordering. - Moreover, in some cases, such as the implementation of synchronization - between threads, arbitrary reordering might result in the incorrect - execution of the program. To constrain the reordering that both the compiler - and processor might perform on a thread's accesses, a programmer can use - atomic operations with <i class="Em">acquire</i> and - <i class="Em">release</i> semantics.</p> -<p class="Pp" id="relaxed">Atomic operations on memory have up to three - variants. The first, or - <a class="permalink" href="#relaxed"><i class="Em">relaxed</i></a> variant, - performs the operation without imposing any ordering constraints on accesses - to other memory locations. This variant is the default. The second variant - has acquire semantics, and the third variant has release semantics.</p> -<p class="Pp" id="atomic_subtract_acq_int">An atomic operation can only have - <i class="Em">acquire</i> semantics if it performs a load from memory. When - an atomic operation has acquire semantics, a load performed as part of the - operation must have completed before any subsequent load or store (by - program order) is performed. Conversely, acquire semantics do not require - that prior loads or stores have completed before a load from the atomic - operation is performed. To denote acquire semantics, the suffix - “<code class="Li">_acq</code>” is inserted into the function - name immediately prior to the - “<code class="Li">_</code>⟨<var class="Fa">type</var>⟩” - suffix. For example, to subtract two integers ensuring that the load of the - value from memory is completed before any subsequent loads and stores are - performed, use - <a class="permalink" href="#atomic_subtract_acq_int"><code class="Fn">atomic_subtract_acq_int</code></a>().</p> -<p class="Pp" id="atomic_add_rel_long">An atomic operation can only have - <i class="Em">release</i> semantics if it performs a store to memory. When - an atomic operation has release semantics, all prior loads or stores (by - program order) must have completed before a store executed as part of the - operation that is performed. Conversely, release semantics do not require - that a store from the atomic operation must have completed before any - subsequent load or store is performed. To denote release semantics, the - suffix “<code class="Li">_rel</code>” is inserted into the - function name immediately prior to the - “<code class="Li">_</code>⟨<var class="Fa">type</var>⟩” - suffix. For example, to add two long integers ensuring that all prior loads - and stores are completed before the store of the result is performed, use - <a class="permalink" href="#atomic_add_rel_long"><code class="Fn">atomic_add_rel_long</code></a>().</p> -<p class="Pp" id="synchronizes">When a release operation by one thread - <a class="permalink" href="#synchronizes"><i class="Em">synchronizes - with</i></a> an acquire operation by another thread, usually meaning that - the acquire operation reads the value written by the release operation, then - the effects of all prior stores by the releasing thread must become visible - to subsequent loads by the acquiring thread. Moreover, the effects of all - stores (by other threads) that were visible to the releasing thread must - also become visible to the acquiring thread. These rules only apply to the - synchronizing threads. Other threads might observe these stores in a - different order.</p> -<p class="Pp">In effect, atomic operations with acquire and release semantics - establish one-way barriers to reordering that enable the implementations of - synchronization primitives to express their ordering requirements without - also imposing unnecessary ordering. For example, for a critical section - guarded by a mutex, an acquire operation when the mutex is locked and a - release operation when the mutex is unlocked will prevent any loads or - stores from moving outside of the critical section. However, they will not - prevent the compiler or processor from moving loads or stores into the - critical section, which does not violate the semantics of a mutex.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Architecture-dependent_caveats_for_compare-and-swap"><a class="permalink" href="#Architecture-dependent_caveats_for_compare-and-swap">Architecture-dependent - caveats for compare-and-swap</a></h2> -<p class="Pp">The - <a class="permalink" href="#atomic__f_cmpset__type_"><code class="Fn" id="atomic__f_cmpset__type_">atomic_[f]cmpset_<type></code></a>() - operations, specifically those without explicitly specified memory ordering, - are defined as relaxed. Consequently, a thread's accesses to memory - locations different from that of the atomic operation can be reordered in - relation to the atomic operation.</p> -<p class="Pp" id="amd64">However, the implementation on the - <a class="permalink" href="#amd64"><b class="Sy">amd64</b></a> and - <a class="permalink" href="#i386"><b class="Sy" id="i386">i386</b></a> - architectures provide sequentially consistent semantics. In particular, the - reordering mentioned above cannot occur.</p> -<p class="Pp" id="arm64/aarch64">On the - <a class="permalink" href="#arm64/aarch64"><b class="Sy">arm64/aarch64</b></a> - architecture, the operation may include either acquire semantics on the - constituent load or release semantics on the constituent store. This means - that accesses to other locations in program order before the atomic, might - be observed as executed after the load that is the part of the atomic - operation (but not after the store from the operation due to release). - Similarly, accesses after the atomic might be observed as executed before - the store.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Thread_Fence_Operations"><a class="permalink" href="#Thread_Fence_Operations">Thread - Fence Operations</a></h2> -<p class="Pp">Alternatively, a programmer can use atomic thread fence operations - to constrain the reordering of accesses. In contrast to other atomic - operations, fences do not, themselves, access memory.</p> -<p class="Pp" id="atomic_thread_fence_acq">When a fence has acquire semantics, - all prior loads (by program order) must have completed before any subsequent - load or store is performed. Thus, an acquire fence is a two-way barrier for - load operations. To denote acquire semantics, the suffix - “<code class="Li">_acq</code>” is appended to the function - name, for example, - <a class="permalink" href="#atomic_thread_fence_acq"><code class="Fn">atomic_thread_fence_acq</code></a>().</p> -<p class="Pp" id="atomic_thread_fence_rel">When a fence has release semantics, - all prior loads or stores (by program order) must have completed before any - subsequent store operation is performed. Thus, a release fence is a two-way - barrier for store operations. To denote release semantics, the suffix - “<code class="Li">_rel</code>” is appended to the function - name, for example, - <a class="permalink" href="#atomic_thread_fence_rel"><code class="Fn">atomic_thread_fence_rel</code></a>().</p> -<p class="Pp" id="atomic_thread_fence_acq_rel">Although - <a class="permalink" href="#atomic_thread_fence_acq_rel"><code class="Fn">atomic_thread_fence_acq_rel</code></a>() - implements both acquire and release semantics, it is not a full barrier. For - example, a store prior to the fence (in program order) may be completed - after a load subsequent to the fence. In contrast, - <a class="permalink" href="#atomic_thread_fence_seq_cst"><code class="Fn" id="atomic_thread_fence_seq_cst">atomic_thread_fence_seq_cst</code></a>() - implements a full barrier. Neither loads nor stores may cross this barrier - in either direction.</p> -<p class="Pp">In C11, a release fence by one thread synchronizes with an acquire - fence by another thread when an atomic load that is prior to the acquire - fence (by program order) reads the value written by an atomic store that is - subsequent to the release fence. In contrast, in - <span class="Ux">FreeBSD</span>, because of the atomicity of ordinary, - naturally aligned loads and stores, fences can also be synchronized by - ordinary loads and stores. This simplifies the implementation and use of - some synchronization primitives in <span class="Ux">FreeBSD</span>.</p> -<p class="Pp">Since neither a compiler nor a processor can foresee which - (atomic) load will read the value written by an (atomic) store, the ordering - constraints imposed by fences must be more restrictive than acquire loads - and release stores. Essentially, this is why fences are two-way - barriers.</p> -<p class="Pp">Although fences impose more restrictive ordering than acquire - loads and release stores, by separating access from ordering, they can - sometimes facilitate more efficient implementations of synchronization - primitives. For example, they can be used to avoid executing a memory - barrier until a memory access shows that some condition is satisfied.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Interrupt_Fence_Operations"><a class="permalink" href="#Interrupt_Fence_Operations">Interrupt - Fence Operations</a></h2> -<p class="Pp">The - <a class="permalink" href="#atomic_interrupt_fence"><code class="Fn" id="atomic_interrupt_fence">atomic_interrupt_fence</code></a>() - function establishes ordering between its call location and any interrupt - handler executing on the same CPU. It is modeled after the similar C11 - function - <a class="permalink" href="#atomic_signal_fence"><code class="Fn" id="atomic_signal_fence">atomic_signal_fence</code></a>(), - and adapted for the kernel environment.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Multiple_Processors"><a class="permalink" href="#Multiple_Processors">Multiple - Processors</a></h2> -<p class="Pp">In multiprocessor systems, the atomicity of the atomic operations - on memory depends on support for cache coherence in the underlying - architecture. In general, cache coherence on the default memory type, - <code class="Dv">VM_MEMATTR_DEFAULT</code>, is guaranteed by all - architectures that are supported by <span class="Ux">FreeBSD</span>. For - example, cache coherence is guaranteed on write-back memory by the amd64 and - i386 architectures. However, on some architectures, cache coherence might - not be enabled on all memory types. To determine if cache coherence is - enabled for a non-default memory type, consult the architecture's - documentation.</p> -</section> -<section class="Ss"> -<h2 class="Ss" id="Semantics"><a class="permalink" href="#Semantics">Semantics</a></h2> -<p class="Pp">This section describes the semantics of each operation using a C - like notation.</p> -<dl class="Bl-hang"> - <dt id="atomic_add"><a class="permalink" href="#atomic_add"><code class="Fn">atomic_add</code></a>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>*p += v;</pre> - </div> - </dd> - <dt id="atomic_clear"><a class="permalink" href="#atomic_clear"><code class="Fn">atomic_clear</code></a>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>*p &= ~v;</pre> - </div> - </dd> - <dt><code class="Fn">atomic_cmpset</code>(<var class="Fa">dst</var>, - <var class="Fa">old</var>, <var class="Fa">new</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>if (*dst == old) { - *dst = new; - return (1); -} else - return (0);</pre> - </div> - </dd> -</dl> -<p class="Pp" id="atomic_cmpset">Some architectures do not implement the - <a class="permalink" href="#atomic_cmpset"><code class="Fn">atomic_cmpset</code></a>() - functions for the types “<code class="Li">char</code>”, - “<code class="Li">short</code>”, - “<code class="Li">8</code>”, and - “<code class="Li">16</code>”.</p> -<dl class="Bl-hang"> - <dt><code class="Fn">atomic_fcmpset</code>(<var class="Fa">dst</var>, - <var class="Fa">*old</var>, <var class="Fa">new</var>)</dt> - <dd></dd> -</dl> -<p class="Pp" id="Compare">On architectures implementing - <a class="permalink" href="#Compare"><i class="Em">Compare And Swap</i></a> - operation in hardware, the functionality can be described as</p> -<div class="Bd Bd-indent Li"> -<pre>if (*dst == *old) { - *dst = new; - return (1); -} else { - *old = *dst; - return (0); -}</pre> -</div> -On architectures which provide - <a class="permalink" href="#Load"><i class="Em" id="Load">Load Linked/Store - Conditional</i></a> primitive, the write to <code class="Dv">*dst</code> might - also fail for several reasons, most important of which is a parallel write to - <code class="Dv">*dst</code> cache line by other CPU. In this case - <a class="permalink" href="#atomic_fcmpset"><code class="Fn" id="atomic_fcmpset">atomic_fcmpset</code></a>() - function also returns <code class="Dv">false</code>, despite -<div class="Bd Bd-indent"><code class="Li">*old == *dst</code></div> -. -<p class="Pp" id="atomic_fcmpset~2">Some architectures do not implement the - <a class="permalink" href="#atomic_fcmpset~2"><code class="Fn">atomic_fcmpset</code></a>() - functions for the types “<code class="Li">char</code>”, - “<code class="Li">short</code>”, - “<code class="Li">8</code>”, and - “<code class="Li">16</code>”.</p> -<dl class="Bl-hang"> - <dt><code class="Fn">atomic_fetchadd</code>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>tmp = *p; -*p += v; -return (tmp);</pre> - </div> - </dd> -</dl> -<p class="Pp" id="atomic_fetchadd">The - <a class="permalink" href="#atomic_fetchadd"><code class="Fn">atomic_fetchadd</code></a>() - functions are only implemented for the types - “<code class="Li">int</code>”, - “<code class="Li">long</code>” and - “<code class="Li">32</code>” and do not have any variants with - memory barriers at this time.</p> -<dl class="Bl-hang"> - <dt id="atomic_load"><a class="permalink" href="#atomic_load"><code class="Fn">atomic_load</code></a>(<var class="Fa">p</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>return (*p);</pre> - </div> - </dd> - <dt><code class="Fn">atomic_readandclear</code>(<var class="Fa">p</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>tmp = *p; -*p = 0; -return (tmp);</pre> - </div> - </dd> -</dl> -<p class="Pp" id="atomic_readandclear">The - <a class="permalink" href="#atomic_readandclear"><code class="Fn">atomic_readandclear</code></a>() - functions are not implemented for the types - “<code class="Li">char</code>”, - “<code class="Li">short</code>”, - “<code class="Li">ptr</code>”, - “<code class="Li">8</code>”, and - “<code class="Li">16</code>” and do not have any variants with - memory barriers at this time.</p> -<dl class="Bl-hang"> - <dt id="atomic_set"><a class="permalink" href="#atomic_set"><code class="Fn">atomic_set</code></a>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>*p |= v;</pre> - </div> - </dd> - <dt id="atomic_subtract"><a class="permalink" href="#atomic_subtract"><code class="Fn">atomic_subtract</code></a>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>*p -= v;</pre> - </div> - </dd> - <dt id="atomic_store"><a class="permalink" href="#atomic_store"><code class="Fn">atomic_store</code></a>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>*p = v;</pre> - </div> - </dd> - <dt><code class="Fn">atomic_swap</code>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>tmp = *p; -*p = v; -return (tmp);</pre> - </div> - </dd> -</dl> -<p class="Pp" id="atomic_swap">The - <a class="permalink" href="#atomic_swap"><code class="Fn">atomic_swap</code></a>() - functions are not implemented for the types - “<code class="Li">char</code>”, - “<code class="Li">short</code>”, - “<code class="Li">ptr</code>”, - “<code class="Li">8</code>”, and - “<code class="Li">16</code>” and do not have any variants with - memory barriers at this time.</p> -<dl class="Bl-hang"> - <dt id="atomic_testandclear"><a class="permalink" href="#atomic_testandclear"><code class="Fn">atomic_testandclear</code></a>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>bit = 1 << (v % (sizeof(*p) * NBBY)); -tmp = (*p & bit) != 0; -*p &= ~bit; -return (tmp);</pre> - </div> - </dd> -</dl> -<dl class="Bl-hang"> - <dt><code class="Fn">atomic_testandset</code>(<var class="Fa">p</var>, - <var class="Fa">v</var>)</dt> - <dd> - <div class="Bd Li"> - <pre>bit = 1 << (v % (sizeof(*p) * NBBY)); -tmp = (*p & bit) != 0; -*p |= bit; -return (tmp);</pre> - </div> - </dd> -</dl> -<p class="Pp" id="atomic_testandset">The - <a class="permalink" href="#atomic_testandset"><code class="Fn">atomic_testandset</code></a>() - and - <a class="permalink" href="#atomic_testandclear~2"><code class="Fn" id="atomic_testandclear~2">atomic_testandclear</code></a>() - functions are only implemented for the types - “<code class="Li">int</code>”, - “<code class="Li">long</code>”, “ptr”, - “<code class="Li">32</code>”, and - “<code class="Li">64</code>” and generally do not have any - variants with memory barriers at this time except for - <a class="permalink" href="#atomic_testandset_acq_long"><code class="Fn" id="atomic_testandset_acq_long">atomic_testandset_acq_long</code></a>().</p> -<p class="Pp">The type “<code class="Li">64</code>” is currently - not implemented for some of the atomic operations on the arm, i386, and - powerpc architectures.</p> -</section> -</section> -<section class="Sh"> -<h1 class="Sh" id="RETURN_VALUES"><a class="permalink" href="#RETURN_VALUES">RETURN - VALUES</a></h1> -<p class="Pp">The <code class="Fn">atomic_cmpset</code>() function returns the - result of the compare operation. The - <code class="Fn">atomic_fcmpset</code>() function returns - <code class="Dv">true</code> if the operation succeeded. Otherwise it - returns <code class="Dv">false</code> and sets <var class="Va">*old</var> to - the found value. The <code class="Fn">atomic_fetchadd</code>(), - <code class="Fn">atomic_load</code>(), - <code class="Fn">atomic_readandclear</code>(), and - <code class="Fn">atomic_swap</code>() functions return the value at the - specified address. The <code class="Fn">atomic_testandset</code>() and - <code class="Fn">atomic_testandclear</code>() function returns the result of - the test operation.</p> -</section> -<section class="Sh"> -<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1> -<p class="Pp">This example uses the - <code class="Fn">atomic_cmpset_acq_ptr</code>() and - <code class="Fn">atomic_set_ptr</code>() functions to obtain a sleep mutex - and handle recursion. Since the <var class="Va">mtx_lock</var> member of a - <var class="Vt">struct mtx</var> is a pointer, the - “<code class="Li">ptr</code>” type is used.</p> -<div class="Bd Pp Li"> -<pre>/* Try to obtain mtx_lock once. */ -#define _obtain_lock(mp, tid) \ - atomic_cmpset_acq_ptr(&(mp)->mtx_lock, MTX_UNOWNED, (tid)) - -/* Get a sleep lock, deal with recursion inline. */ -#define _get_sleep_lock(mp, tid, opts, file, line) do { \ - uintptr_t _tid = (uintptr_t)(tid); \ - \ - if (!_obtain_lock(mp, tid)) { \ - if (((mp)->mtx_lock & MTX_FLAGMASK) != _tid) \ - _mtx_lock_sleep((mp), _tid, (opts), (file), (line));\ - else { \ - atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSE); \ - (mp)->mtx_recurse++; \ - } \ - } \ -} while (0)</pre> -</div> -</section> -<section class="Sh"> -<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1> -<p class="Pp">The <code class="Fn">atomic_add</code>(), - <code class="Fn">atomic_clear</code>(), - <code class="Fn">atomic_set</code>(), and - <code class="Fn">atomic_subtract</code>() operations were introduced in - <span class="Ux">FreeBSD 3.0</span>. Initially, these operations were - defined on the types “<code class="Li">char</code>”, - “<code class="Li">short</code>”, - “<code class="Li">int</code>”, and - “<code class="Li">long</code>”.</p> -<p class="Pp">The <code class="Fn">atomic_cmpset</code>(), - <code class="Fn">atomic_load_acq</code>(), - <code class="Fn">atomic_readandclear</code>(), and - <code class="Fn">atomic_store_rel</code>() operations were added in - <span class="Ux">FreeBSD 5.0</span>. Simultaneously, the acquire and release - variants were introduced, and support was added for operation on the types - “<code class="Li">8</code>”, - “<code class="Li">16</code>”, - “<code class="Li">32</code>”, - “<code class="Li">64</code>”, and - “<code class="Li">ptr</code>”.</p> -<p class="Pp">The <code class="Fn">atomic_fetchadd</code>() operation was added - in <span class="Ux">FreeBSD 6.0</span>.</p> -<p class="Pp">The <code class="Fn">atomic_swap</code>() and - <code class="Fn">atomic_testandset</code>() operations were added in - <span class="Ux">FreeBSD 10.0</span>.</p> -<p class="Pp">The <code class="Fn">atomic_testandclear</code>() and - <code class="Fn">atomic_thread_fence</code>() operations were added in - <span class="Ux">FreeBSD 11.0</span>.</p> -<p class="Pp">The relaxed variants of <code class="Fn">atomic_load</code>() and - <code class="Fn">atomic_store</code>() were added in - <span class="Ux">FreeBSD 12.0</span>.</p> -<p class="Pp">The <code class="Fn">atomic_interrupt_fence</code>() operation was - added in <span class="Ux">FreeBSD 13.0</span>.</p> -</section> -</div> -<table class="foot"> - <tr> - <td class="foot-date">December 16, 2024</td> - <td class="foot-os">FreeBSD 15.0</td> - </tr> -</table> |
