Provided by: freebsd-manpages_11.1-3_all bug

NAME

       atomic_add,     atomic_clear,     atomic_cmpset,     atomic_fcmpset,     atomic_fetchadd,    atomic_load,
       atomic_readandclear, atomic_set, atomic_subtract, atomic_store — atomic operations

SYNOPSIS

       #include <sys/types.h>
       #include <machine/atomic.h>

       void
       atomic_add_[acq_|rel_]<type>(volatile <type> *p, <type> v);

       void
       atomic_clear_[acq_|rel_]<type>(volatile <type> *p, <type> v);

       int
       atomic_cmpset_[acq_|rel_]<type>(volatile <type> *dst, <type> old, <type> new);

       int
       atomic_fcmpset_[acq_|rel_]<type>(volatile <type> *dst, <type> *old, <type> new);

       <type>
       atomic_fetchadd_<type>(volatile <type> *p, <type> v);

       <type>
       atomic_load_acq_<type>(volatile <type> *p);

       <type>
       atomic_readandclear_<type>(volatile <type> *p);

       void
       atomic_set_[acq_|rel_]<type>(volatile <type> *p, <type> v);

       void
       atomic_subtract_[acq_|rel_]<type>(volatile <type> *p, <type> v);

       void
       atomic_store_rel_<type>(volatile <type> *p, <type> v);

       <type>
       atomic_swap_<type>(volatile <type> *p, <type> v);

       int
       atomic_testandclear_<type>(volatile <type> *p, u_int v);

       int
       atomic_testandset_<type>(volatile <type> *p, u_int v);

DESCRIPTION

       Each of the atomic operations is guaranteed to be atomic across multiple threads and 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.

   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:

             int    unsigned integer
             long   unsigned long integer
             ptr    unsigned integer the size of a pointer
             32     unsigned 32-bit integer
             64     unsigned 64-bit integer

       For example, the function to atomically add two integers is called atomic_add_int().

       Certain architectures also provide operations for types smaller than “int”.

             char   unsigned character
             short  unsigned short integer
             8      unsigned 8-bit integer
             16     unsigned 16-bit integer

       These  must  not  be  used in MI code because the instructions to implement them efficiently might not be
       available.

   Acquire and Release Operations
       By default, a thread's accesses to different memory locations might not be performed  in  program  order,
       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 FreeBSD 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, the thread should use atomic operations with acquire and release semantics.

       Most  of  the  atomic operations on memory have three variants.  The first variant performs the operation
       without imposing any ordering constraints on memory accesses to other locations.  The second variant  has
       acquire  semantics,  and the third variant has release semantics.  In effect, operations with acquire and
       release semantics establish one-way barriers to reordering.

       When an atomic operation has acquire semantics, the effects 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 the atomic operation is  performed.   To  denote
       acquire  semantics,  the  suffix  “_acq”  is  inserted  into  the  function name immediately prior to the
       “_type⟩” suffix.  For example, to subtract two integers ensuring that subsequent loads and stores happen
       after the subtraction is performed, use atomic_subtract_acq_int().

       When an atomic operation has release semantics, the effects of all prior  loads  or  stores  (by  program
       order)  must  have  completed  before  the  operation is performed.  Conversely, release semantics do not
       require that the effects of the atomic operation must have completed before any subsequent load or  store
       is  performed.   To  denote  release  semantics,  the  suffix  “_rel”  is inserted into the function name
       immediately prior to the “_type⟩” suffix.  For example, to add two long integers ensuring that all prior
       loads and stores happen before the addition, use atomic_add_rel_long().

       The one-way barriers provided by acquire and release  operations  allow  the  implementations  of  common
       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.

   Multiple Processors
       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,
       VM_MEMATTR_DEFAULT, is guaranteed by all architectures that are supported by FreeBSD.  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.

   Semantics
       This section describes the semantics of each operation using a C like notation.

       atomic_add(p, v)
               *p += v;

       atomic_clear(p, v)
               *p &= ~v;

       atomic_cmpset(dst, old, new)
               if (*dst == old) {
                       *dst = new;
                       return (1);
               } else
                       return (0);

       The atomic_cmpset() functions are not implemented for the types “char”, “short”, “8”, and “16”.

       atomic_fcmpset(dst, *old, new)

       On  architectures implementing Compare And Swap operation in hardware, the functionality can be described
       as
             if (*dst == *old) {
                     *dst = new;
                     return (1);
             } else {
                     *old = *dst;
                     return (0);
             }
       On architectures which provide Load Linked/Store Conditional primitive, the write to *dst might also fail
       for several reasons, most important of which is a parallel write to *dst cache line  by  other  CPU.   In
       this case atomic_fcmpset() function also returns false, despite
             *old == *dst.

       The atomic_fcmpset() functions are not implemented for the types “char”, “short”, “8”, and “16”.

       atomic_fetchadd(p, v)
               tmp = *p;
               *p += v;
               return (tmp);

       The atomic_fetchadd() functions are only implemented for the types “int”, “long” and “32” and do not have
       any variants with memory barriers at this time.

       atomic_load(p)
               return (*p);

       The atomic_load() functions are only provided with acquire memory barriers.

       atomic_readandclear(p)
               tmp = *p;
               *p = 0;
               return (tmp);

       The  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.

       atomic_set(p, v)
               *p |= v;

       atomic_subtract(p, v)
               *p -= v;

       atomic_store(p, v)
               *p = v;

       The atomic_store() functions are only provided with release memory barriers.

       atomic_swap(p, v)
               tmp = *p;
               *p = v;
               return (tmp);

       The atomic_swap() 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.

       atomic_testandclear(p, v)
               bit = 1 << (v % (sizeof(*p) * NBBY));
               tmp = (*p & bit) != 0;
               *p &= ~bit;
               return (tmp);

       atomic_testandset(p, v)
               bit = 1 << (v % (sizeof(*p) * NBBY));
               tmp = (*p & bit) != 0;
               *p |= bit;
               return (tmp);

       The  atomic_testandset()  and  atomic_testandclear()  functions are only implemented for the types “int”,
       “long” and “32” and do not have any variants with memory barriers at this time.

       The type “64” is currently not implemented for any of the atomic operations on the arm, i386, and powerpc
       architectures.

RETURN VALUES

       The atomic_cmpset() function returns the result of the compare operation.  The atomic_fcmpset()  function
       returns  true  if  the operation succeeded.  Otherwise it returns false and sets *old to the found value.
       The atomic_fetchadd(), atomic_load(), atomic_readandclear(), and atomic_swap() functions return the value
       at the specified address.  The atomic_testandset() and atomic_testandclear() function returns the  result
       of the test operation.

EXAMPLES

       This  example uses the atomic_cmpset_acq_ptr() and atomic_set_ptr() functions to obtain a sleep mutex and
       handle recursion.  Since the mtx_lock member of a struct mtx is a pointer, the “ptr” type is used.

       /* 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)

HISTORY

       The atomic_add(), atomic_clear(), atomic_set(), and atomic_subtract() operations were first introduced in
       FreeBSD 3.0.  This first  set  only  supported  the  types  “char”,  “short”,  “int”,  and  “long”.   The
       atomic_cmpset(),  atomic_load(),  atomic_readandclear(),  and  atomic_store()  operations  were  added in
       FreeBSD 5.0.  The types “8”, “16”, “32”, “64”, and “ptr” and all of the acquire and release variants were
       added in FreeBSD 5.0 as  well.   The  atomic_fetchadd()  operations  were  added  in  FreeBSD  6.0.   The
       atomic_swap()  and  atomic_testandset()  operations  were  added  in FreeBSD 10.0.  atomic_testandclear()
       operation was added in FreeBSD 11.0.

Debian                                             Jan 3, 2017                                         ATOMIC(9)