From Jason Turner

[intro.races]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmphci_u2_s/{from.md → to.md} +73 -137
tmp/tmphci_u2_s/{from.md → to.md} RENAMED
@@ -9,27 +9,37 @@ below.
9
  Much of this subclause is motivated by the desire to support atomic
10
  operations with explicit and detailed visibility constraints. However,
11
  it also implicitly supports a simpler view for more restricted
12
  programs. — *end note*]
13
 
14
- Two expression evaluations *conflict* if one of them modifies a memory
15
- location [[intro.memory]] and the other one reads or modifies the same
16
- memory location.
 
 
 
 
 
 
 
 
 
 
17
 
18
  The library defines a number of atomic operations [[atomics]] and
19
  operations on mutexes [[thread]] that are specially identified as
20
  synchronization operations. These operations play a special role in
21
  making assignments in one thread visible to another. A synchronization
22
- operation on one or more memory locations is either a consume operation,
23
- an acquire operation, a release operation, or both an acquire and
24
- release operation. A synchronization operation without an associated
25
- memory location is a fence and can be either an acquire fence, a release
26
- fence, or both an acquire and release fence. In addition, there are
27
- relaxed atomic operations, which are not synchronization operations, and
28
- atomic read-modify-write operations, which have special characteristics.
29
 
30
- [*Note 2*: For example, a call that acquires a mutex will perform an
31
  acquire operation on the locations comprising the mutex.
32
  Correspondingly, a call that releases the same mutex will perform a
33
  release operation on those same locations. Informally, performing a
34
  release operation on A forces prior side effects on other memory
35
  locations to become visible to other threads that later perform a
@@ -38,11 +48,11 @@ not synchronization operations even though, like synchronization
38
  operations, they cannot contribute to data races. — *end note*]
39
 
40
  All modifications to a particular atomic object M occur in some
41
  particular total order, called the *modification order* of M.
42
 
43
- [*Note 3*: There is a separate order for each atomic object. There is
44
  no requirement that these can be combined into a single total order for
45
  all objects. In general this will be impossible since different threads
46
  can observe modifications to different objects in inconsistent
47
  orders. — *end note*]
48
 
@@ -54,181 +64,107 @@ subsequent operation is an atomic read-modify-write operation.
54
  Certain library calls *synchronize with* other library calls performed
55
  by another thread. For example, an atomic store-release synchronizes
56
  with a load-acquire that takes its value from the store
57
  [[atomics.order]].
58
 
59
- [*Note 4*: Except in the specified cases, reading a later value does
60
  not necessarily ensure visibility as described below. Such a requirement
61
  would sometimes interfere with efficient implementation. — *end note*]
62
 
63
- [*Note 5*: The specifications of the synchronization operations define
64
  when one reads the value written by another. For atomic objects, the
65
  definition is clear. All operations on a given mutex occur in a single
66
  total order. Each mutex acquisition “reads the value written” by the
67
  last mutex release. — *end note*]
68
 
69
- An evaluation A *carries a dependency* to an evaluation B if
70
-
71
- - the value of A is used as an operand of B, unless:
72
- - B is an invocation of any specialization of `std::kill_dependency`
73
- [[atomics.order]], or
74
- - A is the left operand of a built-in logical (`&&`, see 
75
- [[expr.log.and]]) or logical (`||`, see  [[expr.log.or]]) operator,
76
- or
77
- - A is the left operand of a conditional (`?:`, see  [[expr.cond]])
78
- operator, or
79
- - A is the left operand of the built-in comma (`,`) operator
80
- [[expr.comma]];
81
-
82
- or
83
- - A writes a scalar object or bit-field M, B reads the value written by
84
- A from M, and A is sequenced before B, or
85
- - for some evaluation X, A carries a dependency to X, and X carries a
86
- dependency to B.
87
-
88
- [*Note 6*: “Carries a dependency to” is a subset of “is sequenced
89
- before”, and is similarly strictly intra-thread. — *end note*]
90
-
91
- An evaluation A is *dependency-ordered before* an evaluation B if
92
-
93
- - A performs a release operation on an atomic object M, and, in another
94
- thread, B performs a consume operation on M and reads the value
95
- written by A, or
96
- - for some evaluation X, A is dependency-ordered before X and X carries
97
- a dependency to B.
98
-
99
- [*Note 7*: The relation “is dependency-ordered before” is analogous to
100
- “synchronizes with”, but uses release/consume in place of
101
- release/acquire. — *end note*]
102
-
103
- An evaluation A *inter-thread happens before* an evaluation B if
104
-
105
- - A synchronizes with B, or
106
- - A is dependency-ordered before B, or
107
- - for some evaluation X
108
- - A synchronizes with X and X is sequenced before B, or
109
- - A is sequenced before X and X inter-thread happens before B, or
110
- - A inter-thread happens before X and X inter-thread happens before B.
111
-
112
- [*Note 8*: The “inter-thread happens before” relation describes
113
- arbitrary concatenations of “sequenced before”, “synchronizes with” and
114
- “dependency-ordered before” relationships, with two exceptions. The
115
- first exception is that a concatenation is not permitted to end with
116
- “dependency-ordered before” followed by “sequenced before”. The reason
117
- for this limitation is that a consume operation participating in a
118
- “dependency-ordered before” relationship provides ordering only with
119
- respect to operations to which this consume operation actually carries a
120
- dependency. The reason that this limitation applies only to the end of
121
- such a concatenation is that any subsequent release operation will
122
- provide the required ordering for a prior consume operation. The second
123
- exception is that a concatenation is not permitted to consist entirely
124
- of “sequenced before”. The reasons for this limitation are (1) to permit
125
- “inter-thread happens before” to be transitively closed and (2) the
126
- “happens before” relation, defined below, provides for relationships
127
- consisting entirely of “sequenced before”. — *end note*]
128
-
129
  An evaluation A *happens before* an evaluation B (or, equivalently, B
130
- *happens after* A) if:
131
-
132
- - A is sequenced before B, or
133
- - A inter-thread happens before B.
134
-
135
- The implementation shall ensure that no program execution demonstrates a
136
- cycle in the “happens before” relation.
137
-
138
- [*Note 9*: This cycle would otherwise be possible only through the use
139
- of consume operations. — *end note*]
140
-
141
- An evaluation A *simply happens before* an evaluation B if either
142
 
143
  - A is sequenced before B, or
144
  - A synchronizes with B, or
145
- - A simply happens before X and X simply happens before B.
146
 
147
- [*Note 10*: In the absence of consume operations, the happens before
148
- and simply happens before relations are identical. — *end note*]
149
 
150
  An evaluation A *strongly happens before* an evaluation D if, either
151
 
152
  - A is sequenced before D, or
153
  - A synchronizes with D, and both A and D are sequentially consistent
154
  atomic operations [[atomics.order]], or
155
  - there are evaluations B and C such that A is sequenced before B, B
156
- simply happens before C, and C is sequenced before D, or
157
  - there is an evaluation B such that A strongly happens before B, and B
158
  strongly happens before D.
159
 
160
- [*Note 11*: Informally, if A strongly happens before B, then A appears
161
- to be evaluated before B in all contexts. Strongly happens before
162
- excludes consume operations. — *end note*]
163
 
164
  A *visible side effect* A on a scalar object or bit-field M with respect
165
  to a value computation B of M satisfies the conditions:
166
 
167
  - A happens before B and
168
  - there is no other side effect X to M such that A happens before X and
169
  X happens before B.
170
 
171
  The value of a non-atomic scalar object or bit-field M, as determined by
172
- evaluation B, shall be the value stored by the visible side effect A.
173
 
174
- [*Note 12*: If there is ambiguity about which side effect to a
175
  non-atomic object or bit-field is visible, then the behavior is either
176
  unspecified or undefined. — *end note*]
177
 
178
- [*Note 13*: This states that operations on ordinary objects are not
179
  visibly reordered. This is not actually detectable without data races,
180
- but it is necessary to ensure that data races, as defined below, and
181
- with suitable restrictions on the use of atomics, correspond to data
182
- races in a simple interleaved (sequentially consistent)
183
- execution. — *end note*]
184
 
185
- The value of an atomic object M, as determined by evaluation B, shall be
186
- the value stored by some side effect A that modifies M, where B does not
187
- happen before A.
188
 
189
- [*Note 14*: The set of such side effects is also restricted by the rest
190
  of the rules described here, and in particular, by the coherence
191
  requirements below. — *end note*]
192
 
193
  If an operation A that modifies an atomic object M happens before an
194
- operation B that modifies M, then A shall be earlier than B in the
195
  modification order of M.
196
 
197
- [*Note 15*: This requirement is known as write-write
198
  coherence. — *end note*]
199
 
200
  If a value computation A of an atomic object M happens before a value
201
  computation B of M, and A takes its value from a side effect X on M,
202
- then the value computed by B shall either be the value stored by X or
203
- the value stored by a side effect Y on M, where Y follows X in the
204
  modification order of M.
205
 
206
- [*Note 16*: This requirement is known as read-read
207
  coherence. — *end note*]
208
 
209
  If a value computation A of an atomic object M happens before an
210
- operation B that modifies M, then A shall take its value from a side
211
- effect X on M, where X precedes B in the modification order of M.
212
 
213
- [*Note 17*: This requirement is known as read-write
214
  coherence. — *end note*]
215
 
216
  If a side effect X on an atomic object M happens before a value
217
- computation B of M, then the evaluation B shall take its value from X or
218
- from a side effect Y that follows X in the modification order of M.
219
 
220
- [*Note 18*: This requirement is known as write-read
221
  coherence. — *end note*]
222
 
223
- [*Note 19*: The four preceding coherence requirements effectively
224
  disallow compiler reordering of atomic operations to a single object,
225
  even if both operations are relaxed loads. This effectively makes the
226
  cache coherence guarantee provided by most hardware available to C++
227
  atomic operations. — *end note*]
228
 
229
- [*Note 20*: The value observed by a load of an atomic depends on the
230
  “happens before” relation, which depends on the values observed by loads
231
  of atomics. The intended reading is that there must exist an association
232
  of atomic loads with modifications they observe that, together with
233
  suitably chosen modification orders and the “happens before” relation
234
  derived as described above, satisfy the resulting constraints as imposed
@@ -244,49 +180,49 @@ The execution of a program contains a *data race* if it contains two
244
  potentially concurrent conflicting actions, at least one of which is not
245
  atomic, and neither happens before the other, except for the special
246
  case for signal handlers described below. Any such data race results in
247
  undefined behavior.
248
 
249
- [*Note 21*: It can be shown that programs that correctly use mutexes
250
  and `memory_order::seq_cst` operations to prevent all data races and use
251
  no other synchronization operations behave as if the operations executed
252
  by their constituent threads were simply interleaved, with each value
253
  computation of an object being taken from the last side effect on that
254
  object in that interleaving. This is normally referred to as “sequential
255
  consistency”. However, this applies only to data-race-free programs, and
256
  data-race-free programs cannot observe most program transformations that
257
  do not change single-threaded program semantics. In fact, most
258
- single-threaded program transformations continue to be allowed, since
259
- any program that behaves differently as a result has undefined
260
  behavior. — *end note*]
261
 
262
- Two accesses to the same object of type `volatile std::sig_atomic_t` do
263
- not result in a data race if both occur in the same thread, even if one
264
- or more occurs in a signal handler. For each signal handler invocation,
265
- evaluations performed by the thread invoking a signal handler can be
266
- divided into two groups A and B, such that no evaluations in B happen
267
- before evaluations in A, and the evaluations of such
268
- `volatile std::sig_atomic_t` objects take values as though all
269
- evaluations in A happened before the execution of the signal handler and
270
- the execution of the signal handler happened before all evaluations in
271
- B.
272
 
273
- [*Note 22*: Compiler transformations that introduce assignments to a
274
  potentially shared memory location that would not be modified by the
275
  abstract machine are generally precluded by this document, since such an
276
  assignment might overwrite another assignment by a different thread in
277
  cases in which an abstract machine execution would not have encountered
278
  a data race. This includes implementations of data member assignment
279
  that overwrite adjacent members in separate memory locations. Reordering
280
  of atomic loads in cases in which the atomics in question might alias is
281
  also generally precluded, since this could violate the coherence
282
  rules. — *end note*]
283
 
284
- [*Note 23*: Transformations that introduce a speculative read of a
285
- potentially shared memory location might not preserve the semantics of
286
- the C++ program as defined in this document, since they potentially
287
- introduce a data race. However, they are typically valid in the context
288
- of an optimizing compiler that targets a specific machine with
289
- well-defined semantics for data races. They would be invalid for a
290
  hypothetical machine that is not tolerant of races or provides hardware
291
  race detection. — *end note*]
292
 
 
9
  Much of this subclause is motivated by the desire to support atomic
10
  operations with explicit and detailed visibility constraints. However,
11
  it also implicitly supports a simpler view for more restricted
12
  programs. — *end note*]
13
 
14
+ Two expression evaluations *conflict* if one of them
15
+
16
+ - modifies [[defns.access]] a memory location [[intro.memory]] or
17
+ - starts or ends the lifetime of an object in a memory location
18
+
19
+ and the other one
20
+
21
+ - reads or modifies the same memory location or
22
+ - starts or ends the lifetime of an object occupying storage that
23
+ overlaps with the memory location.
24
+
25
+ [*Note 2*: A modification can still conflict even if it does not alter
26
+ the value of any bits. — *end note*]
27
 
28
  The library defines a number of atomic operations [[atomics]] and
29
  operations on mutexes [[thread]] that are specially identified as
30
  synchronization operations. These operations play a special role in
31
  making assignments in one thread visible to another. A synchronization
32
+ operation on one or more memory locations is either an acquire
33
+ operation, a release operation, or both an acquire and release
34
+ operation. A synchronization operation without an associated memory
35
+ location is a fence and can be either an acquire fence, a release fence,
36
+ or both an acquire and release fence. In addition, there are relaxed
37
+ atomic operations, which are not synchronization operations, and atomic
38
+ read-modify-write operations, which have special characteristics.
39
 
40
+ [*Note 3*: For example, a call that acquires a mutex will perform an
41
  acquire operation on the locations comprising the mutex.
42
  Correspondingly, a call that releases the same mutex will perform a
43
  release operation on those same locations. Informally, performing a
44
  release operation on A forces prior side effects on other memory
45
  locations to become visible to other threads that later perform a
 
48
  operations, they cannot contribute to data races. — *end note*]
49
 
50
  All modifications to a particular atomic object M occur in some
51
  particular total order, called the *modification order* of M.
52
 
53
+ [*Note 4*: There is a separate order for each atomic object. There is
54
  no requirement that these can be combined into a single total order for
55
  all objects. In general this will be impossible since different threads
56
  can observe modifications to different objects in inconsistent
57
  orders. — *end note*]
58
 
 
64
  Certain library calls *synchronize with* other library calls performed
65
  by another thread. For example, an atomic store-release synchronizes
66
  with a load-acquire that takes its value from the store
67
  [[atomics.order]].
68
 
69
+ [*Note 5*: Except in the specified cases, reading a later value does
70
  not necessarily ensure visibility as described below. Such a requirement
71
  would sometimes interfere with efficient implementation. — *end note*]
72
 
73
+ [*Note 6*: The specifications of the synchronization operations define
74
  when one reads the value written by another. For atomic objects, the
75
  definition is clear. All operations on a given mutex occur in a single
76
  total order. Each mutex acquisition “reads the value written” by the
77
  last mutex release. — *end note*]
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  An evaluation A *happens before* an evaluation B (or, equivalently, B
80
+ happens after A) if either
 
 
 
 
 
 
 
 
 
 
 
81
 
82
  - A is sequenced before B, or
83
  - A synchronizes with B, or
84
+ - A happens before X and X happens before B.
85
 
86
+ [*Note 7*: An evaluation does not happen before itself. *end note*]
 
87
 
88
  An evaluation A *strongly happens before* an evaluation D if, either
89
 
90
  - A is sequenced before D, or
91
  - A synchronizes with D, and both A and D are sequentially consistent
92
  atomic operations [[atomics.order]], or
93
  - there are evaluations B and C such that A is sequenced before B, B
94
+ happens before C, and C is sequenced before D, or
95
  - there is an evaluation B such that A strongly happens before B, and B
96
  strongly happens before D.
97
 
98
+ [*Note 8*: Informally, if A strongly happens before B, then A appears
99
+ to be evaluated before B in all contexts. *end note*]
 
100
 
101
  A *visible side effect* A on a scalar object or bit-field M with respect
102
  to a value computation B of M satisfies the conditions:
103
 
104
  - A happens before B and
105
  - there is no other side effect X to M such that A happens before X and
106
  X happens before B.
107
 
108
  The value of a non-atomic scalar object or bit-field M, as determined by
109
+ evaluation B, is the value stored by the visible side effect A.
110
 
111
+ [*Note 9*: If there is ambiguity about which side effect to a
112
  non-atomic object or bit-field is visible, then the behavior is either
113
  unspecified or undefined. — *end note*]
114
 
115
+ [*Note 10*: This states that operations on ordinary objects are not
116
  visibly reordered. This is not actually detectable without data races,
117
+ but is needed to ensure that data races, as defined below, and with
118
+ suitable restrictions on the use of atomics, correspond to data races in
119
+ a simple interleaved (sequentially consistent) execution. — *end note*]
 
120
 
121
+ The value of an atomic object M, as determined by evaluation B, is the
122
+ value stored by some unspecified side effect A that modifies M, where B
123
+ does not happen before A.
124
 
125
+ [*Note 11*: The set of such side effects is also restricted by the rest
126
  of the rules described here, and in particular, by the coherence
127
  requirements below. — *end note*]
128
 
129
  If an operation A that modifies an atomic object M happens before an
130
+ operation B that modifies M, then A is earlier than B in the
131
  modification order of M.
132
 
133
+ [*Note 12*: This requirement is known as write-write
134
  coherence. — *end note*]
135
 
136
  If a value computation A of an atomic object M happens before a value
137
  computation B of M, and A takes its value from a side effect X on M,
138
+ then the value computed by B is either the value stored by X or the
139
+ value stored by a side effect Y on M, where Y follows X in the
140
  modification order of M.
141
 
142
+ [*Note 13*: This requirement is known as read-read
143
  coherence. — *end note*]
144
 
145
  If a value computation A of an atomic object M happens before an
146
+ operation B that modifies M, then A takes its value from a side effect X
147
+ on M, where X precedes B in the modification order of M.
148
 
149
+ [*Note 14*: This requirement is known as read-write
150
  coherence. — *end note*]
151
 
152
  If a side effect X on an atomic object M happens before a value
153
+ computation B of M, then the evaluation B takes its value from X or from
154
+ a side effect Y that follows X in the modification order of M.
155
 
156
+ [*Note 15*: This requirement is known as write-read
157
  coherence. — *end note*]
158
 
159
+ [*Note 16*: The four preceding coherence requirements effectively
160
  disallow compiler reordering of atomic operations to a single object,
161
  even if both operations are relaxed loads. This effectively makes the
162
  cache coherence guarantee provided by most hardware available to C++
163
  atomic operations. — *end note*]
164
 
165
+ [*Note 17*: The value observed by a load of an atomic depends on the
166
  “happens before” relation, which depends on the values observed by loads
167
  of atomics. The intended reading is that there must exist an association
168
  of atomic loads with modifications they observe that, together with
169
  suitably chosen modification orders and the “happens before” relation
170
  derived as described above, satisfy the resulting constraints as imposed
 
180
  potentially concurrent conflicting actions, at least one of which is not
181
  atomic, and neither happens before the other, except for the special
182
  case for signal handlers described below. Any such data race results in
183
  undefined behavior.
184
 
185
+ [*Note 18*: It can be shown that programs that correctly use mutexes
186
  and `memory_order::seq_cst` operations to prevent all data races and use
187
  no other synchronization operations behave as if the operations executed
188
  by their constituent threads were simply interleaved, with each value
189
  computation of an object being taken from the last side effect on that
190
  object in that interleaving. This is normally referred to as “sequential
191
  consistency”. However, this applies only to data-race-free programs, and
192
  data-race-free programs cannot observe most program transformations that
193
  do not change single-threaded program semantics. In fact, most
194
+ single-threaded program transformations remain possible, since any
195
+ program that behaves differently as a result has undefined
196
  behavior. — *end note*]
197
 
198
+ Two accesses to the same non-bit-field object of type
199
+ `volatile std::sig_atomic_t` do not result in a data race if both occur
200
+ in the same thread, even if one or more occurs in a signal handler. For
201
+ each signal handler invocation, evaluations performed by the thread
202
+ invoking a signal handler can be divided into two groups A and B, such
203
+ that no evaluations in B happen before evaluations in A, and the
204
+ evaluations of such `volatile std::sig_atomic_t` objects take values as
205
+ though all evaluations in A happened before the execution of the signal
206
+ handler and the execution of the signal handler happened before all
207
+ evaluations in B.
208
 
209
+ [*Note 19*: Compiler transformations that introduce assignments to a
210
  potentially shared memory location that would not be modified by the
211
  abstract machine are generally precluded by this document, since such an
212
  assignment might overwrite another assignment by a different thread in
213
  cases in which an abstract machine execution would not have encountered
214
  a data race. This includes implementations of data member assignment
215
  that overwrite adjacent members in separate memory locations. Reordering
216
  of atomic loads in cases in which the atomics in question might alias is
217
  also generally precluded, since this could violate the coherence
218
  rules. — *end note*]
219
 
220
+ [*Note 20*: It is possible that transformations that introduce a
221
+ speculative read of a potentially shared memory location do not preserve
222
+ the semantics of the C++ program as defined in this document, since they
223
+ potentially introduce a data race. However, they are typically valid in
224
+ the context of an optimizing compiler that targets a specific machine
225
+ with well-defined semantics for data races. They would be invalid for a
226
  hypothetical machine that is not tolerant of races or provides hardware
227
  race detection. — *end note*]
228