Skip to content

Commit f998948

Browse files
committed
Impose a full barrier in generic-xlc.h atomics functions.
pg_atomic_compare_exchange_*_impl() were providing only the semantics of an acquire barrier. Buildfarm members hornet and mandrill revealed this deficit beginning with commit 008608b. While we have no report of symptoms in 9.5, we can't rule out the possibility of certain compilers, hardware, or extension code relying on these functions' specified barrier semantics. Back-patch to 9.5, where commit b64d92f introduced atomics. Reviewed by Andres Freund.
1 parent 46e006d commit f998948

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

src/include/port/atomics/generic-xlc.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,22 @@ static inline bool
4646
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
4747
uint32 *expected, uint32 newval)
4848
{
49+
bool ret;
50+
51+
/*
52+
* atomics.h specifies sequential consistency ("full barrier semantics")
53+
* for this interface. Since "lwsync" provides acquire/release
54+
* consistency only, do not use it here. GCC atomics observe the same
55+
* restriction; see its rs6000_pre_atomic_barrier().
56+
*/
57+
__asm__ __volatile__ (" sync \n" ::: "memory");
58+
4959
/*
5060
* XXX: __compare_and_swap is defined to take signed parameters, but that
5161
* shouldn't matter since we don't perform any arithmetic operations.
5262
*/
53-
bool ret = __compare_and_swap((volatile int*)&ptr->value,
54-
(int *)expected, (int)newval);
63+
ret = __compare_and_swap((volatile int*)&ptr->value,
64+
(int *)expected, (int)newval);
5565

5666
/*
5767
* xlc's documentation tells us:
@@ -69,6 +79,10 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
6979
static inline uint32
7080
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
7181
{
82+
/*
83+
* __fetch_and_add() emits a leading "sync" and trailing "isync", thereby
84+
* providing sequential consistency. This is undocumented.
85+
*/
7286
return __fetch_and_add((volatile int *)&ptr->value, add_);
7387
}
7488

@@ -79,8 +93,12 @@ static inline bool
7993
pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
8094
uint64 *expected, uint64 newval)
8195
{
82-
bool ret = __compare_and_swaplp((volatile long*)&ptr->value,
83-
(long *)expected, (long)newval);
96+
bool ret;
97+
98+
__asm__ __volatile__ (" sync \n" ::: "memory");
99+
100+
ret = __compare_and_swaplp((volatile long*)&ptr->value,
101+
(long *)expected, (long)newval);
84102

85103
__isync();
86104

0 commit comments

Comments
 (0)