aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2024-07-30 21:52:46 +1200
committerThomas Munro <tmunro@postgresql.org>2024-07-30 22:58:57 +1200
commit81385261362962deb9861b39b509aeffe213721d (patch)
treecf15fa763cea6ccbc200c5e60759a3688dfba118 /src
parente25626677f8076eb3ce94586136c5464ee154381 (diff)
downloadpostgresql-81385261362962deb9861b39b509aeffe213721d.tar.gz
postgresql-81385261362962deb9861b39b509aeffe213721d.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/port/atomics.c109
-rw-r--r--src/include/pg_config.h.in3
-rw-r--r--src/include/port/atomics.h18
-rw-r--r--src/include/port/atomics/arch-x86.h8
-rw-r--r--src/include/port/atomics/fallback.h87
-rw-r--r--src/include/port/atomics/generic-gcc.h4
-rw-r--r--src/include/port/atomics/generic-msvc.h4
-rw-r--r--src/include/port/atomics/generic-sunpro.h8
8 files changed, 11 insertions, 230 deletions
diff --git a/src/backend/port/atomics.c b/src/backend/port/atomics.c
index cd7ede96726..6f1e014d0b8 100644
--- a/src/backend/port/atomics.c
+++ b/src/backend/port/atomics.c
@@ -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
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index e6c06f61027..0e9b108e667 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -57,9 +57,6 @@
/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
#undef HAVE_ASN1_STRING_GET0_DATA
-/* Define to 1 if you want to use atomics if available. */
-#undef HAVE_ATOMICS
-
/* Define to 1 if you have the <atomic.h> header file. */
#undef HAVE_ATOMIC_H
diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h
index 03134e3b7bb..c2ce10a718f 100644
--- a/src/include/port/atomics.h
+++ b/src/include/port/atomics.h
@@ -17,7 +17,7 @@
* There exist generic, hardware independent, implementations for several
* compilers which might be sufficient, although possibly not optimal, for a
* new platform. If no such generic implementation is available spinlocks will
- * be used to implement the API.
+ * be used to implement the 64-bit parts of the API.
*
* Implement _u64 atomics if and only if your platform can use them
* efficiently (and obviously correctly).
@@ -91,17 +91,17 @@
#elif defined(__SUNPRO_C) && !defined(__GNUC__)
#include "port/atomics/generic-sunpro.h"
#else
-/*
- * Unsupported compiler, we'll likely use slower fallbacks... At least
- * compiler barriers should really be provided.
- */
+/* Unknown compiler. */
+#endif
+
+/* Fail if we couldn't find implementations of required facilities. */
+#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT)
+#error "could not find an implementation of pg_atomic_uint32"
#endif
/*
- * Provide a full fallback of the pg_*_barrier(), pg_atomic**_flag and
- * pg_atomic_* APIs for platforms without sufficient spinlock and/or atomics
- * support. In the case of spinlock backed atomics the emulation is expected
- * to be efficient, although less so than native atomics support.
+ * Provide a spinlock-based implementation of the 64 bit variants, if
+ * necessary.
*/
#include "port/atomics/fallback.h"
diff --git a/src/include/port/atomics/arch-x86.h b/src/include/port/atomics/arch-x86.h
index 2a8eca30fcf..c12f8a60697 100644
--- a/src/include/port/atomics/arch-x86.h
+++ b/src/include/port/atomics/arch-x86.h
@@ -49,8 +49,6 @@
* nice to support older gcc's and the compare/exchange implementation here is
* actually more efficient than the * __sync variant.
*/
-#if defined(HAVE_ATOMICS)
-
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#define PG_HAVE_ATOMIC_FLAG_SUPPORT
@@ -80,8 +78,6 @@ typedef struct pg_atomic_uint64
#endif /* defined(__GNUC__) || defined(__INTEL_COMPILER) */
-#endif /* defined(HAVE_ATOMICS) */
-
#if !defined(PG_HAVE_SPIN_DELAY)
/*
* This sequence is equivalent to the PAUSE instruction ("rep" is
@@ -132,8 +128,6 @@ pg_spin_delay_impl(void)
#endif /* !defined(PG_HAVE_SPIN_DELAY) */
-#if defined(HAVE_ATOMICS)
-
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
#define PG_HAVE_ATOMIC_TEST_SET_FLAG
@@ -250,5 +244,3 @@ pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) /* gcc, sunpro, msvc */
#define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
#endif /* 8 byte single-copy atomicity */
-
-#endif /* HAVE_ATOMICS */
diff --git a/src/include/port/atomics/fallback.h b/src/include/port/atomics/fallback.h
index 2e3eef4acaf..8ffd1a8fd32 100644
--- a/src/include/port/atomics/fallback.h
+++ b/src/include/port/atomics/fallback.h
@@ -1,7 +1,7 @@
/*-------------------------------------------------------------------------
*
* fallback.h
- * Fallback for platforms without spinlock and/or atomics support. Slower
+ * Fallback for platforms without 64 bit atomics support. Slower
* than native atomics support, but not unusably slow.
*
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
@@ -49,50 +49,6 @@ extern void pg_extern_compiler_barrier(void);
#endif
-/*
- * If we have atomics implementation for this platform, fall back to providing
- * the atomics API using a spinlock to protect the internal state. Possibly
- * the spinlock implementation uses semaphores internally...
- *
- * We have to be a bit careful here, as it's not guaranteed that atomic
- * variables are mapped to the same address in every process (e.g. dynamic
- * shared memory segments). We can't just hash the address and use that to map
- * to a spinlock. Instead assign a spinlock on initialization of the atomic
- * variable.
- */
-#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) && !defined(PG_HAVE_ATOMIC_U32_SUPPORT)
-
-#define PG_HAVE_ATOMIC_FLAG_SIMULATION
-#define PG_HAVE_ATOMIC_FLAG_SUPPORT
-
-typedef struct pg_atomic_flag
-{
- /*
- * To avoid circular includes we can't use s_lock as a type here. Instead
- * just reserve enough space for all spinlock types. Some platforms would
- * be content with just one byte instead of 4, but that's not too much
- * waste.
- */
- int sema;
- volatile bool value;
-} pg_atomic_flag;
-
-#endif /* PG_HAVE_ATOMIC_FLAG_SUPPORT */
-
-#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT)
-
-#define PG_HAVE_ATOMIC_U32_SIMULATION
-
-#define PG_HAVE_ATOMIC_U32_SUPPORT
-typedef struct pg_atomic_uint32
-{
- /* Check pg_atomic_flag's definition above for an explanation */
- int sema;
- volatile uint32 value;
-} pg_atomic_uint32;
-
-#endif /* PG_HAVE_ATOMIC_U32_SUPPORT */
-
#if !defined(PG_HAVE_ATOMIC_U64_SUPPORT)
#define PG_HAVE_ATOMIC_U64_SIMULATION
@@ -100,49 +56,10 @@ typedef struct pg_atomic_uint32
#define PG_HAVE_ATOMIC_U64_SUPPORT
typedef struct pg_atomic_uint64
{
- /* Check pg_atomic_flag's definition above for an explanation */
int sema;
volatile uint64 value;
} pg_atomic_uint64;
-#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
-
-#ifdef PG_HAVE_ATOMIC_FLAG_SIMULATION
-
-#define PG_HAVE_ATOMIC_INIT_FLAG
-extern void pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr);
-
-#define PG_HAVE_ATOMIC_TEST_SET_FLAG
-extern bool pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr);
-
-#define PG_HAVE_ATOMIC_CLEAR_FLAG
-extern void pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr);
-
-#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
-extern bool pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr);
-
-#endif /* PG_HAVE_ATOMIC_FLAG_SIMULATION */
-
-#ifdef PG_HAVE_ATOMIC_U32_SIMULATION
-
-#define PG_HAVE_ATOMIC_INIT_U32
-extern void pg_atomic_init_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val_);
-
-#define PG_HAVE_ATOMIC_WRITE_U32
-extern void pg_atomic_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val);
-
-#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
-extern bool pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
- uint32 *expected, uint32 newval);
-
-#define PG_HAVE_ATOMIC_FETCH_ADD_U32
-extern uint32 pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_);
-
-#endif /* PG_HAVE_ATOMIC_U32_SIMULATION */
-
-
-#ifdef PG_HAVE_ATOMIC_U64_SIMULATION
-
#define PG_HAVE_ATOMIC_INIT_U64
extern void pg_atomic_init_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val_);
@@ -153,4 +70,4 @@ extern bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr,
#define PG_HAVE_ATOMIC_FETCH_ADD_U64
extern uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_);
-#endif /* PG_HAVE_ATOMIC_U64_SIMULATION */
+#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
diff --git a/src/include/port/atomics/generic-gcc.h b/src/include/port/atomics/generic-gcc.h
index 872d2f02af4..cfbcbe0fff7 100644
--- a/src/include/port/atomics/generic-gcc.h
+++ b/src/include/port/atomics/generic-gcc.h
@@ -53,8 +53,6 @@
#endif
-#ifdef HAVE_ATOMICS
-
/* generic gcc based atomic flag implementation */
#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) \
&& (defined(HAVE_GCC__SYNC_INT32_TAS) || defined(HAVE_GCC__SYNC_CHAR_TAS))
@@ -319,5 +317,3 @@ pg_atomic_fetch_or_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 or_)
#endif
#endif /* !defined(PG_DISABLE_64_BIT_ATOMICS) */
-
-#endif /* defined(HAVE_ATOMICS) */
diff --git a/src/include/port/atomics/generic-msvc.h b/src/include/port/atomics/generic-msvc.h
index c013aca5e7c..677436f2601 100644
--- a/src/include/port/atomics/generic-msvc.h
+++ b/src/include/port/atomics/generic-msvc.h
@@ -30,8 +30,6 @@
#define pg_memory_barrier_impl() MemoryBarrier()
#endif
-#if defined(HAVE_ATOMICS)
-
#define PG_HAVE_ATOMIC_U32_SUPPORT
typedef struct pg_atomic_uint32
{
@@ -115,5 +113,3 @@ pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
}
#endif /* _WIN64 */
-
-#endif /* HAVE_ATOMICS */
diff --git a/src/include/port/atomics/generic-sunpro.h b/src/include/port/atomics/generic-sunpro.h
index 840a45e7788..08f093ed2c1 100644
--- a/src/include/port/atomics/generic-sunpro.h
+++ b/src/include/port/atomics/generic-sunpro.h
@@ -17,8 +17,6 @@
* -------------------------------------------------------------------------
*/
-#if defined(HAVE_ATOMICS)
-
#ifdef HAVE_MBARRIER_H
#include <mbarrier.h>
@@ -66,10 +64,6 @@ typedef struct pg_atomic_uint64
#endif /* HAVE_ATOMIC_H */
-#endif /* defined(HAVE_ATOMICS) */
-
-
-#if defined(HAVE_ATOMICS)
#ifdef HAVE_ATOMIC_H
@@ -117,5 +111,3 @@ pg_atomic_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 newval)
}
#endif /* HAVE_ATOMIC_H */
-
-#endif /* defined(HAVE_ATOMICS) */