Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 213c7df

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 3019f43 commit 213c7df

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

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

+22-4
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,22 @@ static inline bool
4040
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
4141
uint32 *expected, uint32 newval)
4242
{
43+
bool ret;
44+
45+
/*
46+
* atomics.h specifies sequential consistency ("full barrier semantics")
47+
* for this interface. Since "lwsync" provides acquire/release
48+
* consistency only, do not use it here. GCC atomics observe the same
49+
* restriction; see its rs6000_pre_atomic_barrier().
50+
*/
51+
__asm__ __volatile__ (" sync \n" ::: "memory");
52+
4353
/*
4454
* XXX: __compare_and_swap is defined to take signed parameters, but that
4555
* shouldn't matter since we don't perform any arithmetic operations.
4656
*/
47-
bool ret = __compare_and_swap((volatile int*)&ptr->value,
48-
(int *)expected, (int)newval);
57+
ret = __compare_and_swap((volatile int*)&ptr->value,
58+
(int *)expected, (int)newval);
4959

5060
/*
5161
* xlc's documentation tells us:
@@ -63,6 +73,10 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
6373
static inline uint32
6474
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
6575
{
76+
/*
77+
* __fetch_and_add() emits a leading "sync" and trailing "isync", thereby
78+
* providing sequential consistency. This is undocumented.
79+
*/
6680
return __fetch_and_add((volatile int *)&ptr->value, add_);
6781
}
6882

@@ -73,8 +87,12 @@ static inline bool
7387
pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
7488
uint64 *expected, uint64 newval)
7589
{
76-
bool ret = __compare_and_swaplp((volatile long*)&ptr->value,
77-
(long *)expected, (long)newval);
90+
bool ret;
91+
92+
__asm__ __volatile__ (" sync \n" ::: "memory");
93+
94+
ret = __compare_and_swaplp((volatile long*)&ptr->value,
95+
(long *)expected, (long)newval);
7896

7997
__isync();
8098

0 commit comments

Comments
 (0)