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/20190831071157.GA3251746@rfd.leadboat.com
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

Lines changed: 35 additions & 4 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy