@@ -46,12 +46,22 @@ static inline bool
46
46
pg_atomic_compare_exchange_u32_impl (volatile pg_atomic_uint32 * ptr ,
47
47
uint32 * expected ,uint32 newval )
48
48
{
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
+
49
59
/*
50
60
* XXX: __compare_and_swap is defined to take signed parameters, but that
51
61
* shouldn't matter since we don't perform any arithmetic operations.
52
62
*/
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 );
55
65
56
66
/*
57
67
* xlc's documentation tells us:
@@ -69,6 +79,10 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
69
79
static inline uint32
70
80
pg_atomic_fetch_add_u32_impl (volatile pg_atomic_uint32 * ptr ,int32 add_ )
71
81
{
82
+ /*
83
+ * __fetch_and_add() emits a leading "sync" and trailing "isync", thereby
84
+ * providing sequential consistency. This is undocumented.
85
+ */
72
86
return __fetch_and_add ((volatile int * )& ptr -> value ,add_ );
73
87
}
74
88
@@ -79,8 +93,12 @@ static inline bool
79
93
pg_atomic_compare_exchange_u64_impl (volatile pg_atomic_uint64 * ptr ,
80
94
uint64 * expected ,uint64 newval )
81
95
{
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 );
84
102
85
103
__isync ();
86
104