1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-21 02:52:47 +03:00

Optimize pg_atomic_exchange_u32 and pg_atomic_exchange_u64.

Presently, all platforms implement atomic exchanges by performing
an atomic compare-and-swap in a loop until it succeeds.  This can
be especially expensive when there is contention on the atomic
variable.  This commit optimizes atomic exchanges on many platforms
by using compiler intrinsics, which should compile into something
much less expensive than a compare-and-swap loop.  Since these
intrinsics have been available for some time, the inline assembly
implementations are omitted.

Suggested-by: Andres Freund
Reviewed-by: Andres Freund
Discussion: https://postgr.es/m/20231129212905.GA1258737%40nathanxps13
This commit is contained in:
Nathan Bossart
2023-12-18 10:53:32 -06:00
parent 0d1adae6f7
commit 64b1fb5f03
3 changed files with 66 additions and 0 deletions

View File

@@ -176,6 +176,23 @@ pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
}
#endif
/*
* __sync_lock_test_and_set() only supports setting the value to 1 on some
* platforms, so we only provide an __atomic implementation for
* pg_atomic_exchange.
*
* We assume the availability of 32-bit __atomic_compare_exchange_n() implies
* the availability of 32-bit __atomic_exchange_n().
*/
#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U32) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
#define PG_HAVE_ATOMIC_EXCHANGE_U32
static inline uint32
pg_atomic_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 newval)
{
return __atomic_exchange_n(&ptr->value, newval, __ATOMIC_SEQ_CST);
}
#endif
/* if we have 32-bit __sync_val_compare_and_swap, assume we have these too: */
#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U32) && defined(HAVE_GCC__SYNC_INT32_CAS)
@@ -243,6 +260,23 @@ pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
}
#endif
/*
* __sync_lock_test_and_set() only supports setting the value to 1 on some
* platforms, so we only provide an __atomic implementation for
* pg_atomic_exchange.
*
* We assume the availability of 64-bit __atomic_compare_exchange_n() implies
* the availability of 64-bit __atomic_exchange_n().
*/
#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U64) && defined(HAVE_GCC__ATOMIC_INT64_CAS)
#define PG_HAVE_ATOMIC_EXCHANGE_U64
static inline uint64
pg_atomic_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 newval)
{
return __atomic_exchange_n(&ptr->value, newval, __ATOMIC_SEQ_CST);
}
#endif
/* if we have 64-bit __sync_val_compare_and_swap, assume we have these too: */
#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_U64) && defined(HAVE_GCC__SYNC_INT64_CAS)