[cfe-commits] [PATCH] atomic operation builtins, part 1

Jeffrey Yasskin jyasskin at google.com
Wed Oct 12 14:55:43 PDT 2011

[+ Lawrence who's been driving the ABI-compatibility design. Context
at http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20111010/047614.html]

On Wed, Oct 12, 2011 at 10:57 AM, John McCall <rjmccall at apple.com> wrote:
> On Oct 12, 2011, at 9:03 AM, Jeffrey Yasskin wrote:
>> On Wed, Oct 12, 2011 at 6:31 AM, Andrew MacLeod <amacleod at redhat.com> wrote:
>>> - language atomic types up to 16 bytes should be padded to an appropriate
>>> size, and aligned properly.
>>> - if memory matching one of the 5 'optimized' sizes isn't aligned properly,
>>> results are undefined.
>>> - if the size does not match one of the 5 specific routines, then the
>>> library generic ABI can handle it.  There's no alignment guarantees, so I
>>> presume it would end up being a locked implementation using hash tables and
>>> addresses or something.
>> The ABI library needs to demand alignment guarantees, or have them
>> passed in, or it won't be able to support larger lock-free sizes on
>> new architectures.
> How aggressive are you suggesting we be about this?  If I make this type atomic:
>  struct { float values[5]; };
> do we really increase its size and alignment up to 32 bytes in the wild hope that the architecture will add 32-byte atomics someday?  If so, what's the limit?  If not, why is 16 the limit?

The goal was that architectures could add new atomic instructions
without forcing an ABI change. Changing the size of atomic<FiveFloats>
would be an ABI change, so we should try to plan ahead to avoid it.
All the existing atomics have required alignments equal to their
sizes, and whole-cacheline cmpxchg seems like a plausible future
instruction and would also require alignment equal to the size, so
that's what I've been suggesting.

I suspect users won't use really large types with atomic<T> simply
because every access requires a copy of the whole object. And when
they switch to explicitly locked data, that'll avoid wasted space from
the extra alignment on atomic types.

The fact that it's difficult to allocate over-aligned types does cause problems.

> Honestly, I don't think future-proofing against arbitrary new atomic instructions really makes any sense.  Even going up to 16 bytes (on architectures where that can't be done lock-free now) worries me a bit.

I wouldn't really mind having the compiler produce an error for types
it can't make lock-free. Then users can't use atomics of a size that
would need an external library. If we do allow users to use larger
atomics, then I don't think it's a good idea to guarantee the need for
an ABI change when processors increase the maximum atomic size.

On Wed, Oct 12, 2011 at 1:08 PM, Andrew MacLeod <amacleod at redhat.com> wrote:
>  for  objects where it
> matters, we can probably detect alignment after the fact by looking at the
> pointer value... you should be able to tell if a 32 byte object pointer is
> pointing to a 32 byte boundry or not.

Yep, for some reason I forgot about that possibility. I think it'll
even work in cases where the compiler has the same pointer in some
contexts where it knows the alignment, and other contexts where it

On Wed, Oct 12, 2011 at 2:04 PM, John McCall <rjmccall at apple.com> wrote:
> On Oct 12, 2011, at 1:08 PM, Andrew MacLeod wrote:
>> If the padding is under control of the 'atomic' keyword for the type, then we have complete control over those padding bytes. Regardless of what junk might be in them, they are part of the atomic data structure and the only way to access them is through a full atomic access. Its like adding another user field to the structure and not setting it. It shouldn't cause spurious failures.
> Well, we at least have to make sure that our atomic operations always zero-pad their operands.  For example, if we do an atomic store into a 5-byte struct that we've padded to 8 bytes, we have to make sure we store a zero pattern into the pad.  That's feasible, but it's complexity that we should at least acknowledge before committing to it.
> I can also see this exposing lots of what are, admittedly, source bugs, like only zero'ing the first sizeof(T) bytes of an _Atomic(T).

You're thinking of code that tries to initialize an _Atomic(T) with
memset(0, &at, sizeof(T))? I think code's only supposed to initialize
_Atomic types with ATOMIC_VAR_INIT(value) or atomic_init(&at, value),
so the source bug should be in the memset()'s pointer argument in
addition to its size.

More information about the cfe-commits mailing list