From Jason Turner

[intro.multithread]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmppl8xba52/{from.md → to.md} +37 -36
tmp/tmppl8xba52/{from.md → to.md} RENAMED
@@ -1,22 +1,25 @@
1
  ### Multi-threaded executions and data races <a id="intro.multithread">[[intro.multithread]]</a>
2
 
 
 
3
  A *thread of execution* (also known as a *thread*) is a single flow of
4
  control within a program, including the initial invocation of a specific
5
  top-level function, and recursively including every function invocation
6
  subsequently executed by the thread.
7
 
8
  [*Note 1*: When one thread creates another, the initial call to the
9
  top-level function of the new thread is executed by the new thread, not
10
  by the creating thread. — *end note*]
11
 
12
  Every thread in a program can potentially access every object and
13
- function in a program.[^28] Under a hosted implementation, a C++ program
14
- can have more than one thread running concurrently. The execution of
15
- each thread proceeds as defined by the remainder of this document. The
16
- execution of the entire program consists of an execution of all of its
17
- threads.
 
18
 
19
  [*Note 2*: Usually the execution can be viewed as an interleaving of
20
  all its threads. However, some kinds of atomic operations, for example,
21
  allow executions inconsistent with a simple interleaving, as described
22
  below. — *end note*]
@@ -33,12 +36,12 @@ contains the signal handler invocation.
33
  The value of an object visible to a thread T at a particular point is
34
  the initial value of the object, a value assigned to the object by T, or
35
  a value assigned to the object by another thread, according to the rules
36
  below.
37
 
38
- [*Note 1*: In some cases, there may instead be undefined behavior. Much
39
- of this subclause is motivated by the desire to support atomic
40
  operations with explicit and detailed visibility constraints. However,
41
  it also implicitly supports a simpler view for more restricted
42
  programs. — *end note*]
43
 
44
  Two expression evaluations *conflict* if one of them modifies a memory
@@ -71,11 +74,11 @@ All modifications to a particular atomic object M occur in some
71
  particular total order, called the *modification order* of M.
72
 
73
  [*Note 3*: There is a separate order for each atomic object. There is
74
  no requirement that these can be combined into a single total order for
75
  all objects. In general this will be impossible since different threads
76
- may observe modifications to different objects in inconsistent
77
  orders. — *end note*]
78
 
79
  A *release sequence* headed by a release operation A on an atomic object
80
  M is a maximal contiguous sub-sequence of side effects in the
81
  modification order of M, where the first operation is A, and every
@@ -284,12 +287,12 @@ computation of an object being taken from the last side effect on that
284
  object in that interleaving. This is normally referred to as “sequential
285
  consistency”. However, this applies only to data-race-free programs, and
286
  data-race-free programs cannot observe most program transformations that
287
  do not change single-threaded program semantics. In fact, most
288
  single-threaded program transformations continue to be allowed, since
289
- any program that behaves differently as a result must perform an
290
- undefined operation. — *end note*]
291
 
292
  Two accesses to the same object of type `volatile std::sig_atomic_t` do
293
  not result in a data race if both occur in the same thread, even if one
294
  or more occurs in a signal handler. For each signal handler invocation,
295
  evaluations performed by the thread invoking a signal handler can be
@@ -305,17 +308,17 @@ potentially shared memory location that would not be modified by the
305
  abstract machine are generally precluded by this document, since such an
306
  assignment might overwrite another assignment by a different thread in
307
  cases in which an abstract machine execution would not have encountered
308
  a data race. This includes implementations of data member assignment
309
  that overwrite adjacent members in separate memory locations. Reordering
310
- of atomic loads in cases in which the atomics in question may alias is
311
- also generally precluded, since this may violate the coherence
312
  rules. — *end note*]
313
 
314
  [*Note 23*: Transformations that introduce a speculative read of a
315
- potentially shared memory location may not preserve the semantics of the
316
- C++ program as defined in this document, since they potentially
317
  introduce a data race. However, they are typically valid in the context
318
  of an optimizing compiler that targets a specific machine with
319
  well-defined semantics for data races. They would be invalid for a
320
  hypothetical machine that is not tolerant of races or provides hardware
321
  race detection. — *end note*]
@@ -338,25 +341,25 @@ Executions of atomic functions that are either defined to be lock-free
338
  [[atomics.flag]] or indicated as lock-free [[atomics.lockfree]] are
339
  *lock-free executions*.
340
 
341
  - If there is only one thread that is not blocked [[defns.block]] in a
342
  standard library function, a lock-free execution in that thread shall
343
- complete. \[*Note 2*: Concurrently executing threads may prevent
344
  progress of a lock-free execution. For example, this situation can
345
  occur with load-locked store-conditional implementations. This
346
  property is sometimes termed obstruction-free. — *end note*]
347
  - When one or more lock-free executions run concurrently, at least one
348
  should complete. \[*Note 3*: It is difficult for some implementations
349
  to provide absolute guarantees to this effect, since repeated and
350
- particularly inopportune interference from other threads may prevent
351
  forward progress, e.g., by repeatedly stealing a cache line for
352
  unrelated purposes between load-locked and store-conditional
353
- instructions. Implementations should ensure that such effects cannot
354
- indefinitely delay progress under expected operating conditions, and
355
- that such anomalies can therefore safely be ignored by programmers.
356
- Outside this document, this property is sometimes termed
357
- lock-free. — *end note*]
358
 
359
  During the execution of a thread of execution, each of the following is
360
  termed an *execution step*:
361
 
362
  - termination of the thread of execution,
@@ -368,11 +371,11 @@ An invocation of a standard library function that blocks [[defns.block]]
368
  is considered to continuously execute execution steps while waiting for
369
  the condition that it blocks on to be satisfied.
370
 
371
  [*Example 1*: A library I/O function that blocks until the I/O
372
  operation is complete can be considered to continuously check whether
373
- the operation is complete. Each such check might consist of one or more
374
  execution steps, for example using observable behavior of the abstract
375
  machine. — *end example*]
376
 
377
  [*Note 4*: Because of this and the preceding requirement regarding what
378
  threads of execution have to perform eventually, it follows that no
@@ -387,30 +390,28 @@ concurrent threads that are not blocked in a standard library function
387
  For a thread of execution providing *concurrent forward progress
388
  guarantees*, the implementation ensures that the thread will eventually
389
  make progress for as long as it has not terminated.
390
 
391
  [*Note 5*: This is required regardless of whether or not other threads
392
- of executions (if any) have been or are making progress. To eventually
393
  fulfill this requirement means that this will happen in an unspecified
394
  but finite amount of time. — *end note*]
395
 
396
  It is *implementation-defined* whether the implementation-created thread
397
  of execution that executes `main` [[basic.start.main]] and the threads
398
  of execution created by `std::thread` [[thread.thread.class]] or
399
  `std::jthread` [[thread.jthread.class]] provide concurrent forward
400
- progress guarantees.
401
-
402
- [*Note 6*: General-purpose implementations should provide these
403
- guarantees. — *end note*]
404
 
405
  For a thread of execution providing *parallel forward progress
406
  guarantees*, the implementation is not required to ensure that the
407
  thread will eventually make progress if it has not yet executed any
408
  execution step; once this thread has executed a step, it provides
409
  concurrent forward progress guarantees.
410
 
411
- [*Note 7*: This does not specify a requirement for when to start this
412
  thread of execution, which will typically be specified by the entity
413
  that creates this thread of execution. For example, a thread of
414
  execution that provides concurrent forward progress guarantees and
415
  executes tasks from a set of tasks in an arbitrary order, one after the
416
  other, satisfies the requirements of parallel forward progress for these
@@ -418,57 +419,57 @@ tasks. — *end note*]
418
 
419
  For a thread of execution providing *weakly parallel forward progress
420
  guarantees*, the implementation does not ensure that the thread will
421
  eventually make progress.
422
 
423
- [*Note 8*: Threads of execution providing weakly parallel forward
424
  progress guarantees cannot be expected to make progress regardless of
425
  whether other threads make progress or not; however, blocking with
426
  forward progress guarantee delegation, as defined below, can be used to
427
  ensure that such threads of execution make progress
428
  eventually. — *end note*]
429
 
430
  Concurrent forward progress guarantees are stronger than parallel
431
  forward progress guarantees, which in turn are stronger than weakly
432
  parallel forward progress guarantees.
433
 
434
- [*Note 9*: For example, some kinds of synchronization between threads
435
- of execution may only make progress if the respective threads of
436
  execution provide parallel forward progress guarantees, but will fail to
437
  make progress under weakly parallel guarantees. — *end note*]
438
 
439
  When a thread of execution P is specified to *block with forward
440
  progress guarantee delegation* on the completion of a set S of threads
441
  of execution, then throughout the whole time of P being blocked on S,
442
  the implementation shall ensure that the forward progress guarantees
443
  provided by at least one thread of execution in S is at least as strong
444
  as P’s forward progress guarantees.
445
 
446
- [*Note 10*: It is unspecified which thread or threads of execution in S
447
  are chosen and for which number of execution steps. The strengthening is
448
  not permanent and not necessarily in place for the rest of the lifetime
449
  of the affected thread of execution. As long as P is blocked, the
450
  implementation has to eventually select and potentially strengthen a
451
  thread of execution in S. — *end note*]
452
 
453
  Once a thread of execution in S terminates, it is removed from S. Once S
454
  is empty, P is unblocked.
455
 
456
- [*Note 11*: A thread of execution B thus can temporarily provide an
457
  effectively stronger forward progress guarantee for a certain amount of
458
  time, due to a second thread of execution A being blocked on it with
459
  forward progress guarantee delegation. In turn, if B then blocks with
460
- forward progress guarantee delegation on C, this may also temporarily
461
  provide a stronger forward progress guarantee to C. — *end note*]
462
 
463
- [*Note 12*: If all threads of execution in S finish executing (e.g.,
464
  they terminate and do not use blocking synchronization incorrectly),
465
  then P’s execution of the operation that blocks with forward progress
466
  guarantee delegation will not result in P’s progress guarantee being
467
  effectively weakened. — *end note*]
468
 
469
- [*Note 13*: This does not remove any constraints regarding blocking
470
  synchronization for threads of execution providing parallel or weakly
471
  parallel forward progress guarantees because the implementation is not
472
  required to strengthen a particular thread of execution whose too-weak
473
  progress guarantee is preventing overall progress. — *end note*]
474
 
 
1
  ### Multi-threaded executions and data races <a id="intro.multithread">[[intro.multithread]]</a>
2
 
3
+ #### General <a id="intro.multithread.general">[[intro.multithread.general]]</a>
4
+
5
  A *thread of execution* (also known as a *thread*) is a single flow of
6
  control within a program, including the initial invocation of a specific
7
  top-level function, and recursively including every function invocation
8
  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.
21
 
22
  [*Note 2*: Usually the execution can be viewed as an interleaving of
23
  all its threads. However, some kinds of atomic operations, for example,
24
  allow executions inconsistent with a simple interleaving, as described
25
  below. — *end note*]
 
36
  The value of an object visible to a thread T at a particular point is
37
  the initial value of the object, a value assigned to the object by T, or
38
  a value assigned to the object by another thread, according to the rules
39
  below.
40
 
41
+ [*Note 1*: In some cases, there might instead be undefined behavior.
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
 
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
 
82
  A *release sequence* headed by a release operation A on an atomic object
83
  M is a maximal contiguous sub-sequence of side effects in the
84
  modification order of M, where the first operation is A, and every
 
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
 
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*]
 
341
  [[atomics.flag]] or indicated as lock-free [[atomics.lockfree]] are
342
  *lock-free executions*.
343
 
344
  - If there is only one thread that is not blocked [[defns.block]] in a
345
  standard library function, a lock-free execution in that thread shall
346
+ complete. \[*Note 2*: Concurrently executing threads might prevent
347
  progress of a lock-free execution. For example, this situation can
348
  occur with load-locked store-conditional implementations. This
349
  property is sometimes termed obstruction-free. — *end note*]
350
  - When one or more lock-free executions run concurrently, at least one
351
  should complete. \[*Note 3*: It is difficult for some implementations
352
  to provide absolute guarantees to this effect, since repeated and
353
+ particularly inopportune interference from other threads could prevent
354
  forward progress, e.g., by repeatedly stealing a cache line for
355
  unrelated purposes between load-locked and store-conditional
356
+ instructions. For implementations that follow this recommendation and
357
+ ensure that such effects cannot indefinitely delay progress under
358
+ expected operating conditions, such anomalies can therefore safely be
359
+ ignored by programmers. Outside this document, this property is
360
+ sometimes termed lock-free. — *end note*]
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,
 
371
  is considered to continuously execute execution steps while waiting for
372
  the condition that it blocks on to be satisfied.
373
 
374
  [*Example 1*: A library I/O function that blocks until the I/O
375
  operation is complete can be considered to continuously check whether
376
+ the operation is complete. Each such check consists of one or more
377
  execution steps, for example using observable behavior of the abstract
378
  machine. — *end example*]
379
 
380
  [*Note 4*: Because of this and the preceding requirement regarding what
381
  threads of execution have to perform eventually, it follows that no
 
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
401
  of execution created by `std::thread` [[thread.thread.class]] or
402
  `std::jthread` [[thread.jthread.class]] provide concurrent forward
403
+ progress guarantees. General-purpose implementations should provide
404
+ these guarantees.
 
 
405
 
406
  For a thread of execution providing *parallel forward progress
407
  guarantees*, the implementation is not required to ensure that the
408
  thread will eventually make progress if it has not yet executed any
409
  execution step; once this thread has executed a step, it provides
410
  concurrent forward progress guarantees.
411
 
412
+ [*Note 6*: This does not specify a requirement for when to start this
413
  thread of execution, which will typically be specified by the entity
414
  that creates this thread of execution. For example, a thread of
415
  execution that provides concurrent forward progress guarantees and
416
  executes tasks from a set of tasks in an arbitrary order, one after the
417
  other, satisfies the requirements of parallel forward progress for these
 
419
 
420
  For a thread of execution providing *weakly parallel forward progress
421
  guarantees*, the implementation does not ensure that the thread will
422
  eventually make progress.
423
 
424
+ [*Note 7*: Threads of execution providing weakly parallel forward
425
  progress guarantees cannot be expected to make progress regardless of
426
  whether other threads make progress or not; however, blocking with
427
  forward progress guarantee delegation, as defined below, can be used to
428
  ensure that such threads of execution make progress
429
  eventually. — *end note*]
430
 
431
  Concurrent forward progress guarantees are stronger than parallel
432
  forward progress guarantees, which in turn are stronger than weakly
433
  parallel forward progress guarantees.
434
 
435
+ [*Note 8*: For example, some kinds of synchronization between threads
436
+ of execution might only make progress if the respective threads of
437
  execution provide parallel forward progress guarantees, but will fail to
438
  make progress under weakly parallel guarantees. — *end note*]
439
 
440
  When a thread of execution P is specified to *block with forward
441
  progress guarantee delegation* on the completion of a set S of threads
442
  of execution, then throughout the whole time of P being blocked on S,
443
  the implementation shall ensure that the forward progress guarantees
444
  provided by at least one thread of execution in S is at least as strong
445
  as P’s forward progress guarantees.
446
 
447
+ [*Note 9*: It is unspecified which thread or threads of execution in S
448
  are chosen and for which number of execution steps. The strengthening is
449
  not permanent and not necessarily in place for the rest of the lifetime
450
  of the affected thread of execution. As long as P is blocked, the
451
  implementation has to eventually select and potentially strengthen a
452
  thread of execution in S. — *end note*]
453
 
454
  Once a thread of execution in S terminates, it is removed from S. Once S
455
  is empty, P is unblocked.
456
 
457
+ [*Note 10*: A thread of execution B thus can temporarily provide an
458
  effectively stronger forward progress guarantee for a certain amount of
459
  time, due to a second thread of execution A being blocked on it with
460
  forward progress guarantee delegation. In turn, if B then blocks with
461
+ forward progress guarantee delegation on C, this can also temporarily
462
  provide a stronger forward progress guarantee to C. — *end note*]
463
 
464
+ [*Note 11*: If all threads of execution in S finish executing (e.g.,
465
  they terminate and do not use blocking synchronization incorrectly),
466
  then P’s execution of the operation that blocks with forward progress
467
  guarantee delegation will not result in P’s progress guarantee being
468
  effectively weakened. — *end note*]
469
 
470
+ [*Note 12*: This does not remove any constraints regarding blocking
471
  synchronization for threads of execution providing parallel or weakly
472
  parallel forward progress guarantees because the implementation is not
473
  required to strengthen a particular thread of execution whose too-weak
474
  progress guarantee is preventing overall progress. — *end note*]
475