*/ } ul /* Whole unordered list */ { } ul li /* Unordered list item */ { } ol /* Whole ordered list */ { } ol li /* Ordered list item */ { } hr {} /* ---- Some span elements --- */ sub /* Subscripts. Pandoc: H~2~O */ { } sup /* Superscripts. Pandoc: The 2^nd^ try. */ { } em /* Emphasis. Markdown: *emphasis* or _emphasis_ */ { } em > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } blockquote > * > p > ins > em /* Emphasis within emphasis: *This is all *emphasized* except that* */ { font-style: normal; } /* ---- Links (anchors) ---- */ a /* All links */ { /* Keep links clean. On screen, they are colored; in print, they do nothing anyway. */ text-decoration: none; } @media screen { a:hover { /* On hover, we indicate a bit more that it is a link. */ text-decoration: underline; } } @media print { a { /* In print, a colored link is useless, so un-style it. */ color: black; background: transparent; } a[href^="http://"]:after, a[href^="https://"]:after { /* However, links that go somewhere else, might be useful to the reader, so for http and https links, print the URL after what was the link text in parens */ content: " (" attr(href) ") "; font-size: 90%; } } /* ---- Images ---- */ img { /* Let it be inline left/right where it wants to be, but verticality make it in the middle to look nicer, but opinions differ, and if in a multi-line paragraph, it might not be so great. */ vertical-align: middle; } div.figure /* Pandoc figure-style image */ { /* Center the image and caption */ margin-left: auto; margin-right: auto; text-align: center; font-style: italic; } p.caption /* Pandoc figure-style caption within div.figure */ { /* Inherits div.figure props by default */ } /* ---- Code blocks and spans ---- */ pre, code { background-color: #fdf7ee; /* BEGIN word wrap */ /* Need all the following to word wrap instead of scroll box */ /* This will override the overflow:auto if present */ white-space: pre-wrap; /* css-3 */ white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */ white-space: -pre-wrap; /* Opera 4-6 */ white-space: -o-pre-wrap; /* Opera 7 */ word-wrap: break-word; /* Internet Explorer 5.5+ */ /* END word wrap */ } pre /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.5em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 1px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.5em; margin-right: 0.5em; } pre.yacc, code.yacc { background-color: #f0f0f0; } pre.yacc /* Code blocks */ { /* Distinguish pre blocks from other text by more than the font with a background tint. */ padding: 0.0em; /* Since we have a background color */ border-radius: 5px; /* Softens it */ /* Give it a some definition */ border: 0px solid #aaa; /* Set it off left and right, seems to look a bit nicer when we have a background */ margin-left: 0.0em; margin-right: 0.0em; } @media screen { pre { white-space: pre; /* Dotted looks better on screen and solid seems to print better. */ border: 1px dotted #777; } } code /* All inline code spans */ { } p > code, li > code /* Code spans in paragraphs and tight lists */ { /* Pad a little from adjacent text */ padding-left: 2px; padding-right: 2px; } li > p code /* Code span in a loose list */ { /* We have room for some more background color above and below */ padding: 2px; } span.option { color: blue; text-decoration: underline; } /* ---- Math ---- */ span.math /* Pandoc inline math default and --jsmath inline math */ { /* Tried font-style:italic here, and it messed up MathJax rendering in some browsers. Maybe don't mess with at all. */ } div.math /* Pandoc --jsmath display math */ { } span.LaTeX /* Pandoc --latexmathml math */ { } eq /* Pandoc --gladtex math */ { } /* ---- Tables ---- */ /* A clean textbook-like style with horizontal lines above and below and under the header. Rows highlight on hover to help scanning the table on screen. */ table { border-collapse: collapse; border-spacing: 0; /* IE 6 */ border-bottom: 2pt solid #000; border-top: 2pt solid #000; /* The caption on top will not have a bottom-border */ /* Center */ margin-left: auto; margin-right: auto; } thead /* Entire table header */ { border-bottom: 1pt solid #000; background-color: #eee; /* Does this BG print well? */ } tr.header /* Each header row */ { } tbody /* Entire table body */ { } /* Table body rows */ tr { } tr.odd:hover, tr.even:hover /* Use .odd and .even classes to avoid styling rows in other tables */ { background-color: #eee; } /* Odd and even rows */ tr.odd {} tr.even {} td, th /* Table cells and table header cells */ { vertical-align: top; /* Word */ vertical-align: baseline; /* Others */ padding-left: 0.5em; padding-right: 0.5em; padding-top: 0.2em; padding-bottom: 0.2em; } /* Removes padding on left and right of table for a tight look. Good if thead has no background color*/ /* tr td:last-child, tr th:last-child { padding-right: 0; } tr td:first-child, tr th:first-child { padding-left: 0; } */ th /* Table header cells */ { font-weight: bold; } tfoot /* Table footer (what appears here if caption is on top?) */ { } caption /* This is for a table caption tag, not the p.caption Pandoc uses in a div.figure */ { caption-side: top; border: none; font-size: 0.9em; font-style: italic; text-align: center; margin-bottom: 0.3em; /* Good for when on top */ padding-bottom: 0.2em; } /* ---- Definition lists ---- */ dl /* The whole list */ { border-top: 2pt solid black; padding-top: 0.5em; border-bottom: 2pt solid black; } dt /* Definition term */ { font-weight: bold; } dd+dt /* 2nd or greater term in the list */ { border-top: 1pt solid black; padding-top: 0.5em; } dd /* A definition */ { margin-bottom: 0.5em; } dd+dd /* 2nd or greater definition of a term */ { border-top: 1px solid black; /* To separate multiple definitions */ } /* ---- Footnotes ---- */ a.footnote, a.footnoteRef { /* Pandoc, MultiMarkdown footnote links */ font-size: small; vertical-align: text-top; } a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown, ?? footnote back links */ { } @media print { a[href^="#fnref"], a.reversefootnote /* Pandoc, MultiMarkdown */ { /* Don't display these at all in print since the arrow is only something to click on */ display: none; } } div.footnotes /* Pandoc footnotes div at end of the document */ { } div.footnotes li[id^="fn"] /* A footnote item within that div */ { } table tr td,th { border-right: 1px solid; border-left: 1px solid; } /* You can class stuff as "noprint" to not print. Useful since you can't set this media conditional inside an HTML element's style attribute (I think), and you don't want to make another stylesheet that imports this one and adds a class just to do this. */ @media print { .noprint { display:none; } }
2025-06-29
integration into IS ISO/IEC 9899:202y
document number | date | comment |
---|---|---|
n3607 | 202505 | this document |
This document is based on Defang and
deprecate memory_order::consume
by Hans Boehm, which has been accepted into C++26.
It is widely accepted that the current definition of the concept of
consume operations and of the corresponding memory order memory_order_consume
(memory_order::consume
for C++) in the C standard is not useful: all current compilers
essentially map it to memory_order_acquire
. We propose to
completely remove the notion from the C standard and to phase out the
associated features.
Memory order “consume” is a concept that is meant to be less restrictive than “acquire” by relaxing the requirement on the receiving side of an atomic operation. The relaxation is basically that instead of locally relying on the sequenced before relation for the ordering (which is a temporal relationship) it is based on a concept of “dependency”, the term referring in that case to a data-flow dependency.
Difficulties with the concept appear to be multiple:
kill_dependency
macro (and additionally the [[carries_dependency]]
attribute in C++).It is also widely accepted that memory_order_consume
could have
frequent and important use cases in many large code bases. For example,
the Linux kernel makes extensive use of RCU. To avoid over-constraining
memory order for something like RCU on architectures like ARM and Power
something like memory_order_consume
is
required. Some core Android code similarly relies on dependency-based
ordering.
On the other hand, there are strong arguments that we are not likely to introduce a new facility that can benefit significantly from the existing wording, and that we therefor should remove it:
memory_order_consume
.
memory_order_acquire
(and memory_order_seq_cst
) loads that, for common
micro-architectures and use-cases, perform similarly to memory_order_relaxed
. The accepted C++ paper has a
comparison of microbenchmark between memory_order_relaxed
vs. memory_order_seq_cst
load times on some ARM
implementations.memory_order_relaxed
seems to have carried
the day for the remaining use cases.There are other problems concerning memory consistency that arise
from the use of memory_order_relaxed
and memory_order_seq_cst
that are
not handled by this paper here. The whole has been
described in
It identifies several problems: non-conformance of some specific
implementations, seq_cst
fences,
release sequences, out-of-thin-air, consume.
C++ has already integrated changes that deal with two of these problems:
These provide satisfactory solutions, namely for the problem of consume operations (as proposed in this paper) and for a problem with release sequences. Since the second problem is orthogonal to what is proposed here, we will deal with this in a seperate paper. For convenience, the suggested wording below already marks the text that would be suppressed by this second change.
Some solutions for the other problems are already integrated into C++ (which version?), but are unfortunately not yet satisfactory and will need more discussion in the community, including implementers. So we don’t think that it would be wise to follow C++, yet.
When not using consume operations, a whole bunch of definitions in the C standard become unused, namely:
memory_order_consume
, andkill_dependency
.The first three can be safely removed. The latter two should be kept for backwards compatibility.
memory_order_consume
becomes a synonym for
memory_order_acquire
, because that is
what implementations currently do and because this is conforming to
C23.kill_dependency
simply
returns its argument. Again, this is what implementations do and what is
conforming to C23.Both identifiers are marked to be obsolescent.
New text is underlined green, removed text is
stroke-out red. For information, other changes that have
already brought to C++ are underlined.
5.2.2.5 Multi-threaded executions and data races
…
5 The library defines atomic operations (7.17) and operations on mutexes (7.30.4) that are specially identified as synchronization operations. These operations play a special role in making assignments in one thread visible to another. A synchronization operation on one or more memory locations is one of an acquire operation, a release operation, or both an acquire and release operation
, or a consume operation. A synchronization operation without an associated memory location is a fence and can be either an acquire fence, a release fence, or both an acquire and release fence. In addition, there are relaxed atomic operations, which are not synchronization operations, and atomic read-modify-write operations, which have special characteristics.
6 NOTE 2 For example, a call that acquires a mutex will perform an acquire operation on the locations composing the mutex. Correspondingly, a call that releases the same mutex will perform a release operation on those same locations. Informally, performing a release operation on A forces prior side effects on other memory locations to become visible to other threads that later perform an acquire
or consumeoperation on A. Relaxed atomic operations are not included as synchronization operations although, like synchronization operations, they cannot contribute to data races.
…
10 A release sequence headed by a release operation A on an atomic object M is a maximal contiguous sub-sequence of side effects in the modification order of M , where the first operation is A and every subsequent operation either is performed by the same thread that performed the release or is an atomic read-modify-write operation.
11 Certain library calls synchronize with other library calls performed by another thread. In particular, an atomic operation A that performs a release operation on an object M synchronizes with an atomic operation B that performs an acquire operation on M and reads a value written by any side effect in the release sequence headed by A.
…
14 An evaluation A carries a dependency11) to an evaluation B if:
- the value of A is used as an operand of B, unless:
- B is an invocation of the
kill_dependency
macro,- A is the left operand of a
&&
or||
operator,- A is the left operand of a
?:
operator, or- A is the left operand of a
,
operator;
or
- A writes a scalar object or bit-field M , B reads from M the value written by A, and A is sequenced before B, or
- for some evaluation X, A carries a dependency to X and X carries a dependency to B.
11) The “carries a dependency” relation is a subset of the “sequenced before” relation, and is similarly strictly intra-thread.
15 An evaluation A is dependency-ordered before12) an evaluation B if:
- A performs a release operation on an atomic object M , and, in another thread, B performs a consume operation on M and reads a value written by any side effect in the release sequence headed by A, or
- for some evaluation X, A is dependency-ordered before X and X carries a dependency to B.
12) The “dependency-ordered before” relation is analogous to the “synchronizes with” relation, but uses release/consume in place of release/acquire.
16 An evaluation A inter-thread happens before an evaluation B if A synchronizes with B, A is dependency-ordered before B, or, for some evaluation X:
- A synchronizes with X and X is sequenced before B,
- A is sequenced before X and X inter-thread happens before B, or
- A inter-thread happens before X and X inter-thread happens before B.
17 NOTE 7 The “inter-thread happens before” relation describes arbitrary concatenations of “sequenced before”, “synchronizes with”, and “dependency-ordered before” relationships, with two exceptions. The first exception is that a concatenation is not permitted to end with “dependency-ordered before” followed by “sequenced before”. The reason for this limitation is that a consume operation participating in a “dependency-ordered before” relationship provides ordering only with respect to operations to which this consume operation carries a dependency. The reason that this limitation applies only to the end of such a concatenation is that any subsequent release operation will provide the required ordering for a prior consume operation. The second exception is that a concatenation is not permitted to consist entirely of “sequenced before”. The reasons for this limitation are (1) to permit “inter-thread happens> before” to be transitively closed and (2) the “happens before” relation, defined subsequently in this subclause, provides for relationships consisting entirely of “sequenced before”.
18 An evaluation A happens before an evaluation B if A is sequenced before B or A inter-thread happens before B. The implementation shall ensure that no program execution demonstrates a cycle in the “happens> before” relation.
14′ An evaluation A happens before an evaluation B (or, equivalently, B happens after A) if either
- A is sequenced before B, or
- A synchronizes with B, or
- A happens before X and X happens before B.
19 NOTE 8 This cycle would otherwise be possible only through the use of consume operations.
15′ NOTE 7′ An evaluation cannot happen before itself.
7.17 Atomics <stdatomic.h>
…
7.17.3 Order and consistency
7.17.3.1 General
1 The enumerated type
memory_order
specifies the detailed regular (non-atomic) memory synchronization operations as defined in 5.2.2.5 and may provide for operation ordering. Its enumeration constants are as follows:XXX)
XXX) The use of the enumeration constant memory_order_consume
is obsolescent. See
“future library directions” (7.35.11).
memory_order_relaxed |
memory_order_consume |
memory_order_acquire |
memory_order_release |
memory_order_acq_rel |
memory_order_seq_cst |
2 For
memory_order_relaxed
, no operation orders memory.
3 For
memory_order_release
,memory_order_acq_rel
, andmemory_order_seq_cst
, a store operation performs a release operation on the affected memory location.
4 For
memory_order_acquire
,memory_order_consume
,memory_order_acq_rel
, andmemory_order_seq_cst
, a load operation performs an acquire operation on the affected memory location.
5 Formemory_order_consume
, a load operation performs a consume operation on the affected memory location.
…
7.17.3.2 The kill_dependency macro
…
Description
2 The
kill_dependency
macroterminates a dependency chain; the argument does not carry a dependency to the return valuehas no other effect than its result.
Returns
3 The
kill_dependency
macro returns the value ofy
.
4 NOTE The kill_dependency
macro is an
obsolescent feature (7.35.11).
…
7.35 Future library directions
…
7.35.11 Atomics <stdatomic.h>
1 Macros that begin with
ATOMIC_
and an uppercase letter are potentially reserved identifiers and may be added to the macros defined in the<stdatomic.h>
header. Typedef names that begin with eitheratomic_
ormemory_
, and a lowercase letter are potentially reserved identifiers and may be added to the declarations in the <stdatomic.h> header. Enumeration constants that begin withmemory_order_
and a lowercase letter are potentially reserved identifiers and may be added to the definition of thememory_order
type in the<stdatomic.h>
header; the enumeration constantmemory_order_consume
is an obsolescent feature. Function names that begin withatomic_
and a lowercase letter are potentially reserved identifiers and may be added to the declarations in the<stdatomic.h>
header. Thekill_dependency
macro is an obsolescent feature.
The changes proposed have some modified paragraphs in common with n3606.
In particular, we would have to watch to remove memory_order_consume
in 7.17.3.1,
p12′, NOTE 2′ of that paper.
The wording changes have been integrated into the standard source in the following branch:
https://gitlab.gwdg.de/iso-c/draft/-/tree/consume