Updates to C++ Memory Model Based on Formalization

ISO/IEC JTC1 SC22 WG14 N1417 - 2009-10-27

Paul E. McKenney, [email protected]

Introduction

WG21 added memory fences to their working draft to ease migration of current practice to the C++0x standard, choosing semantics that can be readily implemented on current multicore/parallel systems. Memory fences are often provided in concurrent C and C++ programming environments, usually in the form of platform-dependent inline assembly. Adding memory fences to the standard promotes portability.

The purpose of this document is informative. If there is interest, a document proposing changes will follow.

The remainder of this document summarizes the definition of fences in the C++ working draft N2960.

29.3 Order and Consistency (Additions)

  1. For an atomic operation B that reads the value of an atomic object M, if there is a memory_order_seq_cst fence X sequenced before B, then B observes either the last memory_order_seq_cst modification of M preceding X in the total order S or a later modification of M in its modification order.
  2. For atomic operations A and B on an atomic object M, where A modifies M and B takes its value, if there is a memory_order_seq_cst fence X such that A is sequenced before X and B follows X in S, then B observes either the effects of A or a later modification of M in its modification order.
  3. For atomic operations A and B on an atomic object M, where A modifies M and B takes its value, if there are memory_order_seq_cst fences X and Y such that A is sequenced before X, Y is sequenced before B, and X precedes Y in S, then B observes either the effects of A or a later modification of M in its modification order.

29.8 Fences (New)

  1. This section introduces synchronization primitives called fences. Fences can have acquire semantics, release semantics, or both. A fence with acquire semantics is called an acquire fence. A fence with release semantics is called a release fence.
  2. A release fence A synchronizes with an acquire fence B if there exist atomic operations X and Y, both operating on some atomic object M, such that A is sequenced before X, X modifies M, Y is sequenced before B, and Y reads the value written by X or a value written by any side effect in the hypothetical release sequence X would head if it were a release operation.
  3. A release fence A synchronizes with an atomic operation B that performs an acquire operation on an atomic object M if there exists an atomic operation X such that A is sequenced before X, X modifies M, and B reads the value written by X or a value written by any side effect in the hypothetical release sequence X would head if it were a release operation.
  4. An atomic operation A that is a release operation on an atomic object M synchronizes with an acquire fence B if there exists some atomic operation X on M such that X is sequenced before B and reads the value written by A or a value written by any side effect in the release sequence headed by A.

    void atomic_thread_fence(memory_order order);

  5. Effects: depending on the value of order, this operation:

    void atomic_signal_fence(memory_order order);

  6. Effects: equivalent to atomic_thread_fence(order), except that synchronizes with relationships are established only between a thread and a signal handler executed in the same thread.
  7. Note: atomic_signal_fence can be used to specify the order in which actions performed by the thread become visible to the signal handler.
  8. Note: compiler optimizations and reorderings of loads and stores are inhibited in the same way as with atomic_thread_fence, but the hardware fence instructions that atomic_thread_fence would have inserted are not emitted.