From Jason Turner

[intro.multithread]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp_1sed6wx/{from.md → to.md} +89 -148
tmp/tmp_1sed6wx/{from.md → to.md} RENAMED
@@ -9,12 +9,12 @@ subsequently executed by the thread.
9
 
10
  [*Note 1*: When one thread creates another, the initial call to the
11
  top-level function of the new thread is executed by the new thread, not
12
  by the creating thread. — *end note*]
13
 
14
- Every thread in a program can potentially access every object and
15
- function in a program.[^24]
16
 
17
  Under a hosted implementation, a C++ program can have more than one
18
  thread running concurrently. The execution of each thread proceeds as
19
  defined by the remainder of this document. The execution of the entire
20
  program consists of an execution of all of its threads.
@@ -42,27 +42,37 @@ below.
42
  Much of this subclause is motivated by the desire to support atomic
43
  operations with explicit and detailed visibility constraints. However,
44
  it also implicitly supports a simpler view for more restricted
45
  programs. — *end note*]
46
 
47
- Two expression evaluations *conflict* if one of them modifies a memory
48
- location [[intro.memory]] and the other one reads or modifies the same
49
- memory location.
 
 
 
 
 
 
 
 
 
 
50
 
51
  The library defines a number of atomic operations [[atomics]] and
52
  operations on mutexes [[thread]] that are specially identified as
53
  synchronization operations. These operations play a special role in
54
  making assignments in one thread visible to another. A synchronization
55
- operation on one or more memory locations is either a consume operation,
56
- an acquire operation, a release operation, or both an acquire and
57
- release operation. A synchronization operation without an associated
58
- memory location is a fence and can be either an acquire fence, a release
59
- fence, or both an acquire and release fence. In addition, there are
60
- relaxed atomic operations, which are not synchronization operations, and
61
- atomic read-modify-write operations, which have special characteristics.
62
 
63
- [*Note 2*: For example, a call that acquires a mutex will perform an
64
  acquire operation on the locations comprising the mutex.
65
  Correspondingly, a call that releases the same mutex will perform a
66
  release operation on those same locations. Informally, performing a
67
  release operation on A forces prior side effects on other memory
68
  locations to become visible to other threads that later perform a
@@ -71,11 +81,11 @@ not synchronization operations even though, like synchronization
71
  operations, they cannot contribute to data races. — *end note*]
72
 
73
  All modifications to a particular atomic object M occur in some
74
  particular total order, called the *modification order* of M.
75
 
76
- [*Note 3*: There is a separate order for each atomic object. There is
77
  no requirement that these can be combined into a single total order for
78
  all objects. In general this will be impossible since different threads
79
  can observe modifications to different objects in inconsistent
80
  orders. — *end note*]
81
 
@@ -87,181 +97,107 @@ subsequent operation is an atomic read-modify-write operation.
87
  Certain library calls *synchronize with* other library calls performed
88
  by another thread. For example, an atomic store-release synchronizes
89
  with a load-acquire that takes its value from the store
90
  [[atomics.order]].
91
 
92
- [*Note 4*: Except in the specified cases, reading a later value does
93
  not necessarily ensure visibility as described below. Such a requirement
94
  would sometimes interfere with efficient implementation. — *end note*]
95
 
96
- [*Note 5*: The specifications of the synchronization operations define
97
  when one reads the value written by another. For atomic objects, the
98
  definition is clear. All operations on a given mutex occur in a single
99
  total order. Each mutex acquisition “reads the value written” by the
100
  last mutex release. — *end note*]
101
 
102
- An evaluation A *carries a dependency* to an evaluation B if
103
-
104
- - the value of A is used as an operand of B, unless:
105
- - B is an invocation of any specialization of `std::kill_dependency`
106
- [[atomics.order]], or
107
- - A is the left operand of a built-in logical (`&&`, see 
108
- [[expr.log.and]]) or logical (`||`, see  [[expr.log.or]]) operator,
109
- or
110
- - A is the left operand of a conditional (`?:`, see  [[expr.cond]])
111
- operator, or
112
- - A is the left operand of the built-in comma (`,`) operator
113
- [[expr.comma]];
114
-
115
- or
116
- - A writes a scalar object or bit-field M, B reads the value written by
117
- A from M, and A is sequenced before B, or
118
- - for some evaluation X, A carries a dependency to X, and X carries a
119
- dependency to B.
120
-
121
- [*Note 6*: “Carries a dependency to” is a subset of “is sequenced
122
- before”, and is similarly strictly intra-thread. — *end note*]
123
-
124
- An evaluation A is *dependency-ordered before* an evaluation B if
125
-
126
- - A performs a release operation on an atomic object M, and, in another
127
- thread, B performs a consume operation on M and reads the value
128
- written by A, or
129
- - for some evaluation X, A is dependency-ordered before X and X carries
130
- a dependency to B.
131
-
132
- [*Note 7*: The relation “is dependency-ordered before” is analogous to
133
- “synchronizes with”, but uses release/consume in place of
134
- release/acquire. — *end note*]
135
-
136
- An evaluation A *inter-thread happens before* an evaluation B if
137
-
138
- - A synchronizes with B, or
139
- - A is dependency-ordered before B, or
140
- - for some evaluation X
141
- - A synchronizes with X and X is sequenced before B, or
142
- - A is sequenced before X and X inter-thread happens before B, or
143
- - A inter-thread happens before X and X inter-thread happens before B.
144
-
145
- [*Note 8*: The “inter-thread happens before” relation describes
146
- arbitrary concatenations of “sequenced before”, “synchronizes with” and
147
- “dependency-ordered before” relationships, with two exceptions. The
148
- first exception is that a concatenation is not permitted to end with
149
- “dependency-ordered before” followed by “sequenced before”. The reason
150
- for this limitation is that a consume operation participating in a
151
- “dependency-ordered before” relationship provides ordering only with
152
- respect to operations to which this consume operation actually carries a
153
- dependency. The reason that this limitation applies only to the end of
154
- such a concatenation is that any subsequent release operation will
155
- provide the required ordering for a prior consume operation. The second
156
- exception is that a concatenation is not permitted to consist entirely
157
- of “sequenced before”. The reasons for this limitation are (1) to permit
158
- “inter-thread happens before” to be transitively closed and (2) the
159
- “happens before” relation, defined below, provides for relationships
160
- consisting entirely of “sequenced before”. — *end note*]
161
-
162
  An evaluation A *happens before* an evaluation B (or, equivalently, B
163
- *happens after* A) if:
164
-
165
- - A is sequenced before B, or
166
- - A inter-thread happens before B.
167
-
168
- The implementation shall ensure that no program execution demonstrates a
169
- cycle in the “happens before” relation.
170
-
171
- [*Note 9*: This cycle would otherwise be possible only through the use
172
- of consume operations. — *end note*]
173
-
174
- An evaluation A *simply happens before* an evaluation B if either
175
 
176
  - A is sequenced before B, or
177
  - A synchronizes with B, or
178
- - A simply happens before X and X simply happens before B.
179
 
180
- [*Note 10*: In the absence of consume operations, the happens before
181
- and simply happens before relations are identical. — *end note*]
182
 
183
  An evaluation A *strongly happens before* an evaluation D if, either
184
 
185
  - A is sequenced before D, or
186
  - A synchronizes with D, and both A and D are sequentially consistent
187
  atomic operations [[atomics.order]], or
188
  - there are evaluations B and C such that A is sequenced before B, B
189
- simply happens before C, and C is sequenced before D, or
190
  - there is an evaluation B such that A strongly happens before B, and B
191
  strongly happens before D.
192
 
193
- [*Note 11*: Informally, if A strongly happens before B, then A appears
194
- to be evaluated before B in all contexts. Strongly happens before
195
- excludes consume operations. — *end note*]
196
 
197
  A *visible side effect* A on a scalar object or bit-field M with respect
198
  to a value computation B of M satisfies the conditions:
199
 
200
  - A happens before B and
201
  - there is no other side effect X to M such that A happens before X and
202
  X happens before B.
203
 
204
  The value of a non-atomic scalar object or bit-field M, as determined by
205
- evaluation B, shall be the value stored by the visible side effect A.
206
 
207
- [*Note 12*: If there is ambiguity about which side effect to a
208
  non-atomic object or bit-field is visible, then the behavior is either
209
  unspecified or undefined. — *end note*]
210
 
211
- [*Note 13*: This states that operations on ordinary objects are not
212
  visibly reordered. This is not actually detectable without data races,
213
- but it is necessary to ensure that data races, as defined below, and
214
- with suitable restrictions on the use of atomics, correspond to data
215
- races in a simple interleaved (sequentially consistent)
216
- execution. — *end note*]
217
 
218
- The value of an atomic object M, as determined by evaluation B, shall be
219
- the value stored by some side effect A that modifies M, where B does not
220
- happen before A.
221
 
222
- [*Note 14*: The set of such side effects is also restricted by the rest
223
  of the rules described here, and in particular, by the coherence
224
  requirements below. — *end note*]
225
 
226
  If an operation A that modifies an atomic object M happens before an
227
- operation B that modifies M, then A shall be earlier than B in the
228
  modification order of M.
229
 
230
- [*Note 15*: This requirement is known as write-write
231
  coherence. — *end note*]
232
 
233
  If a value computation A of an atomic object M happens before a value
234
  computation B of M, and A takes its value from a side effect X on M,
235
- then the value computed by B shall either be the value stored by X or
236
- the value stored by a side effect Y on M, where Y follows X in the
237
  modification order of M.
238
 
239
- [*Note 16*: This requirement is known as read-read
240
  coherence. — *end note*]
241
 
242
  If a value computation A of an atomic object M happens before an
243
- operation B that modifies M, then A shall take its value from a side
244
- effect X on M, where X precedes B in the modification order of M.
245
 
246
- [*Note 17*: This requirement is known as read-write
247
  coherence. — *end note*]
248
 
249
  If a side effect X on an atomic object M happens before a value
250
- computation B of M, then the evaluation B shall take its value from X or
251
- from a side effect Y that follows X in the modification order of M.
252
 
253
- [*Note 18*: This requirement is known as write-read
254
  coherence. — *end note*]
255
 
256
- [*Note 19*: The four preceding coherence requirements effectively
257
  disallow compiler reordering of atomic operations to a single object,
258
  even if both operations are relaxed loads. This effectively makes the
259
  cache coherence guarantee provided by most hardware available to C++
260
  atomic operations. — *end note*]
261
 
262
- [*Note 20*: The value observed by a load of an atomic depends on the
263
  “happens before” relation, which depends on the values observed by loads
264
  of atomics. The intended reading is that there must exist an association
265
  of atomic loads with modifications they observe that, together with
266
  suitably chosen modification orders and the “happens before” relation
267
  derived as described above, satisfy the resulting constraints as imposed
@@ -277,67 +213,71 @@ The execution of a program contains a *data race* if it contains two
277
  potentially concurrent conflicting actions, at least one of which is not
278
  atomic, and neither happens before the other, except for the special
279
  case for signal handlers described below. Any such data race results in
280
  undefined behavior.
281
 
282
- [*Note 21*: It can be shown that programs that correctly use mutexes
283
  and `memory_order::seq_cst` operations to prevent all data races and use
284
  no other synchronization operations behave as if the operations executed
285
  by their constituent threads were simply interleaved, with each value
286
  computation of an object being taken from the last side effect on that
287
  object in that interleaving. This is normally referred to as “sequential
288
  consistency”. However, this applies only to data-race-free programs, and
289
  data-race-free programs cannot observe most program transformations that
290
  do not change single-threaded program semantics. In fact, most
291
- single-threaded program transformations continue to be allowed, since
292
- any program that behaves differently as a result has undefined
293
  behavior. — *end note*]
294
 
295
- Two accesses to the same object of type `volatile std::sig_atomic_t` do
296
- not result in a data race if both occur in the same thread, even if one
297
- or more occurs in a signal handler. For each signal handler invocation,
298
- evaluations performed by the thread invoking a signal handler can be
299
- divided into two groups A and B, such that no evaluations in B happen
300
- before evaluations in A, and the evaluations of such
301
- `volatile std::sig_atomic_t` objects take values as though all
302
- evaluations in A happened before the execution of the signal handler and
303
- the execution of the signal handler happened before all evaluations in
304
- B.
305
 
306
- [*Note 22*: Compiler transformations that introduce assignments to a
307
  potentially shared memory location that would not be modified by the
308
  abstract machine are generally precluded by this document, since such an
309
  assignment might overwrite another assignment by a different thread in
310
  cases in which an abstract machine execution would not have encountered
311
  a data race. This includes implementations of data member assignment
312
  that overwrite adjacent members in separate memory locations. Reordering
313
  of atomic loads in cases in which the atomics in question might alias is
314
  also generally precluded, since this could violate the coherence
315
  rules. — *end note*]
316
 
317
- [*Note 23*: Transformations that introduce a speculative read of a
318
- potentially shared memory location might not preserve the semantics of
319
- the C++ program as defined in this document, since they potentially
320
- introduce a data race. However, they are typically valid in the context
321
- of an optimizing compiler that targets a specific machine with
322
- well-defined semantics for data races. They would be invalid for a
323
  hypothetical machine that is not tolerant of races or provides hardware
324
  race detection. — *end note*]
325
 
326
  #### Forward progress <a id="intro.progress">[[intro.progress]]</a>
327
 
328
  The implementation may assume that any thread will eventually do one of
329
  the following:
330
 
331
  - terminate,
 
332
  - make a call to a library I/O function,
333
- - perform an access through a volatile glvalue, or
334
- - perform a synchronization operation or an atomic operation.
 
 
335
 
336
  [*Note 1*: This is intended to allow compiler transformations such as
337
- removal of empty loops, even when termination cannot be
338
- proven. *end note*]
 
339
 
340
  Executions of atomic functions that are either defined to be lock-free
341
  [[atomics.flag]] or indicated as lock-free [[atomics.lockfree]] are
342
  *lock-free executions*.
343
 
@@ -361,13 +301,14 @@ Executions of atomic functions that are either defined to be lock-free
361
 
362
  During the execution of a thread of execution, each of the following is
363
  termed an *execution step*:
364
 
365
  - termination of the thread of execution,
366
- - performing an access through a volatile glvalue, or
367
- - completion of a call to a library I/O function, a synchronization
368
- operation, or an atomic operation.
 
369
 
370
  An invocation of a standard library function that blocks [[defns.block]]
371
  is considered to continuously execute execution steps while waiting for
372
  the condition that it blocks on to be satisfied.
373
 
@@ -389,12 +330,12 @@ concurrent threads that are not blocked in a standard library function
389
 
390
  For a thread of execution providing *concurrent forward progress
391
  guarantees*, the implementation ensures that the thread will eventually
392
  make progress for as long as it has not terminated.
393
 
394
- [*Note 5*: This is required regardless of whether or not other threads
395
- of execution (if any) have been or are making progress. To eventually
396
  fulfill this requirement means that this will happen in an unspecified
397
  but finite amount of time. — *end note*]
398
 
399
  It is *implementation-defined* whether the implementation-created thread
400
  of execution that executes `main` [[basic.start.main]] and the threads
 
9
 
10
  [*Note 1*: When one thread creates another, the initial call to the
11
  top-level function of the new thread is executed by the new thread, not
12
  by the creating thread. — *end note*]
13
 
14
+ Every thread in a program can potentially use every object and function
15
+ in a program.[^23]
16
 
17
  Under a hosted implementation, a C++ program can have more than one
18
  thread running concurrently. The execution of each thread proceeds as
19
  defined by the remainder of this document. The execution of the entire
20
  program consists of an execution of all of its threads.
 
42
  Much of this subclause is motivated by the desire to support atomic
43
  operations with explicit and detailed visibility constraints. However,
44
  it also implicitly supports a simpler view for more restricted
45
  programs. — *end note*]
46
 
47
+ Two expression evaluations *conflict* if one of them
48
+
49
+ - modifies [[defns.access]] a memory location [[intro.memory]] or
50
+ - starts or ends the lifetime of an object in a memory location
51
+
52
+ and the other one
53
+
54
+ - reads or modifies the same memory location or
55
+ - starts or ends the lifetime of an object occupying storage that
56
+ overlaps with the memory location.
57
+
58
+ [*Note 2*: A modification can still conflict even if it does not alter
59
+ the value of any bits. — *end note*]
60
 
61
  The library defines a number of atomic operations [[atomics]] and
62
  operations on mutexes [[thread]] that are specially identified as
63
  synchronization operations. These operations play a special role in
64
  making assignments in one thread visible to another. A synchronization
65
+ operation on one or more memory locations is either an acquire
66
+ operation, a release operation, or both an acquire and release
67
+ operation. A synchronization operation without an associated memory
68
+ location is a fence and can be either an acquire fence, a release fence,
69
+ or both an acquire and release fence. In addition, there are relaxed
70
+ atomic operations, which are not synchronization operations, and atomic
71
+ read-modify-write operations, which have special characteristics.
72
 
73
+ [*Note 3*: For example, a call that acquires a mutex will perform an
74
  acquire operation on the locations comprising the mutex.
75
  Correspondingly, a call that releases the same mutex will perform a
76
  release operation on those same locations. Informally, performing a
77
  release operation on A forces prior side effects on other memory
78
  locations to become visible to other threads that later perform a
 
81
  operations, they cannot contribute to data races. — *end note*]
82
 
83
  All modifications to a particular atomic object M occur in some
84
  particular total order, called the *modification order* of M.
85
 
86
+ [*Note 4*: There is a separate order for each atomic object. There is
87
  no requirement that these can be combined into a single total order for
88
  all objects. In general this will be impossible since different threads
89
  can observe modifications to different objects in inconsistent
90
  orders. — *end note*]
91
 
 
97
  Certain library calls *synchronize with* other library calls performed
98
  by another thread. For example, an atomic store-release synchronizes
99
  with a load-acquire that takes its value from the store
100
  [[atomics.order]].
101
 
102
+ [*Note 5*: Except in the specified cases, reading a later value does
103
  not necessarily ensure visibility as described below. Such a requirement
104
  would sometimes interfere with efficient implementation. — *end note*]
105
 
106
+ [*Note 6*: The specifications of the synchronization operations define
107
  when one reads the value written by another. For atomic objects, the
108
  definition is clear. All operations on a given mutex occur in a single
109
  total order. Each mutex acquisition “reads the value written” by the
110
  last mutex release. — *end note*]
111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  An evaluation A *happens before* an evaluation B (or, equivalently, B
113
+ happens after A) if either
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  - A is sequenced before B, or
116
  - A synchronizes with B, or
117
+ - A happens before X and X happens before B.
118
 
119
+ [*Note 7*: An evaluation does not happen before itself. *end note*]
 
120
 
121
  An evaluation A *strongly happens before* an evaluation D if, either
122
 
123
  - A is sequenced before D, or
124
  - A synchronizes with D, and both A and D are sequentially consistent
125
  atomic operations [[atomics.order]], or
126
  - there are evaluations B and C such that A is sequenced before B, B
127
+ happens before C, and C is sequenced before D, or
128
  - there is an evaluation B such that A strongly happens before B, and B
129
  strongly happens before D.
130
 
131
+ [*Note 8*: Informally, if A strongly happens before B, then A appears
132
+ to be evaluated before B in all contexts. *end note*]
 
133
 
134
  A *visible side effect* A on a scalar object or bit-field M with respect
135
  to a value computation B of M satisfies the conditions:
136
 
137
  - A happens before B and
138
  - there is no other side effect X to M such that A happens before X and
139
  X happens before B.
140
 
141
  The value of a non-atomic scalar object or bit-field M, as determined by
142
+ evaluation B, is the value stored by the visible side effect A.
143
 
144
+ [*Note 9*: If there is ambiguity about which side effect to a
145
  non-atomic object or bit-field is visible, then the behavior is either
146
  unspecified or undefined. — *end note*]
147
 
148
+ [*Note 10*: This states that operations on ordinary objects are not
149
  visibly reordered. This is not actually detectable without data races,
150
+ but is needed to ensure that data races, as defined below, and with
151
+ suitable restrictions on the use of atomics, correspond to data races in
152
+ a simple interleaved (sequentially consistent) execution. — *end note*]
 
153
 
154
+ The value of an atomic object M, as determined by evaluation B, is the
155
+ value stored by some unspecified side effect A that modifies M, where B
156
+ does not happen before A.
157
 
158
+ [*Note 11*: The set of such side effects is also restricted by the rest
159
  of the rules described here, and in particular, by the coherence
160
  requirements below. — *end note*]
161
 
162
  If an operation A that modifies an atomic object M happens before an
163
+ operation B that modifies M, then A is earlier than B in the
164
  modification order of M.
165
 
166
+ [*Note 12*: This requirement is known as write-write
167
  coherence. — *end note*]
168
 
169
  If a value computation A of an atomic object M happens before a value
170
  computation B of M, and A takes its value from a side effect X on M,
171
+ then the value computed by B is either the value stored by X or the
172
+ value stored by a side effect Y on M, where Y follows X in the
173
  modification order of M.
174
 
175
+ [*Note 13*: This requirement is known as read-read
176
  coherence. — *end note*]
177
 
178
  If a value computation A of an atomic object M happens before an
179
+ operation B that modifies M, then A takes its value from a side effect X
180
+ on M, where X precedes B in the modification order of M.
181
 
182
+ [*Note 14*: This requirement is known as read-write
183
  coherence. — *end note*]
184
 
185
  If a side effect X on an atomic object M happens before a value
186
+ computation B of M, then the evaluation B takes its value from X or from
187
+ a side effect Y that follows X in the modification order of M.
188
 
189
+ [*Note 15*: This requirement is known as write-read
190
  coherence. — *end note*]
191
 
192
+ [*Note 16*: The four preceding coherence requirements effectively
193
  disallow compiler reordering of atomic operations to a single object,
194
  even if both operations are relaxed loads. This effectively makes the
195
  cache coherence guarantee provided by most hardware available to C++
196
  atomic operations. — *end note*]
197
 
198
+ [*Note 17*: The value observed by a load of an atomic depends on the
199
  “happens before” relation, which depends on the values observed by loads
200
  of atomics. The intended reading is that there must exist an association
201
  of atomic loads with modifications they observe that, together with
202
  suitably chosen modification orders and the “happens before” relation
203
  derived as described above, satisfy the resulting constraints as imposed
 
213
  potentially concurrent conflicting actions, at least one of which is not
214
  atomic, and neither happens before the other, except for the special
215
  case for signal handlers described below. Any such data race results in
216
  undefined behavior.
217
 
218
+ [*Note 18*: It can be shown that programs that correctly use mutexes
219
  and `memory_order::seq_cst` operations to prevent all data races and use
220
  no other synchronization operations behave as if the operations executed
221
  by their constituent threads were simply interleaved, with each value
222
  computation of an object being taken from the last side effect on that
223
  object in that interleaving. This is normally referred to as “sequential
224
  consistency”. However, this applies only to data-race-free programs, and
225
  data-race-free programs cannot observe most program transformations that
226
  do not change single-threaded program semantics. In fact, most
227
+ single-threaded program transformations remain possible, since any
228
+ program that behaves differently as a result has undefined
229
  behavior. — *end note*]
230
 
231
+ Two accesses to the same non-bit-field object of type
232
+ `volatile std::sig_atomic_t` do not result in a data race if both occur
233
+ in the same thread, even if one or more occurs in a signal handler. For
234
+ each signal handler invocation, evaluations performed by the thread
235
+ invoking a signal handler can be divided into two groups A and B, such
236
+ that no evaluations in B happen before evaluations in A, and the
237
+ evaluations of such `volatile std::sig_atomic_t` objects take values as
238
+ though all evaluations in A happened before the execution of the signal
239
+ handler and the execution of the signal handler happened before all
240
+ evaluations in B.
241
 
242
+ [*Note 19*: Compiler transformations that introduce assignments to a
243
  potentially shared memory location that would not be modified by the
244
  abstract machine are generally precluded by this document, since such an
245
  assignment might overwrite another assignment by a different thread in
246
  cases in which an abstract machine execution would not have encountered
247
  a data race. This includes implementations of data member assignment
248
  that overwrite adjacent members in separate memory locations. Reordering
249
  of atomic loads in cases in which the atomics in question might alias is
250
  also generally precluded, since this could violate the coherence
251
  rules. — *end note*]
252
 
253
+ [*Note 20*: It is possible that transformations that introduce a
254
+ speculative read of a potentially shared memory location do not preserve
255
+ the semantics of the C++ program as defined in this document, since they
256
+ potentially introduce a data race. However, they are typically valid in
257
+ the context of an optimizing compiler that targets a specific machine
258
+ with well-defined semantics for data races. They would be invalid for a
259
  hypothetical machine that is not tolerant of races or provides hardware
260
  race detection. — *end note*]
261
 
262
  #### Forward progress <a id="intro.progress">[[intro.progress]]</a>
263
 
264
  The implementation may assume that any thread will eventually do one of
265
  the following:
266
 
267
  - terminate,
268
+ - invoke the function `std::this_thread::yield` [[thread.thread.this]],
269
  - make a call to a library I/O function,
270
+ - perform an access through a volatile glvalue,
271
+ - perform an atomic or synchronization operation other than an atomic
272
+ modify-write operation [[atomics.order]], or
273
+ - continue execution of a trivial infinite loop [[stmt.iter.general]].
274
 
275
  [*Note 1*: This is intended to allow compiler transformations such as
276
+ removal, merging, and reordering of empty loops, even when termination
277
+ cannot be proven. An affordance is made for trivial infinite loops,
278
+ which cannot be removed nor reordered. — *end note*]
279
 
280
  Executions of atomic functions that are either defined to be lock-free
281
  [[atomics.flag]] or indicated as lock-free [[atomics.lockfree]] are
282
  *lock-free executions*.
283
 
 
301
 
302
  During the execution of a thread of execution, each of the following is
303
  termed an *execution step*:
304
 
305
  - termination of the thread of execution,
306
+ - performing an access through a volatile glvalue,
307
+ - completion of a call to a library I/O function, or
308
+ - completion of an atomic or synchronization operation other than an
309
+ atomic modify-write operation [[atomics.order]].
310
 
311
  An invocation of a standard library function that blocks [[defns.block]]
312
  is considered to continuously execute execution steps while waiting for
313
  the condition that it blocks on to be satisfied.
314
 
 
330
 
331
  For a thread of execution providing *concurrent forward progress
332
  guarantees*, the implementation ensures that the thread will eventually
333
  make progress for as long as it has not terminated.
334
 
335
+ [*Note 5*: This applies regardless of whether or not other threads of
336
+ execution (if any) have been or are making progress. To eventually
337
  fulfill this requirement means that this will happen in an unspecified
338
  but finite amount of time. — *end note*]
339
 
340
  It is *implementation-defined* whether the implementation-created thread
341
  of execution that executes `main` [[basic.start.main]] and the threads