Re: Problem with pg_atomic_compare_exchange_u64 at 32-bit platforms - Mailing list pgsql-hackers

From Konstantin Knizhnik
Subject Re: Problem with pg_atomic_compare_exchange_u64 at 32-bit platforms
Date
Msg-id ac9f2435-2b0e-6136-c2ca-32cf3c28b20e@postgrespro.ru
Whole thread Raw
In response to Re: Problem with pg_atomic_compare_exchange_u64 at 32-bit platformwd  (Noah Misch <noah@leadboat.com>)
Responses Re: Problem with pg_atomic_compare_exchange_u64 at 32-bit platforms  (Noah Misch <noah@leadboat.com>)
List pgsql-hackers

On 20.05.2020 06:05, Noah Misch wrote:
> On Tue, May 19, 2020 at 04:07:29PM +0300, Konstantin Knizhnik wrote:
>> Definition of pg_atomic_compare_exchange_u64 requires alignment of expected
>> pointer on 8-byte boundary.
>>
>> pg_atomic_compare_exchange_u64(volatile pg_atomic_uint64 *ptr,
>>                                 uint64 *expected, uint64 newval)
>> {
>> #ifndef PG_HAVE_ATOMIC_U64_SIMULATION
>>      AssertPointerAlignment(ptr, 8);
>>      AssertPointerAlignment(expected, 8);
>> #endif
>>
>>
>> I wonder if there are platforms  where such restriction is actually needed.
> In general, sparc Linux does SIGBUS on unaligned access.  Other platforms
> function but suffer performance penalties.
Well, if platform enforces strict alignment, then addressed value should 
be properly aligned in any case, shouldn't it?
So my question is whether there are platforms which allows unaligned 
access for normal (non-atomic) memory operations
but requires them for atomic operations.

>
>> And if so, looks like our ./src/test/regress/regress.c is working only
>> occasionally:
>>
>> static void
>> test_atomic_uint64(void)
>> {
>>      pg_atomic_uint64 var;
>>      uint64        expected;
>>      ...
>>          if (!pg_atomic_compare_exchange_u64(&var, &expected, 1))
>>
>> because there is no warranty that "expected" variable will be aligned on
>> stack at 8 byte boundary (at least at Win32).
> src/tools/msvc sets ALIGNOF_LONG_LONG_INT=8, so it believes that win32 does
> guarantee 8-byte alignment of both automatic variables.  Is it wrong?

Yes, by default "long long" and "double" types are aligned on 8-byte 
boundary at 32-bit Windows (but not at 32-bit Linux).
Bu it is only about alignment of fields inside struct.
So if you define structure:

typedef struct {
      int x;
      long long y;
} foo;

then sizeof(foo) will be really 16 at Win32.'
But Win32 doesn't enforce alignment of stack frames on 8-byte boundary.
It means that if you define local variable "y":

void f() {
      int x;
      long long y;
      printf("%p\n", &y);
}

then its address must not be aligned on 8 at 32-bit platform.
This is why "expected" in test_atomic_uint64 may not be aligned on 
8-byte boundary and we can get assertion failure.




pgsql-hackers by date:

Previous
From: Michael Paquier
Date:
Subject: Re: Expand the use of check_canonical_path() for more GUCs
Next
From: Konstantin Knizhnik
Date:
Subject: Re: Problem with pg_atomic_compare_exchange_u64 at 32-bit platforms