mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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/20190831071157.GA3251746@rfd.leadboat.com
This commit is contained in:
parent
8d32f82cbb
commit
a1df9a015d
@ -73,11 +73,27 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
|
|||||||
static inline uint32
|
static inline uint32
|
||||||
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
|
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
|
||||||
{
|
{
|
||||||
|
uint32 _t;
|
||||||
|
uint32 res;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __fetch_and_add() emits a leading "sync" and trailing "isync", thereby
|
* xlc has a no-longer-documented __fetch_and_add() intrinsic. In xlc
|
||||||
* providing sequential consistency. This is undocumented.
|
* 12.01.0000.0000, it emits a leading "sync" and trailing "isync". In
|
||||||
|
* xlc 13.01.0003.0004, it emits neither. Hence, using the intrinsic
|
||||||
|
* would add redundant syncs on xlc 12.
|
||||||
*/
|
*/
|
||||||
return __fetch_and_add((volatile int *)&ptr->value, add_);
|
__asm__ __volatile__(
|
||||||
|
" sync \n"
|
||||||
|
" lwarx %1,0,%4 \n"
|
||||||
|
" add %0,%1,%3 \n"
|
||||||
|
" stwcx. %0,0,%4 \n"
|
||||||
|
" bne $-12 \n" /* branch to lwarx */
|
||||||
|
" isync \n"
|
||||||
|
: "=&r"(_t), "=&r"(res), "+m"(ptr->value)
|
||||||
|
: "r"(add_), "r"(&ptr->value)
|
||||||
|
: "memory", "cc");
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
|
#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
|
||||||
@ -103,7 +119,22 @@ pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
|
|||||||
static inline uint64
|
static inline uint64
|
||||||
pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
|
pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
|
||||||
{
|
{
|
||||||
return __fetch_and_addlp((volatile long *)&ptr->value, add_);
|
uint64 _t;
|
||||||
|
uint64 res;
|
||||||
|
|
||||||
|
/* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/ */
|
||||||
|
__asm__ __volatile__(
|
||||||
|
" sync \n"
|
||||||
|
" ldarx %1,0,%4 \n"
|
||||||
|
" add %0,%1,%3 \n"
|
||||||
|
" stdcx. %0,0,%4 \n"
|
||||||
|
" bne $-12 \n" /* branch to ldarx */
|
||||||
|
" isync \n"
|
||||||
|
: "=&r"(_t), "=&r"(res), "+m"(ptr->value)
|
||||||
|
: "r"(add_), "r"(&ptr->value)
|
||||||
|
: "memory", "cc");
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
|
#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user