0
votes

gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0

How to align void * referencing entity with no declared type to a cache line size in a conforming way?

I'm interested to explain the legitimacy of the common alignment technique with Standard.

My attempt

void *ptr = //some valid pointer;
void *aligned_ptr = (void *) ((intptr_t) ptr & -64);

The (intptr_t) ptr & -64 part is conforming since any 7.20.1.4 N2310:

an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void , and the result will compare equal to the original pointer

Converting (intptr_t) ptr & -64 back to void * is not specified to have well-defined behavior. 6.3.2.3/5 provides some blurred information (emp. mine):

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

If I correctly understand the concept of the "trap representation" then it is not possible to have it in such case since there is not declared type of the object.

I'm not sure if (void *) ((intptr_t) ptr & -64) is correctly aligned from the Standard standpoint or the result is not an implementation defined.

UPD: 6.2.8 Describes

Every valid alignment value shall be a nonnegative integral power of two.

Since _Alignof (max_align_t) is 16 on my implementation then I suppose the 64 byte alignment is not obligated to be supported by gcc.

1
As the standard says, except from conversion from pointer to integer and back the behavior is implementation-defined. Since you're using GCC: When casting from pointer to integer and back again, the resulting pointer must reference the same object as the original pointer, otherwise the behavior is undefined. So, unless your pointer has already been aligned to a cache line, the behavior of your code is undefined.Language Lawyer
"except from conversion from pointer to integer and back the behavior is implementation-defined" Oops. Confused with the C++ standard. In C standard, even conversions to integers and back are implementation-defined, unless the pointer value is null or integer is zero.Language Lawyer
What you are trying to do in your snippet is unclear. What do you want to achieve by "adjusting" a pointer like that? If it does not point to a valid object, then it's pointless. This seems like an XY problem. The correct way to align something to a cache line is to just declare it padded to the needed size using __attribute__((aligned(64)) or similar compiler directives. Needless to say, this cannot be made in a generic non compiler-specific way. There is no standard-defined way to "conformingly align" something to cache.Marco Bonelli
Re “If I correctly understand the concept of the "trap representation" then it is not possible to have it in such case since there is not declared type of the object.” the result of the conversion to void * may be a trap representation of the void * type.Eric Postpischil
@SomeName just because it's C11, I wouldn't opt into C11 just for such an insignificant feature. I also was assuming you were talking about C99, since it's the most common version of the standard to refer to.Marco Bonelli

1 Answers

1
votes

If you really want a generic solution, maybe use union and optionally some preprocessor macros.

union myptr{
    void *ptr;
    (whatever-type-that-meets-your-padding-requirment) padding;
};

union myptr myalignedptr;
#define alignedptr (myalignedptr.ptr)       /* optional */