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:
Eli Friedman 2011-08-22 21:35:27 +00:00
parent 838130e3b9
commit 234bccd194
2 changed files with 34 additions and 19 deletions

View File

@ -121,9 +121,10 @@ void f(int* a) {
</pre> </pre>
<p>However, LLVM is not allowed to transform the former to the latter: it could <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. indirectly introduce undefined behavior if another thread can access x at
(This example is particularly of interest because before the concurrency model the same time. (This example is particularly of interest because before the
was implemented, LLVM would perform this transformation.)</p> concurrency model was implemented, LLVM would perform this
transformation.)</p>
<p>Note that speculative loads are allowed; a load which <p>Note that speculative loads are allowed; a load which
is part of a race returns <code>undef</code>, but does not have undefined 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, <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; 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 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> <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 <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 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 essentially a regular load or store. If there is a race on a given memory
from multiple threads at the same time, the resulting loads return location, loads from that location return undef.</p>
'undef'.</p>
<dl> <dl>
<dt>Relevant standard</dt> <dt>Relevant standard</dt>
<dd>This is intended to match shared variables in C/C++, and to be used <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 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> <dt>Notes for frontends</dt>
<dd>The rule is essentially that all memory accessed with basic loads and <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 stores by multiple threads should be protected by a lock or other

View File

@ -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 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> 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 <p>We define a <i>happens-before</i> partial order as the least partial order
that</p> that</p>
<ul> <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: <p>Given that definition, <var>R<sub>byte</sub></var> is defined as follows:
<ul> <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 <var>R<sub>byte</sub></var>, <var>R<sub>byte</sub></var> returns
<tt>undef</tt> for that byte. <tt>undef</tt> for that byte.
<li>Otherwise, if <var>R<sub>byte</sub></var> may see exactly one write, <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 that determines which other atomic instructions on the same address they
<i>synchronize with</i>. These semantics are borrowed from Java and C++0x, <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, 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. treat these orderings somewhat differently since they don't take an address.
See that instruction's documentation for details.</p> 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> <dl>
<dt><code>unordered</code></dt> <dt><code>unordered</code></dt>
<dd>The set of values that can be read is governed by the happens-before <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 <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 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 <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 eventually see the write. This corresponds to the C++0x/C1x
variables.</dd> <code>memory_order_relaxed</code>.</dd>
<dt><code>acquire</code></dt> <dt><code>acquire</code></dt>
<dd>In addition to the guarantees of <code>monotonic</code>, if this operation <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 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> <dt><code>release</code></dt>
<dd>In addition to the guarantees of <code>monotonic</code>, <dd>In addition to the guarantees of <code>monotonic</code>,
a <i>synchronizes-with</i> edge may be formed by an <code>acquire</code> a <i>synchronizes-with</i> edge may be formed with an <code>acquire</code>
operation.</dd> 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 <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> <dt><code>seq_cst</code> (sequentially consistent)</dt><dd>
<dd>In addition to the guarantees of <code>acq_rel</code> <dd>In addition to the guarantees of <code>acq_rel</code>
(<code>acquire</code> for an operation which only reads, <code>release</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 sequentially-consistent operations on all addresses, which is consistent with
the <i>happens-before</i> partial order and with the modification orders of the <i>happens-before</i> partial order and with the modification orders of
all the affected addresses. Each sequentially-consistent read sees the last all the affected addresses. Each sequentially-consistent read sees the last
preceding write to the same address in this global order. This is intended preceding write to the same address in this global order. This corresponds
to model C++'s sequentially-consistent atomic variables and Java's volatile to the C++0x/C1x <code>memory_order_seq_cst</code> and Java volatile.</dd>
shared variables.</dd>
</dl> </dl>
<p id="singlethread">If an atomic operation is marked <code>singlethread</code>, <p id="singlethread">If an atomic operation is marked <code>singlethread</code>,