mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-03 09:21:02 +00:00
Some minor wording updates and cross-linking for atomic docs. Explicitly note that we don't try to portably define what volatile in LLVM IR means.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138274 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
838130e3b9
commit
234bccd194
@ -121,9 +121,10 @@ void f(int* a) {
|
||||
</pre>
|
||||
|
||||
<p>However, LLVM is not allowed to transform the former to the latter: it could
|
||||
introduce undefined behavior if another thread can access x at the same time.
|
||||
(This example is particularly of interest because before the concurrency model
|
||||
was implemented, LLVM would perform this transformation.)</p>
|
||||
indirectly introduce undefined behavior if another thread can access x at
|
||||
the same time. (This example is particularly of interest because before the
|
||||
concurrency model was implemented, LLVM would perform this
|
||||
transformation.)</p>
|
||||
|
||||
<p>Note that speculative loads are allowed; a load which
|
||||
is part of a race returns <code>undef</code>, but does not have undefined
|
||||
@ -177,7 +178,7 @@ void f(int* a) {
|
||||
<p>In order to achieve a balance between performance and necessary guarantees,
|
||||
there are six levels of atomicity. They are listed in order of strength;
|
||||
each level includes all the guarantees of the previous level except for
|
||||
Acquire/Release.</p>
|
||||
Acquire/Release. (See also <a href="LangRef.html#ordering">LangRef</a>.)</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
@ -188,15 +189,15 @@ void f(int* a) {
|
||||
|
||||
<p>NotAtomic is the obvious, a load or store which is not atomic. (This isn't
|
||||
really a level of atomicity, but is listed here for comparison.) This is
|
||||
essentially a regular load or store. If code accesses a memory location
|
||||
from multiple threads at the same time, the resulting loads return
|
||||
'undef'.</p>
|
||||
essentially a regular load or store. If there is a race on a given memory
|
||||
location, loads from that location return undef.</p>
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This is intended to match shared variables in C/C++, and to be used
|
||||
in any other context where memory access is necessary, and
|
||||
a race is impossible.
|
||||
a race is impossible. (The precise definition is in
|
||||
<a href="LangRef.html#memmodel">LangRef</a>.)
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>The rule is essentially that all memory accessed with basic loads and
|
||||
stores by multiple threads should be protected by a lock or other
|
||||
|
@ -1497,6 +1497,9 @@ or to register signal handlers. Nonetheless, there are platform-specific
|
||||
ways to create them, and we define LLVM IR's behavior in their presence. This
|
||||
model is inspired by the C++0x memory model.</p>
|
||||
|
||||
<p>For a more informal introduction to this model, see the
|
||||
<a href="Atomics.html">LLVM Atomic Instructions and Concurrency Guide</a>.
|
||||
|
||||
<p>We define a <i>happens-before</i> partial order as the least partial order
|
||||
that</p>
|
||||
<ul>
|
||||
@ -1533,7 +1536,12 @@ any write to the same byte, except:</p>
|
||||
|
||||
<p>Given that definition, <var>R<sub>byte</sub></var> is defined as follows:
|
||||
<ul>
|
||||
<li>If there is no write to the same byte that happens before
|
||||
<li>If <var>R</var> is volatile, the result is target-dependent. (Volatile
|
||||
is supposed to give guarantees which can support
|
||||
<code>sig_atomic_t</code> in C/C++, and may be used for accesses to
|
||||
addresses which do not behave like normal memory. It does not generally
|
||||
provide cross-thread synchronization.)
|
||||
<li>Otherwise, if there is no write to the same byte that happens before
|
||||
<var>R<sub>byte</sub></var>, <var>R<sub>byte</sub></var> returns
|
||||
<tt>undef</tt> for that byte.
|
||||
<li>Otherwise, if <var>R<sub>byte</sub></var> may see exactly one write,
|
||||
@ -1590,10 +1598,15 @@ as if it writes to the relevant surrounding bytes.
|
||||
that determines which other atomic instructions on the same address they
|
||||
<i>synchronize with</i>. These semantics are borrowed from Java and C++0x,
|
||||
but are somewhat more colloquial. If these descriptions aren't precise enough,
|
||||
check those specs. <a href="#i_fence"><code>fence</code></a> instructions
|
||||
check those specs (see spec references in the
|
||||
<a href="Atomic.html#introduction">atomics guide</a>).
|
||||
<a href="#i_fence"><code>fence</code></a> instructions
|
||||
treat these orderings somewhat differently since they don't take an address.
|
||||
See that instruction's documentation for details.</p>
|
||||
|
||||
<p>For a simpler introduction to the ordering constraints, see the
|
||||
<a href="Atomics.html">LLVM Atomic Instructions and Concurrency Guide</a>.</p>
|
||||
|
||||
<dl>
|
||||
<dt><code>unordered</code></dt>
|
||||
<dd>The set of values that can be read is governed by the happens-before
|
||||
@ -1618,18 +1631,20 @@ address's modification order. This disallows reordering of
|
||||
<code>monotonic</code> (or stronger) operations on the same address. If an
|
||||
address is written <code>monotonic</code>ally by one thread, and other threads
|
||||
<code>monotonic</code>ally read that address repeatedly, the other threads must
|
||||
eventually see the write. This is intended to model C++'s relaxed atomic
|
||||
variables.</dd>
|
||||
eventually see the write. This corresponds to the C++0x/C1x
|
||||
<code>memory_order_relaxed</code>.</dd>
|
||||
<dt><code>acquire</code></dt>
|
||||
<dd>In addition to the guarantees of <code>monotonic</code>, if this operation
|
||||
reads a value written by a <code>release</code> atomic operation, it
|
||||
<i>synchronizes-with</i> that operation.</dd>
|
||||
<i>synchronizes-with</i> that operation. This corresponds to the C++0x/C1x
|
||||
<code>memory_order_acquire</code>.</dd>
|
||||
<dt><code>release</code></dt>
|
||||
<dd>In addition to the guarantees of <code>monotonic</code>,
|
||||
a <i>synchronizes-with</i> edge may be formed by an <code>acquire</code>
|
||||
operation.</dd>
|
||||
a <i>synchronizes-with</i> edge may be formed with an <code>acquire</code>
|
||||
operation. This is intended to model C++'s <code>memory_order_release</code>.</dd>
|
||||
<dt><code>acq_rel</code> (acquire+release)</dt><dd>Acts as both an
|
||||
<code>acquire</code> and <code>release</code> operation on its address.</dd>
|
||||
<code>acquire</code> and <code>release</code> operation on its address.
|
||||
This corresponds to the C++0x/C1x <code>memory_order_acq_rel</code>.</dd>
|
||||
<dt><code>seq_cst</code> (sequentially consistent)</dt><dd>
|
||||
<dd>In addition to the guarantees of <code>acq_rel</code>
|
||||
(<code>acquire</code> for an operation which only reads, <code>release</code>
|
||||
@ -1637,9 +1652,8 @@ for an operation which only writes), there is a global total order on all
|
||||
sequentially-consistent operations on all addresses, which is consistent with
|
||||
the <i>happens-before</i> partial order and with the modification orders of
|
||||
all the affected addresses. Each sequentially-consistent read sees the last
|
||||
preceding write to the same address in this global order. This is intended
|
||||
to model C++'s sequentially-consistent atomic variables and Java's volatile
|
||||
shared variables.</dd>
|
||||
preceding write to the same address in this global order. This corresponds
|
||||
to the C++0x/C1x <code>memory_order_seq_cst</code> and Java volatile.</dd>
|
||||
</dl>
|
||||
|
||||
<p id="singlethread">If an atomic operation is marked <code>singlethread</code>,
|
||||
|
Loading…
Reference in New Issue
Block a user