This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Implementing C++1x and C1x atomics


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 
the kernel).

> 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 
emulations.

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 
at runtime.)

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 
libgcc can.)

> > 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
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]