@@ -46,12 +46,22 @@ static inline bool
4646pg_atomic_compare_exchange_u32_impl (volatile pg_atomic_uint32 * ptr ,
4747uint32 * 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,
6979static inline uint32
7080pg_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+ */
7286return __fetch_and_add ((volatile int * )& ptr -> value ,add_ );
7387}
7488
@@ -79,8 +93,12 @@ static inline bool
7993pg_atomic_compare_exchange_u64_impl (volatile pg_atomic_uint64 * ptr ,
8094uint64 * 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