Skip to content

Commit dd50f1a

Browse files
committed
Replace xlc __fetch_and_add() with inline asm.
PostgreSQL has been unusable when built with xlc 13 and newer, which are incompatible with our use of __fetch_and_add(). Back-patch to 9.5, which introduced pg_atomic_fetch_add_u32(). Reviewed by Tom Lane. Discussion: https://postgr.es/m/[email protected]
1 parent f380c51 commit dd50f1a

File tree

1 file changed

+35
-4
lines changed

1 file changed

+35
-4
lines changed

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

+35-4
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,27 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
7373
static inline uint32
7474
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
7575
{
76+
uint32 _t;
77+
uint32 res;
78+
7679
/*
77-
* __fetch_and_add() emits a leading "sync" and trailing "isync", thereby
78-
* providing sequential consistency. This is undocumented.
80+
* xlc has a no-longer-documented __fetch_and_add() intrinsic. In xlc
81+
* 12.01.0000.0000, it emits a leading "sync" and trailing "isync". In
82+
* xlc 13.01.0003.0004, it emits neither. Hence, using the intrinsic
83+
* would add redundant syncs on xlc 12.
7984
*/
80-
return __fetch_and_add((volatile int *)&ptr->value, add_);
85+
__asm__ __volatile__(
86+
" sync \n"
87+
" lwarx %1,0,%4 \n"
88+
" add %0,%1,%3 \n"
89+
" stwcx. %0,0,%4 \n"
90+
" bne $-12 \n" /* branch to lwarx */
91+
" isync \n"
92+
: "=&r"(_t), "=&r"(res), "+m"(ptr->value)
93+
: "r"(add_), "r"(&ptr->value)
94+
: "memory", "cc");
95+
96+
return res;
8197
}
8298

8399
#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
@@ -103,7 +119,22 @@ pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
103119
static inline uint64
104120
pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
105121
{
106-
return __fetch_and_addlp((volatile long *)&ptr->value, add_);
122+
uint64 _t;
123+
uint64 res;
124+
125+
/* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/ */
126+
__asm__ __volatile__(
127+
" sync \n"
128+
" ldarx %1,0,%4 \n"
129+
" add %0,%1,%3 \n"
130+
" stdcx. %0,0,%4 \n"
131+
" bne $-12 \n" /* branch to ldarx */
132+
" isync \n"
133+
: "=&r"(_t), "=&r"(res), "+m"(ptr->value)
134+
: "r"(add_), "r"(&ptr->value)
135+
: "memory", "cc");
136+
137+
return res;
107138
}
108139

109140
#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */

0 commit comments

Comments
 (0)