2 Copyright 1988-2022 Free Software Foundation, Inc.
3 This is part of the GCC manual.
4 For copying conditions, see the copyright.rst file.
8 Legacy __sync Built-in Functions for Atomic Memory Access
9 *********************************************************
11 The following built-in functions
12 are intended to be compatible with those described
13 in the Intel Itanium Processor-specific Application Binary Interface,
14 section 7.4. As such, they depart from normal GCC practice by not using
15 the :samp:`__builtin_` prefix and also by being overloaded so that they
16 work on multiple types.
18 The definition given in the Intel documentation allows only for the use of
19 the types ``int``, ``long``, ``long long`` or their unsigned
20 counterparts. GCC allows any scalar type that is 1, 2, 4 or 8 bytes in
21 size other than the C type ``_Bool`` or the C++ type ``bool``.
22 Operations on pointer arguments are performed as if the operands were
23 of the ``uintptr_t`` type. That is, they are not scaled by the size
24 of the type to which the pointer points.
26 These functions are implemented in terms of the :samp:`__atomic`
27 builtins (see :ref:`atomic-builtins`). They should not be used for new
28 code which should use the :samp:`__atomic` builtins instead.
30 Not all operations are supported by all target processors. If a particular
31 operation cannot be implemented on the target processor, a warning is
32 generated and a call to an external function is generated. The external
33 function carries the same name as the built-in version,
34 with an additional suffix
35 :samp:`_{n}` where :samp:`{n}` is the size of the data type.
37 .. ??? Should we have a mechanism to suppress this warning? This is almost
38 useful for implementing the operation under the control of an external
41 In most cases, these built-in functions are considered a :dfn:`full barrier`.
43 no memory operand is moved across the operation, either forward or
44 backward. Further, instructions are issued as necessary to prevent the
45 processor from speculating loads across the operation and from queuing stores
48 All of the routines are described in the Intel documentation to take
49 'an optional list of variables protected by the memory barrier'. It's
50 not clear what is meant by that; it could mean that *only* the
51 listed variables are protected, or it could mean a list of additional
52 variables to be protected. The list is ignored by GCC which treats it as
53 empty. GCC interprets an empty list as meaning that all globally
54 accessible variables should be protected.
58 type __sync_fetch_and_add (type *ptr, type value, ...)
59 type __sync_fetch_and_sub (type *ptr, type value, ...)
60 type __sync_fetch_and_or (type *ptr, type value, ...)
61 type __sync_fetch_and_and (type *ptr, type value, ...)
62 type __sync_fetch_and_xor (type *ptr, type value, ...)
63 type __sync_fetch_and_nand (type *ptr, type value, ...)
65 .. index:: __sync_fetch_and_add
66 .. index:: __sync_fetch_and_sub
67 .. index:: __sync_fetch_and_or
68 .. index:: __sync_fetch_and_and
69 .. index:: __sync_fetch_and_xor
70 .. index:: __sync_fetch_and_nand
72 These built-in functions perform the operation suggested by the name, and
73 returns the value that had previously been in memory. That is, operations
74 on integer operands have the following semantics. Operations on pointer
75 arguments are performed as if the operands were of the ``uintptr_t``
76 type. That is, they are not scaled by the size of the type to which
81 { tmp = *ptr; *ptr op= value; return tmp; }
82 { tmp = *ptr; *ptr = ~(tmp & value); return tmp; } // nand
84 The object pointed to by the first argument must be of integer or pointer
85 type. It must not be a boolean type.
88 GCC 4.4 and later implement ``__sync_fetch_and_nand``
89 as ``*ptr = ~(tmp & value)`` instead of ``*ptr = ~tmp & value``.
93 type __sync_add_and_fetch (type *ptr, type value, ...)
94 type __sync_sub_and_fetch (type *ptr, type value, ...)
95 type __sync_or_and_fetch (type *ptr, type value, ...)
96 type __sync_and_and_fetch (type *ptr, type value, ...)
97 type __sync_xor_and_fetch (type *ptr, type value, ...)
98 type __sync_nand_and_fetch (type *ptr, type value, ...)
100 .. index:: __sync_add_and_fetch
101 .. index:: __sync_sub_and_fetch
102 .. index:: __sync_or_and_fetch
103 .. index:: __sync_and_and_fetch
104 .. index:: __sync_xor_and_fetch
105 .. index:: __sync_nand_and_fetch
107 These built-in functions perform the operation suggested by the name, and
108 return the new value. That is, operations on integer operands have
109 the following semantics. Operations on pointer operands are performed as
110 if the operand's type were ``uintptr_t``.
114 { *ptr op= value; return *ptr; }
115 { *ptr = ~(*ptr & value); return *ptr; } // nand
117 The same constraints on arguments apply as for the corresponding
118 ``__sync_op_and_fetch`` built-in functions.
121 GCC 4.4 and later implement ``__sync_nand_and_fetch``
122 as ``*ptr = ~(*ptr & value)`` instead of
123 ``*ptr = ~*ptr & value``.
125 .. function:: bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)
126 .. function:: type __sync_val_compare_and_swap (type *ptr, type oldval, type newval, ...)
128 These built-in functions perform an atomic compare and swap.
129 That is, if the current
130 value of ``*ptr`` is :samp:`{oldval}`, then write :samp:`{newval}` into
133 The 'bool' version returns ``true`` if the comparison is successful and
134 :samp:`{newval}` is written. The 'val' version returns the contents
135 of ``*ptr`` before the operation.
137 .. function:: __sync_synchronize (...)
139 This built-in function issues a full memory barrier.
141 .. function:: type __sync_lock_test_and_set (type *ptr, type value, ...)
143 This built-in function, as described by Intel, is not a traditional test-and-set
144 operation, but rather an atomic exchange operation. It writes :samp:`{value}`
145 into ``*ptr``, and returns the previous contents of
148 Many targets have only minimal support for such locks, and do not support
149 a full exchange operation. In this case, a target may support reduced
150 functionality here by which the *only* valid value to store is the
151 immediate constant 1. The exact value actually stored in ``*ptr``
152 is implementation defined.
154 This built-in function is not a full barrier,
155 but rather an :dfn:`acquire barrier`.
156 This means that references after the operation cannot move to (or be
157 speculated to) before the operation, but previous memory stores may not
158 be globally visible yet, and previous memory loads may not yet be
161 .. function:: void __sync_lock_release (type *ptr, ...)
163 This built-in function releases the lock acquired by
164 ``__sync_lock_test_and_set``.
165 Normally this means writing the constant 0 to ``*ptr``.
167 This built-in function is not a full barrier,
168 but rather a :dfn:`release barrier`.
169 This means that all previous memory stores are globally visible, and all
170 previous memory loads have been satisfied, but following memory reads
171 are not prevented from being speculated to before the barrier.