-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LangRef] adjust IR atomics specification following C++20 model tweaks. #77263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3307,15 +3307,15 @@ Memory Model for Concurrent Operations | |
The LLVM IR does not define any way to start parallel threads of | ||
execution 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. | ||
in their presence. This model is inspired by the C++ memory model. | ||
|
||
For a more informal introduction to this model, see the :doc:`Atomics`. | ||
|
||
We define a *happens-before* partial order as the least partial order | ||
that | ||
|
||
- Is a superset of single-thread program order, and | ||
- When a *synchronizes-with* ``b``, includes an edge from ``a`` to | ||
- When ``a`` *synchronizes-with* ``b``, includes an edge from ``a`` to | ||
``b``. *Synchronizes-with* pairs are introduced by platform-specific | ||
techniques, like pthread locks, thread creation, thread joining, | ||
etc., and by atomic instructions. (See also :ref:`Atomic Memory Ordering | ||
|
@@ -3379,13 +3379,12 @@ Atomic instructions (:ref:`cmpxchg <i_cmpxchg>`, | |
:ref:`atomicrmw <i_atomicrmw>`, :ref:`fence <i_fence>`, | ||
:ref:`atomic load <i_load>`, and :ref:`atomic store <i_store>`) take | ||
ordering parameters that determine which other atomic instructions on | ||
the same address they *synchronize with*. These semantics are borrowed | ||
from Java and C++0x, but are somewhat more colloquial. If these | ||
descriptions aren't precise enough, check those specs (see spec | ||
references in the :doc:`atomics guide <Atomics>`). | ||
:ref:`fence <i_fence>` instructions treat these orderings somewhat | ||
differently since they don't take an address. See that instruction's | ||
documentation for details. | ||
the same address they *synchronize with*. These semantics implement | ||
the Java or C++ memory models; if these descriptions aren't precise | ||
enough, check those specs (see spec references in the | ||
:doc:`atomics guide <Atomics>`). :ref:`fence <i_fence>` instructions | ||
treat these orderings somewhat differently since they don't take an | ||
address. See that instruction's documentation for details. | ||
|
||
For a simpler introduction to the ordering constraints, see the | ||
:doc:`Atomics`. | ||
|
@@ -3413,33 +3412,38 @@ For a simpler introduction to the ordering constraints, see the | |
stronger) operations on the same address. If an address is written | ||
``monotonic``-ally by one thread, and other threads ``monotonic``-ally | ||
read that address repeatedly, the other threads must eventually see | ||
the write. This corresponds to the C++0x/C1x | ||
``memory_order_relaxed``. | ||
the write. This corresponds to the C++/C ``memory_order_relaxed``. | ||
``acquire`` | ||
In addition to the guarantees of ``monotonic``, a | ||
*synchronizes-with* edge may be formed with a ``release`` operation. | ||
This is intended to model C++'s ``memory_order_acquire``. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: here's a bare C++ that could do with C/C++ :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
``release`` | ||
In addition to the guarantees of ``monotonic``, if this operation | ||
writes a value which is subsequently read by an ``acquire`` | ||
operation, it *synchronizes-with* that operation. (This isn't a | ||
complete description; see the C++0x definition of a release | ||
sequence.) This corresponds to the C++0x/C1x | ||
operation, it *synchronizes-with* that operation. Furthermore, | ||
this occurs even if the value written by a ``release`` operation | ||
has been modified by a read-modify-write operation before being | ||
read. (Such a set of operations comprises a *release | ||
sequence*). This corresponds to the C++/C | ||
``memory_order_release``. | ||
``acq_rel`` (acquire+release) | ||
Acts as both an ``acquire`` and ``release`` operation on its | ||
address. This corresponds to the C++0x/C1x ``memory_order_acq_rel``. | ||
address. This corresponds to the C++/C ``memory_order_acq_rel``. | ||
``seq_cst`` (sequentially consistent) | ||
In addition to the guarantees of ``acq_rel`` (``acquire`` for an | ||
operation that only reads, ``release`` for an operation that only | ||
writes), there is a global total order on all | ||
sequentially-consistent operations on all addresses, which is | ||
consistent with the *happens-before* partial order and with the | ||
modification orders of all the affected addresses. Each | ||
sequentially-consistent operations on all addresses. Each | ||
sequentially-consistent read sees the last preceding write to the | ||
same address in this global order. This corresponds to the C++0x/C1x | ||
same address in this global order. This corresponds to the C++/C | ||
``memory_order_seq_cst`` and Java volatile. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: volatile should also get double-backticks here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
|
||
Note: this global total order is *not* guaranteed to be fully | ||
consistent with the *happens-before* partial order if | ||
non-``seq_cst`` accesses are involved. See the C++ standard | ||
`[atomics.order] <https://wg21.link/atomics.order>`_ section | ||
for more details on the exact guarantees. | ||
|
||
.. _syncscope: | ||
|
||
If an atomic operation is marked ``syncscope("singlethread")``, it only | ||
|
@@ -10754,7 +10758,13 @@ still *synchronize-with* the explicit ``fence`` and establish the | |
|
||
A ``fence`` which has ``seq_cst`` ordering, in addition to having both | ||
``acquire`` and ``release`` semantics specified above, participates in | ||
the global program order of other ``seq_cst`` operations and/or fences. | ||
the global program order of other ``seq_cst`` operations and/or | ||
fences. Furthermore, the global ordering created by a ``seq_cst`` | ||
fence must be compatible with the individual total orders of | ||
``monotonic`` (or stronger) memory accesses occurring before and after | ||
such a fence. The exact semantics of this interaction are somewhat | ||
complicated, see the C++ standard's `[atomics.order] | ||
<https://wg21.link/atomics.order>`_ section for more details. | ||
|
||
A ``fence`` instruction can also take an optional | ||
":ref:`syncscope <syncscope>`" argument. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: C/C++ is the usual formulation you see here, not C++/C
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was puzzled by
C++/C
formulation as well but was thinking whether jyknight wants to emphasize that C atomics were based on C++'s :)