You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
11 KiB
HTML
158 lines
11 KiB
HTML
4 years ago
|
<html lang="en">
|
||
|
<head>
|
||
|
<title>__sync Builtins - Using the GNU Compiler Collection (GCC)</title>
|
||
|
<meta http-equiv="Content-Type" content="text/html">
|
||
|
<meta name="description" content="Using the GNU Compiler Collection (GCC)">
|
||
|
<meta name="generator" content="makeinfo 4.13">
|
||
|
<link title="Top" rel="start" href="index.html#Top">
|
||
|
<link rel="up" href="C-Extensions.html#C-Extensions" title="C Extensions">
|
||
|
<link rel="prev" href="Offsetof.html#Offsetof" title="Offsetof">
|
||
|
<link rel="next" href="_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins" title="__atomic Builtins">
|
||
|
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
|
||
|
<!--
|
||
|
Copyright (C) 1988-2015 Free Software Foundation, Inc.
|
||
|
|
||
|
Permission is granted to copy, distribute and/or modify this document
|
||
|
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||
|
any later version published by the Free Software Foundation; with the
|
||
|
Invariant Sections being ``Funding Free Software'', the Front-Cover
|
||
|
Texts being (a) (see below), and with the Back-Cover Texts being (b)
|
||
|
(see below). A copy of the license is included in the section entitled
|
||
|
``GNU Free Documentation License''.
|
||
|
|
||
|
(a) The FSF's Front-Cover Text is:
|
||
|
|
||
|
A GNU Manual
|
||
|
|
||
|
(b) The FSF's Back-Cover Text is:
|
||
|
|
||
|
You have freedom to copy and modify this GNU Manual, like GNU
|
||
|
software. Copies published by the Free Software Foundation raise
|
||
|
funds for GNU development.-->
|
||
|
<meta http-equiv="Content-Style-Type" content="text/css">
|
||
|
<style type="text/css"><!--
|
||
|
pre.display { font-family:inherit }
|
||
|
pre.format { font-family:inherit }
|
||
|
pre.smalldisplay { font-family:inherit; font-size:smaller }
|
||
|
pre.smallformat { font-family:inherit; font-size:smaller }
|
||
|
pre.smallexample { font-size:smaller }
|
||
|
pre.smalllisp { font-size:smaller }
|
||
|
span.sc { font-variant:small-caps }
|
||
|
span.roman { font-family:serif; font-weight:normal; }
|
||
|
span.sansserif { font-family:sans-serif; font-weight:normal; }
|
||
|
--></style>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="node">
|
||
|
<a name="__sync-Builtins"></a>
|
||
|
<a name="g_t_005f_005fsync-Builtins"></a>
|
||
|
<p>
|
||
|
Next: <a rel="next" accesskey="n" href="_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins">__atomic Builtins</a>,
|
||
|
Previous: <a rel="previous" accesskey="p" href="Offsetof.html#Offsetof">Offsetof</a>,
|
||
|
Up: <a rel="up" accesskey="u" href="C-Extensions.html#C-Extensions">C Extensions</a>
|
||
|
<hr>
|
||
|
</div>
|
||
|
|
||
|
<h3 class="section">6.50 Legacy <code>__sync</code> Built-in Functions for Atomic Memory Access</h3>
|
||
|
|
||
|
<p>The following built-in functions
|
||
|
are intended to be compatible with those described
|
||
|
in the <cite>Intel Itanium Processor-specific Application Binary Interface</cite>,
|
||
|
section 7.4. As such, they depart from the normal GCC practice of using
|
||
|
the ‘<samp><span class="samp">__builtin_</span></samp>’ prefix, and further that they are overloaded such that
|
||
|
they work on multiple types.
|
||
|
|
||
|
<p>The definition given in the Intel documentation allows only for the use of
|
||
|
the types <code>int</code>, <code>long</code>, <code>long long</code> as well as their unsigned
|
||
|
counterparts. GCC allows any integral scalar or pointer type that is
|
||
|
1, 2, 4 or 8 bytes in length.
|
||
|
|
||
|
<p>Not all operations are supported by all target processors. If a particular
|
||
|
operation cannot be implemented on the target processor, a warning is
|
||
|
generated and a call to an external function is generated. The external
|
||
|
function carries the same name as the built-in version,
|
||
|
with an additional suffix
|
||
|
‘<samp><span class="samp">_</span><var>n</var></samp>’ where <var>n</var> is the size of the data type.
|
||
|
|
||
|
<!-- ??? Should we have a mechanism to suppress this warning? This is almost -->
|
||
|
<!-- useful for implementing the operation under the control of an external -->
|
||
|
<!-- mutex. -->
|
||
|
<p>In most cases, these built-in functions are considered a <dfn>full barrier</dfn>.
|
||
|
That is,
|
||
|
no memory operand is moved across the operation, either forward or
|
||
|
backward. Further, instructions are issued as necessary to prevent the
|
||
|
processor from speculating loads across the operation and from queuing stores
|
||
|
after the operation.
|
||
|
|
||
|
<p>All of the routines are described in the Intel documentation to take
|
||
|
“an optional list of variables protected by the memory barrier”. It's
|
||
|
not clear what is meant by that; it could mean that <em>only</em> the
|
||
|
following variables are protected, or it could mean that these variables
|
||
|
should in addition be protected. At present GCC ignores this list and
|
||
|
protects all variables that are globally accessible. If in the future
|
||
|
we make some use of this list, an empty list will continue to mean all
|
||
|
globally accessible variables.
|
||
|
|
||
|
<dl>
|
||
|
<dt><var>type</var><code> __sync_fetch_and_add (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_fetch_and_sub (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_fetch_and_or (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_fetch_and_and (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_fetch_and_xor (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_fetch_and_nand (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dd><a name="index-g_t_005f_005fsync_005ffetch_005fand_005fadd-3519"></a><a name="index-g_t_005f_005fsync_005ffetch_005fand_005fsub-3520"></a><a name="index-g_t_005f_005fsync_005ffetch_005fand_005for-3521"></a><a name="index-g_t_005f_005fsync_005ffetch_005fand_005fand-3522"></a><a name="index-g_t_005f_005fsync_005ffetch_005fand_005fxor-3523"></a><a name="index-g_t_005f_005fsync_005ffetch_005fand_005fnand-3524"></a>These built-in functions perform the operation suggested by the name, and
|
||
|
returns the value that had previously been in memory. That is,
|
||
|
|
||
|
<pre class="smallexample"> { tmp = *ptr; *ptr <var>op</var>= value; return tmp; }
|
||
|
{ tmp = *ptr; *ptr = ~(tmp & value); return tmp; } // nand
|
||
|
</pre>
|
||
|
<p><em>Note:</em> GCC 4.4 and later implement <code>__sync_fetch_and_nand</code>
|
||
|
as <code>*ptr = ~(tmp & value)</code> instead of <code>*ptr = ~tmp & value</code>.
|
||
|
|
||
|
<br><dt><var>type</var><code> __sync_add_and_fetch (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_sub_and_fetch (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_or_and_fetch (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_and_and_fetch (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_xor_and_fetch (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dt><var>type</var><code> __sync_nand_and_fetch (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dd><a name="index-g_t_005f_005fsync_005fadd_005fand_005ffetch-3525"></a><a name="index-g_t_005f_005fsync_005fsub_005fand_005ffetch-3526"></a><a name="index-g_t_005f_005fsync_005for_005fand_005ffetch-3527"></a><a name="index-g_t_005f_005fsync_005fand_005fand_005ffetch-3528"></a><a name="index-g_t_005f_005fsync_005fxor_005fand_005ffetch-3529"></a><a name="index-g_t_005f_005fsync_005fnand_005fand_005ffetch-3530"></a>These built-in functions perform the operation suggested by the name, and
|
||
|
return the new value. That is,
|
||
|
|
||
|
<pre class="smallexample"> { *ptr <var>op</var>= value; return *ptr; }
|
||
|
{ *ptr = ~(*ptr & value); return *ptr; } // nand
|
||
|
</pre>
|
||
|
<p><em>Note:</em> GCC 4.4 and later implement <code>__sync_nand_and_fetch</code>
|
||
|
as <code>*ptr = ~(*ptr & value)</code> instead of
|
||
|
<code>*ptr = ~*ptr & value</code>.
|
||
|
|
||
|
<br><dt><code>bool __sync_bool_compare_and_swap (</code><var>type</var><code> *ptr, </code><var>type</var><code> oldval, </code><var>type</var><code> newval, ...)</code><dt><var>type</var><code> __sync_val_compare_and_swap (</code><var>type</var><code> *ptr, </code><var>type</var><code> oldval, </code><var>type</var><code> newval, ...)</code><dd><a name="index-g_t_005f_005fsync_005fbool_005fcompare_005fand_005fswap-3531"></a><a name="index-g_t_005f_005fsync_005fval_005fcompare_005fand_005fswap-3532"></a>These built-in functions perform an atomic compare and swap.
|
||
|
That is, if the current
|
||
|
value of <code>*</code><var>ptr</var> is <var>oldval</var>, then write <var>newval</var> into
|
||
|
<code>*</code><var>ptr</var>.
|
||
|
|
||
|
<p>The “bool” version returns true if the comparison is successful and
|
||
|
<var>newval</var> is written. The “val” version returns the contents
|
||
|
of <code>*</code><var>ptr</var> before the operation.
|
||
|
|
||
|
<br><dt><code>__sync_synchronize (...)</code><dd><a name="index-g_t_005f_005fsync_005fsynchronize-3533"></a>This built-in function issues a full memory barrier.
|
||
|
|
||
|
<br><dt><var>type</var><code> __sync_lock_test_and_set (</code><var>type</var><code> *ptr, </code><var>type</var><code> value, ...)</code><dd><a name="index-g_t_005f_005fsync_005flock_005ftest_005fand_005fset-3534"></a>This built-in function, as described by Intel, is not a traditional test-and-set
|
||
|
operation, but rather an atomic exchange operation. It writes <var>value</var>
|
||
|
into <code>*</code><var>ptr</var>, and returns the previous contents of
|
||
|
<code>*</code><var>ptr</var>.
|
||
|
|
||
|
<p>Many targets have only minimal support for such locks, and do not support
|
||
|
a full exchange operation. In this case, a target may support reduced
|
||
|
functionality here by which the <em>only</em> valid value to store is the
|
||
|
immediate constant 1. The exact value actually stored in <code>*</code><var>ptr</var>
|
||
|
is implementation defined.
|
||
|
|
||
|
<p>This built-in function is not a full barrier,
|
||
|
but rather an <dfn>acquire barrier</dfn>.
|
||
|
This means that references after the operation cannot move to (or be
|
||
|
speculated to) before the operation, but previous memory stores may not
|
||
|
be globally visible yet, and previous memory loads may not yet be
|
||
|
satisfied.
|
||
|
|
||
|
<br><dt><code>void __sync_lock_release (</code><var>type</var><code> *ptr, ...)</code><dd><a name="index-g_t_005f_005fsync_005flock_005frelease-3535"></a>This built-in function releases the lock acquired by
|
||
|
<code>__sync_lock_test_and_set</code>.
|
||
|
Normally this means writing the constant 0 to <code>*</code><var>ptr</var>.
|
||
|
|
||
|
<p>This built-in function is not a full barrier,
|
||
|
but rather a <dfn>release barrier</dfn>.
|
||
|
This means that all previous memory stores are globally visible, and all
|
||
|
previous memory loads have been satisfied, but following memory reads
|
||
|
are not prevented from being speculated to before the barrier.
|
||
|
</dl>
|
||
|
|
||
|
</body></html>
|
||
|
|