1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-02 04:21:28 +03:00

Remove --disable-atomics, require 32 bit atomics.

Modern versions of all relevant architectures and tool chains have
atomics support.  Since edadeb07, there is no remaining reason to carry
code that simulates atomic flags and uint32 imperfectly with spinlocks.
64 bit atomics are still emulated with spinlocks, if needed, for now.

Any modern compiler capable of implementing C11 <stdatomic.h> must have
the underlying operations we need, though we don't require C11 yet.  We
detect certain compilers and architectures, so hypothetical new systems
might need adjustments here.

Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> (concept, not the patch)
Reviewed-by: Andres Freund <andres@anarazel.de> (concept, not the patch)
Discussion: https://postgr.es/m/3351991.1697728588%40sss.pgh.pa.us
This commit is contained in:
Thomas Munro
2024-07-30 21:52:46 +12:00
parent e25626677f
commit 8138526136
12 changed files with 39 additions and 345 deletions

View File

@@ -49,115 +49,6 @@ pg_extern_compiler_barrier(void)
#endif
#ifdef PG_HAVE_ATOMIC_FLAG_SIMULATION
void
pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
{
StaticAssertDecl(sizeof(ptr->sema) >= sizeof(slock_t),
"size mismatch of atomic_flag vs slock_t");
SpinLockInit((slock_t *) &ptr->sema);
ptr->value = false;
}
bool
pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
{
uint32 oldval;
SpinLockAcquire((slock_t *) &ptr->sema);
oldval = ptr->value;
ptr->value = true;
SpinLockRelease((slock_t *) &ptr->sema);
return oldval == 0;
}
void
pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
{
SpinLockAcquire((slock_t *) &ptr->sema);
ptr->value = false;
SpinLockRelease((slock_t *) &ptr->sema);
}
bool
pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
{
return ptr->value == 0;
}
#endif /* PG_HAVE_ATOMIC_FLAG_SIMULATION */
#ifdef PG_HAVE_ATOMIC_U32_SIMULATION
void
pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_)
{
StaticAssertDecl(sizeof(ptr->sema) >= sizeof(slock_t),
"size mismatch of atomic_uint32 vs slock_t");
SpinLockInit((slock_t *) &ptr->sema);
ptr->value = val_;
}
void
pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
{
/*
* One might think that an unlocked write doesn't need to acquire the
* spinlock, but one would be wrong. Even an unlocked write has to cause a
* concurrent pg_atomic_compare_exchange_u32() (et al) to fail.
*/
SpinLockAcquire((slock_t *) &ptr->sema);
ptr->value = val;
SpinLockRelease((slock_t *) &ptr->sema);
}
bool
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
uint32 *expected, uint32 newval)
{
bool ret;
/*
* Do atomic op under a spinlock. It might look like we could just skip
* the cmpxchg if the lock isn't available, but that'd just emulate a
* 'weak' compare and swap. I.e. one that allows spurious failures. Since
* several algorithms rely on a strong variant and that is efficiently
* implementable on most major architectures let's emulate it here as
* well.
*/
SpinLockAcquire((slock_t *) &ptr->sema);
/* perform compare/exchange logic */
ret = ptr->value == *expected;
*expected = ptr->value;
if (ret)
ptr->value = newval;
/* and release lock */
SpinLockRelease((slock_t *) &ptr->sema);
return ret;
}
uint32
pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
{
uint32 oldval;
SpinLockAcquire((slock_t *) &ptr->sema);
oldval = ptr->value;
ptr->value += add_;
SpinLockRelease((slock_t *) &ptr->sema);
return oldval;
}
#endif /* PG_HAVE_ATOMIC_U32_SIMULATION */
#ifdef PG_HAVE_ATOMIC_U64_SIMULATION
void