This is the mail archive of the
mailing list for the glibc project.
Re: Implementing C++1x and C1x atomics
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: Lawrence Crowl <crowl at google dot com>
- Cc: Richard Guenther <richard dot guenther at gmail dot com>, "Boehm, Hans" <hans dot boehm at hp dot com>, Andrew Haley <aph at redhat dot com>, Paolo Bonzini <bonzini at gnu dot org>, gcc at gcc dot gnu dot org, libc-alpha at sourceware dot org
- Date: Thu, 13 Aug 2009 01:22:37 +0000 (UTC)
- Subject: Re: Implementing C++1x and C1x atomics
- References: <4A82E93B.email@example.com> <Pine.LNX.firstname.lastname@example.org> <4A82F34B.email@example.com> <4A82F47A.firstname.lastname@example.org> <4A82F5C0.email@example.com> <4A82F88D.firstname.lastname@example.org> <238A96A773B3934685A7269CC8A8D042577A01E71A@GVW0436EXB.americas.hpqcorp.net> <238A96A773B3934685A7269CC8A8D042577A01E754@GVW0436EXB.americas.hpqcorp.net> <email@example.com> <Pine.LNX.firstname.lastname@example.org><email@example.com>
On Wed, 12 Aug 2009, Lawrence Crowl wrote:
> > The C1x atomics specification
> > <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1349.htm> does
> > not mention any amendment to the list of headers to be provided by
> > freestanding implementations (clause 4 paragraph 6), which suggests
> > that providing this header is actually in the domain of libc, not
> > the compiler (which accords with it providing (generic) library
> > functions, which the headers for freestanding implementations
> > do not). It seems clear however that close cooperation with the
> > compiler will be needed in the implementation to ensure that the
> > right semantics are available from the compiler for the header
> > to use.
> I think the C++ specification currently has the same problem.
> The atomics are really a compiler issue.
In that it defines functions, <stdatomic.h> is unlike all the headers
presently required of freestanding implementations, and seems much more
like <tgmath.h> - a header that involves library functions, depends on the
library to some extent (if you implement the ISO 24747 functions then that
has additions to <tgmath.h> as well as <math.h>) but is nevertheless
almost entirely compiler-specific.
> > The information the compiler should provide the library would
> > include which operations are available built-in or in libgcc
> > and which the C library has to emulate with locks (if e.g. a
> > particular architecture or subarchitecture does not have 64-bit
> > atomic operations). Given how many variations there are on what
> > targets support and how, and given that what's supported may
> > depend on -march etc. options passed when compiling code that
> > includes the header, I think a single version of the header for
> > all targets, that contains code conditional on various predefined
> > macros, would be a good ideal to aim for.
> The compiler must recognize all the atomic operations, so that it can
> respect their implications, which means that they must be intrinsics.
It is of course valid for a user program to wrap a call to an atomic
operation in a call to its own function that calls an intrinsic - and a
macro or inline function in the header could just as much use intrinsics
in some cases and fall back to library functions, or more complicated
sequences of intrinsics, in other cases. It doesn't seem immediately
obvious whether the compiler should provide intrinsics for each case and
handle falling back to the library as needed or whether the header should
handle fallback. If the compiler provides all the intrinsics, it needs to
agree with the library on what all the underlying functions are.
> Then there is direct instruction support for all the operations of
> a type, it should emit that code. When not, the compiler should
> emit a call into a shared library that comes with the system.
Existing practice is to use static-only libgcc functions for __sync_*
where they go in libgcc (for ARM, SH and PA GNU/Linux, where kernel help
is needed for atomic operations in some cases), not shared libraries.
But those are cases where atomic operations are supported with kernel help
rather than ones where you are trying to make a userspace emulation with
locks - and it's the kernel's job to make the kernel-supported
implementations interoperate with native hardware instructions. "comes
with the system" could mean either libgcc or libc (or a vDSO provided by
> You really do not want to take the risk of getting two different
> implementations of the atomics. They will fail to synchronize with
> each other, and result in intermitent concurrency bugs. Yuck.
Is the point here that it's problematic to use real atomic operations on
some subarchitectures that support them for a given type but emulations
using locks for other subarchitectures, because they will not interoperate
properly? That does seem a good point, that which types direct atomic
operations are used on must be considered part of the platform ABI, and so
if newer hardware adds 64-bit atomic operations (say) they must still not
be used if some other code (accessing the same object) might be using
Since static libgcc is generally useful and so programs may end up using
functions from more than one version of libgcc your suggestion of putting
functions in a shared library to avoid this issue would imply:
* The out-of-line functions go in shared libc.
* The header therefore comes with libc.
* The header never uses an inline operation when compiling for a
particular subarchitecture unless the corresponding version of libc, when
executing on hardware capable of executing code for that subarchitecture,
will always use an atomic operation that interoperates correctly with the
header. (libc might need in some cases to determine the hardware in use
So whether an operation is inlined would be a function both of what the
compiler knows the hardware supports and what the header knows about what
libc will do at runtime. (But much of the complexity only arises when a
single ABI supports hardware with different sets of atomic operations.)
(Using functions present in libgcc_s but not static libgcc might be
possible here as an alternative to using libc, but libc can more readily
access HWCAP information for hardware identification at runtime than
> > The compiler would also need to meet the underlying memory model
> > requirements - avoiding optimizations that break the memory model
> > assumptions (writes to locations that may not be written in the
> > memory model, in particular) unless given an option to say it
> > doesn't need to follow the model.
> My recommendation is to just do a good enough job on _changing_
> the optimizations so that you don't need an option. It would
> probably avoid some rather elusive bugs when someone links in a
> library compiled the wrong way.
I'm thinking of such an option as being one to use when building a
single-threaded program, not for use when building libraries.
Joseph S. Myers