Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
ATOMIC(9)	       FreeBSD Kernel Developer's Manual	     ATOMIC(9)

NAME
     atomic_add, atomic_clear, atomic_cmpset, 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);

     _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 sin-
     gle-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 syn-
     chronization 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, oper-
     ations with acquire and release semantics establish one-way barriers to
     reordering.

     When an atomic operation has acquire semantics, the effects of the	opera-
     tion 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 per-
     formed.  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 opera-
     tion 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 proces-
     sor 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 mem-
     ory depends on support for	cache coherence	in the underlying architec-
     ture.  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 architec-
     tures, 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_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 barri-
     ers.

     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 vari-
     ants 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	barri-
     ers.

     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	opera-
     tions on the arm, i386, and powerpc architectures.

RETURN VALUES
     The atomic_cmpset() function returns the result of	the compare operation.
     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()	func-
     tions 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() opera-
     tions were	added in FreeBSD 10.0.	atomic_testandclear() operation	was
     added in FreeBSD 11.0.

FreeBSD	11.1			 May 12, 2016			  FreeBSD 11.1

NAME | SYNOPSIS | DESCRIPTION | RETURN VALUES | EXAMPLES | HISTORY

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=atomic&sektion=9&manpath=FreeBSD+11.0-RELEASE+and+Ports>

home | help