<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>



<meta http-equiv="Content-Type" content="text/html;charset=us-ascii"><title>3057: Explicit Initializers for Atomics</title></head><body>
<h1>Explicit Initializers for Atomics</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3057 = 10-0047 - 2010-03-11
</p>

<p>
Paul E. McKenney, paulmck@linux.vnet.ibm.com
<br>
Mark Batty, mjb220@cl.cam.ac.uk
<br>
Clark Nelson, clark.nelson@intel.com
<br>
N.M. Maclaren, nmm1@cam.ac.uk
<br>
Hans Boehm, hans.boehm@hp.com
<br>
Anthony Williams, anthony@justsoftwaresolutions.co.uk
<br>
Peter Dimov, pdimov@mmltd.net
<br>
Lawrence Crowl, crowl@google.com, Lawrence@Crowl.org
</p>

<h2>Introduction</h2>

<p>
Mark Batty recently undertook a partial formalization of the C++
memory model, which  Mark summarized in
<a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2955.html">N2955</a>.
This paper summarizes the discussions on Mark's paper, both verbal and
email, recommending appropriate actions for the Library Working Group.
Core issues are dealt with in a companion N3074 paper.
</p>

<p>This paper is based on
<a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3045.html">N3045</a>,
and has been updated to reflect discussions in the Concurrency subgroup
of the Library Working Group in Pittsburgh.
This paper also carries the C-language side of
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3040.html">N3040</a>,
which was also discussed in the Concurrency subgroup of the Library
Working Group in Pittsburgh.
</p>

<h3>Library Issues</h3>

<h3>Library Issue 1: 29.3p1 Limits to Memory-Order Relaxation (Non-Normative)</h3>

<p>
Add a note stating that <code>memory_order_relaxed</code> operations
must maintain indivisibility, as described in the discussion of 1.10p4.
This must be considered in conjunction with the resolution to LWG 1151,
which is expected to be addressed by Hans Boehm in N3040.
</p>

<h3>Library Issue 2: 29.3p11 Schedulers, Loops, and Atomics (Normative)</h3>

<p>
The second sentence of this paragraph, &ldquo;Implementations shall not
move an atomic operation out of an unbounded loop&rdquo;, does not add
anything to the first sentence, and, worse, can be interpreted as restricting
the meaning of the first sentence.
This sentence should therefore be deleted.
The Library Working Group discussed this change during the Santa Cruz
meeting in October 2009, and agreed with this deletion.
</p>

<h3>Library Issue 3: 29.5.1 Uninitialized Atomics and C/C++ Compatibility (Normative)</h3>

<p>
This topic was the subject of a spirited discussion among a subset of
the participants in the C/C++-compatibility effort this past October and
November.
</p>

<p>
Unlike C++, C has no mechanism to force a given variable to be
initialized.
Therefore, if C++ atomics are going to be compatible with those of C,
either C++ needs to tolerate uninitialized atomic objects, or C needs
to require that all atomic objects be initialized.
There are a number of cases to consider:
</p>
<ol>
<li>	C static variables.  The C standard specifies that these are
	initialized bitwise to zero.
	The C &ldquo;<code>={value}</code>&rdquo; syntax may be used
	to explicitly initialize these values, however, such initialization
	may <i>not</i> contain any statements executing at run time.
<li>	C on-stack <code>auto</code> variables.  The C standard does not
	require that these be initialized.
	On some machines, such variables might be
	initialized to an error value (for example, not-a-thing (NAT)
	for variables on Itanium that live only in a machine register).
	The C &ldquo;<code>={value}</code>&rdquo; syntax may be used
	to explicitly initialize these values, and may include
	statements executing at run time.
<li>	C dynamically allocated variables, for example, via
	<code>malloc()</code>.
	The C standard does not require that these be initialized.
	The C &ldquo;<code>={value}</code>&rdquo; syntax may <i>not</i> be
	used to explicitly initialize these values.
</ol>

<p>Of course, C on-stack <code>auto</code> variables and dynamically
allocated variables are inaccessible to other threads until references
to them are published.
Such publication must ensure that any initialization happens before any
access to the variable from another thread, for example, by use of
store release or locking.
</p>

<p>
There are also a number of interesting constraints on these types:
</p>
<ol>
<li>	The
	<a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf">
	C++0x Working Draft</a>
	requires that the atomic integral type have
	standard layout (29.5.1p2).
<li>	The
	<a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf">
	C++0x Working Draft</a>
	requires that the atomic pointer type have
	standard layout (29.5.2p1).
<li>	The
	<a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2009/n3000.pdf">
	C++0x Working Draft</a>
	requires that the atomic flag type have
	standard layout (29.7p3).
</ol>

<p>
These constraints permit but three known ways for C++ to make use of
non-generic atomic types defined in C-language translation units:
</p>

<ol>
<li>	The atomic type is a structure containing a single field of
	the underlying type, possibly followed by padding.
	There is an implementation-provided external lock table,
	and the implementation locates the lock corresponding to
	a given instance of an atomic type by hashing that
	instance's address.
	The implementation is of course responsible for correctly
	initializing the array of locks.
	This implementation permits C++ to tolerate an unspecified initial
	value for a given instance of an atomic type, but only in cases
	where every bit pattern corresponds to a valid value of the atomic
	type in question.
<li>	The atomic type is a structure containing a single field of
	the underlying type, possibly followed by padding.
	If the atomic type is implemented in a non-lock-free manner,
	an external table is used to check whether a given instance of
	an atomic type has been initialized, allowing it to be initialized
	if required.
	Such initialization could include any locks that might be embedded
	in instance of the atomic type.
	This external table would
	be accessed by both C and C++ code for each access to the atomic
	variable in question (although a clever optimizer might be able
	to elide some table accesses).
	This table would clearly need to be implemented so as to tolerate
	multithreaded access and modification.
	In addition, special handling might be required to ensure that
	any atomic variables residing in deallocated memory were removed
	from the external table.
	There are therefore serious concerns about the overhead of this
	approach.
<li>	If the underlying hardware supports atomic operations that are
	large enough to cover the given non-generic atomic type, then
	those atomic operations can be used directly.
<li>	Any instance of an atomic type that is defined in a C-language
	translation units must be initialized by C code before
	the first C++ use of that instance.
	This approach requires two syntaxes for C-language initialization,
	one to be applied to static variables and another for dynamically
	allocated objects.  Either syntax may be appled to <code>auto</code>
	variables.
</ol>

<p>
The wording below permits any of the above implementation alternatives.
Note that WG14's C-language working draft also requires initializers
for non-flag atomic types (initialization is already provided in the C++
working draft via constructors).
These are listed in a subsequent section.
</p>

<h2>WG21 C++-Language Wording</h2>

<h4>Wording for Library Issue 1</h4>

<p>
Add a note as follows:
</p>

<blockquote>
	<p>
	The enumeration <code>memory_order</code> specifies the detailed
	regular (non&ndash;atomic) memory synchronization order
	as defined in 1.10 and may provide for operation ordering.
	Its enumerated values and their meanings are as follows:</p>
	<p>
	&mdash;	memory_order_relaxed: no operation orders memory.<br>
	&mdash;	<code>memory_order_release</code>,
		<code>memory_order_acq_rel</code>, and
		<code>memory_order_seq_cst</code>: a store operation performs
		a release operation on the affected memory location.<br>
	&mdash; <code>memory_order_consume</code>: a load operation
		performs a consume operation on the affected memory
		location.<br>
	&mdash; <code>memory_order_acquire</code>,
		<code>memory_order_acq_rel</code>, and
		<code>memory_order_seq_cst</code>: a load operation performs
		an acquire operation on the affected memory location.
	<p>
	<ins> [ Note: Atomic operations specifying
	<code>memory_order_relaxed</code> are relaxed only with
	respect to memory ordering.  Implementations must still
	guarantee that any given atomic access to a particular
	atomic object be indivisible with respect to all other
	atomic accesses to that object.  &mdash; end note. ]</ins>
	</p>
</blockquote>

<h4>Wording for Library Issue 2</h4>

<p>
Therefore, remove the second sentence of 29.3p11 as follows:
</p>

<blockquote>
	<p>
	Implementations should make atomic stores visible to atomic
	loads within a reasonable amount of time.
	<del>Implementations shall not move an atomic operation out of an
	unbounded loop.</del>
	</p>
</blockquote>

<h4>Wording for Library Issue 3</h4>

<p>Add the following to WG21 29.5.1 (Integral Types) in locations
corresponding to the existing <code>atomic_is_lock_free()</code> functions:
</p>

<blockquote>
	<p>
	<ins><code>void atomic_init(volatile atomic_bool*, bool);</code></ins>
	</p>
	<p>
	<ins><code>void atomic_init(atomic_bool*, bool);</code></ins>
	</p>
	<p>
	<ins><code>void atomic_init(volatile atomic_<i>itype</i>*, <i>itype</i>);</code></ins>
	</p>
	<p>
	<ins><code>void atomic_init(atomic_<i>itype</i>*, <i>itype</i>);</code></ins>
	</p>
</blockquote>

<p>
Note that <code>ATOMIC_INIT</code> is already in use, for example, in
the Linux kernel.
Google code search was unable to find <code>ATOMIC_VAR_INIT</code> or
<code>atomic_init</code>.
</p>

<p>Add the following to WG21 29.5.2 (Address Type) located
corresponding to the existing <code>atomic_is_lock_free()</code> function:
</p>

<blockquote>
	<p>
	<ins><code>void atomic_init(volatile atomic_address*, void *);</code></ins>
	</p>
	<p>
	<ins><code>void atomic_init(atomic_address*, void *);</code></ins>
	</p>
</blockquote>

<p>Add the following after WG21 29.6p4 (Operations on Atomic Types):
</p>

<blockquote>
	<p>
	<ins><code>#define ATOMIC_VAR_INIT(<i>value</i>)</code>
	<i>implementation-defined</i></ins>
	</p>
	<p>
	<ins>A macro expanding to a token sequence suitable for initializing an
	atomic variable of a type that is initialization&ndash;compatible with
	<var>value</var>.
	Concurrent access to the variable being initialized, even via an
	atomic operation, constitutes a data race. </ins>
	</p>
	<p>
	<ins>[ Example: </ins>
	</p>
	<p>
	<ins><code>atomic_int v = ATOMIC_VAR_INIT(5);</code></ins>
	</p>
	<p>
	<ins>&mdash; end example ]</ins>
	</p>
</blockquote>

<p>Add the following after WG21 29.6p5 (Operations on Atomic Types):
</p>

<blockquote>
	<p>
	<ins><code>void atomic_init(volatile A *object, C desired);</code></ins>
	</p>
	<p>
	<ins><code>void atomic_init(A *object, C desired);</code></ins>
	</p>
	<p>
	<i>Effects:</i> Non&ndash;atomically assigns the value <var>desired</var> to
	<var>object</var>.
	Concurrent access from another thread, even via an atomic operation,
	constitutes a data race.
	</p>
</blockquote>

<h2>WG14 C&ndash;Language Wording</h2>

<p>Change WG14 7.16.1p1 as follows:
</p>

<blockquote>
	<p>
	The header &lt;stdatomic.h&gt; defines
	<del>three</del><ins>several</ins>
	macros and declares several types and functions for performing
	atomic operations on data shared between threads.
	</p>
</blockquote>

<p>Change WG14 7.16.1p2 as follows:
</p>

<blockquote>
	<p> The macros defined are</p>
	<p>
	<del><code>ATOMIC_INTEGRAL_FREE</code></del><br>
	<ins><code>ATOMIC_CHAR_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_CHAR16_T_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_CHAR32_T_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_WCHAR_T_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_SHORT_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_INT_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_LONG_LOCK_FREE</code></ins><br>
	<ins><code>ATOMIC_LLONG_LOCK_FREE</code></ins><br>
	<code>ATOMIC_ADDRESS_LOCK_FREE</code><br>
	</p>
	<p>which indicate the <del>general</del>
	lock&ndash;free property of <del>integer and
	address</del> <ins>the corresponding</ins> atomic types<ins>, with
	the signed and unsigned variants grouped together</ins>; and</p>
	<p>
	<code>ATOMIC_FLAG_INIT</code><br>
	<ins><code>ATOMIC_VAR_INIT</code></ins><br>
	<ins><code>atomic_init</code></ins><br>
	</p>
	<p>which expands to an initializer for an object of type
	atomic_flag<del>.</del><ins>,</ins>
	<ins>to an initializer of an atomic type,
	and to an execution&ndash;time initializer for an atomic type,
	respectively.</ins></p>
</blockquote>

<p>As called out in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3040.html">N3040</a>
&ldquo;More precise definition of atomic&rdquo;,
add a paragraph to WG14 preceding 7.16p13 as follows:

<blockquote>
	<p>
	<ins>Atomic read-modify-write operations shall always read the
	last value (in the modification order) written before the write
	associated with the read-modify-write operation.</ins>
	</p>
</blockquote>

<p>Change WG14 7.16p13 as follows:
</p>

<blockquote>
	<p>
	Implementations should make atomic stores visible to atomic
	loads within a reasonable amount of time.
	<del>Implementations shall not move an atomic operation out of an
	unbounded loop.</del>
	</p>
</blockquote>

<p>Add a new section to WG14 named &ldquo;Initialization&rdquo;:
</p>

<blockquote>
	<p><ins>7.16.N Initialization</ins></p>
	<p><ins>The macro <code>ATOMIC_VAR_INIT</code> may be used
	to initialize an atomic variable declaration, however,
	the default zero&ndash;initialization is guaranteed to produce
	a valid object where it applies.</ins></p>
	<p><ins>EXAMPLE</ins></p>
	<p><ins><code>atomic_int guide = ATOMIC_VAR_INIT(42);</code></ins></p>
	<p><ins>The macro <code>atomic_init</code> may be used
	to initialize an atomic variable at execution time, for example,
	for atomic variables that have been dynamically allocated.</ins></p>
	<p><ins>EXAMPLE</ins></p>
	<p><ins><code>atomic_init(&amp;p->a, 42);</code></ins></p>
	<p><ins>An atomic variable that is not explicitly initialized with
	<code>ATOMIC_VAR_INIT</code> is initially in an indeterminate
	state.</ins></p>
</blockquote>

</body></html>
