0001-Replace-pg_atomic_flag-with-pg_atomic_bool.patch
text/x-patch
Filename: 0001-Replace-pg_atomic_flag-with-pg_atomic_bool.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Replace pg_atomic_flag with pg_atomic_bool
| File | + | − |
|---|---|---|
| contrib/pg_stash_advice/pg_stash_advice.c | 4 | 4 |
| contrib/pg_stash_advice/pg_stash_advice.h | 1 | 1 |
| contrib/pg_stash_advice/stashfuncs.c | 2 | 2 |
| contrib/pg_stash_advice/stashpersist.c | 2 | 2 |
| src/backend/postmaster/autovacuum.c | 9 | 15 |
| src/include/port/atomics/arch-x86.h | 0 | 33 |
| src/include/port/atomics/generic-gcc.h | 0 | 67 |
| src/include/port/atomics/generic.h | 66 | 84 |
| src/include/port/atomics.h | 58 | 50 |
| src/test/regress/regress.c | 21 | 13 |
| src/tools/pgindent/typedefs.list | 1 | 1 |
From ba3395f8a09a3ae3919f3f811296b05b2cddd17c Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 6 Jul 2026 01:10:45 +0300
Subject: [PATCH 1/1] Replace pg_atomic_flag with pg_atomic_bool
The pg_atomic_flag operations were different from those that we
support with pg_atomic_u32/u64. I've learned the u32/u64 functions by
now, but whenever I deal with pg_atomic_flag, I need to read the docs
to remind myself what the pg_atomic_flag functions do. However, what I
really just want is to have a "bool" with an atomic-exchange
operation. The pg_atomic_flag operations were slightly different and
unintuitive to me at least:
- pg_atomic_unlocked_test_flag() returned false, if the flag was set
and true if it was not set. That felt backwards if you thought of it
as just reading the underlying boolean value.
- Similarly, pg_atomic_test_set_flag() returned true if it was not
previously set, which was different from what pg_atomic_exchange()
returns. (None of the callers of pg_atomic_test_set_flag() actually
looked at the return value, however. They all just wanted to set the
flag, but there was no pg_atomic_set_flag() function!)
- There was no atomic "test and clear" operation
- There were differences in the barrier semantics compared to the
pg_atomic_u32 variants. We don't expose "acquire" or "release"
semantics anywhere else (outside arch-specific headers), we use the
terms "read" and "write" barriers instead, and it wasn't quite clear
if they're the same thing.
Replace the pg_atomic_flag type and functions with pg_atomic_bool,
which has functions with same names and semantics as pg_atomic_u32.
Remove the x86-specific implementation, and rely on the fallback that
defines pg_atomic_bool as a wrapper around pg_atomic_u32 on all
platforms.
---
contrib/pg_stash_advice/pg_stash_advice.c | 8 +-
contrib/pg_stash_advice/pg_stash_advice.h | 2 +-
contrib/pg_stash_advice/stashfuncs.c | 4 +-
contrib/pg_stash_advice/stashpersist.c | 4 +-
src/backend/postmaster/autovacuum.c | 24 ++--
src/include/port/atomics.h | 108 ++++++++--------
src/include/port/atomics/arch-x86.h | 33 -----
src/include/port/atomics/generic-gcc.h | 67 ----------
src/include/port/atomics/generic.h | 150 ++++++++++------------
src/test/regress/regress.c | 34 +++--
src/tools/pgindent/typedefs.list | 2 +-
11 files changed, 164 insertions(+), 272 deletions(-)
diff --git a/contrib/pg_stash_advice/pg_stash_advice.c b/contrib/pg_stash_advice/pg_stash_advice.c
index 1858c6a135a..6dbb3f57b6b 100644
--- a/contrib/pg_stash_advice/pg_stash_advice.c
+++ b/contrib/pg_stash_advice/pg_stash_advice.c
@@ -167,7 +167,7 @@ pgsa_advisor(PlannerGlobal *glob, Query *parse,
pgsa_attach();
/* If stash data is still being restored from disk, ignore. */
- if (pg_atomic_unlocked_test_flag(&pgsa_state->stashes_ready))
+ if (!pg_atomic_read_bool(&pgsa_state->stashes_ready))
return NULL;
/*
@@ -324,7 +324,7 @@ pgsa_attach(void)
void
pgsa_check_lockout(void)
{
- if (pg_atomic_unlocked_test_flag(&pgsa_state->stashes_ready))
+ if (!pg_atomic_read_bool(&pgsa_state->stashes_ready))
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("stash modifications are not allowed because \"%s\" has not been loaded yet",
@@ -579,7 +579,7 @@ pgsa_init_shared_state(void *ptr, void *arg)
state->stash_hash = DSHASH_HANDLE_INVALID;
state->entry_hash = DSHASH_HANDLE_INVALID;
state->bgworker_pid = InvalidPid;
- pg_atomic_init_flag(&state->stashes_ready);
+ pg_atomic_init_bool(&state->stashes_ready, false);
pg_atomic_init_u64(&state->change_count, 0);
/*
@@ -594,7 +594,7 @@ pgsa_init_shared_state(void *ptr, void *arg)
* which leads to the correct behavior.
*/
if (!pg_stash_advice_persist)
- pg_atomic_test_set_flag(&state->stashes_ready);
+ pg_atomic_write_bool(&state->stashes_ready, true);
}
/*
diff --git a/contrib/pg_stash_advice/pg_stash_advice.h b/contrib/pg_stash_advice/pg_stash_advice.h
index 01aded472f3..e15e09582f8 100644
--- a/contrib/pg_stash_advice/pg_stash_advice.h
+++ b/contrib/pg_stash_advice/pg_stash_advice.h
@@ -65,7 +65,7 @@ typedef struct pgsa_shared_state
dshash_table_handle stash_hash;
dshash_table_handle entry_hash;
pid_t bgworker_pid;
- pg_atomic_flag stashes_ready;
+ pg_atomic_bool stashes_ready;
pg_atomic_uint64 change_count;
} pgsa_shared_state;
diff --git a/contrib/pg_stash_advice/stashfuncs.c b/contrib/pg_stash_advice/stashfuncs.c
index a70df60579b..2af369e4bc8 100644
--- a/contrib/pg_stash_advice/stashfuncs.c
+++ b/contrib/pg_stash_advice/stashfuncs.c
@@ -99,7 +99,7 @@ pg_get_advice_stashes(PG_FUNCTION_ARGS)
pgsa_attach();
/* If stash data is still being restored from disk, ignore. */
- if (pg_atomic_unlocked_test_flag(&pgsa_state->stashes_ready))
+ if (!pg_atomic_read_bool(&pgsa_state->stashes_ready))
return (Datum) 0;
/* Tally up the number of entries per stash. */
@@ -163,7 +163,7 @@ pg_get_advice_stash_contents(PG_FUNCTION_ARGS)
pgsa_attach();
/* If stash data is still being restored from disk, ignore. */
- if (pg_atomic_unlocked_test_flag(&pgsa_state->stashes_ready))
+ if (!pg_atomic_read_bool(&pgsa_state->stashes_ready))
return (Datum) 0;
/* User can pass NULL for all stashes, or the name of a specific stash. */
diff --git a/contrib/pg_stash_advice/stashpersist.c b/contrib/pg_stash_advice/stashpersist.c
index 5bdf4bddaae..c9d7887cb75 100644
--- a/contrib/pg_stash_advice/stashpersist.c
+++ b/contrib/pg_stash_advice/stashpersist.c
@@ -141,10 +141,10 @@ pg_stash_advice_worker_main(Datum main_arg)
* process_shared_preload_libraries() and the data has not yet been
* successfully loaded, load it now.
*/
- if (pg_atomic_unlocked_test_flag(&pgsa_state->stashes_ready))
+ if (!pg_atomic_read_bool(&pgsa_state->stashes_ready))
{
pgsa_read_from_disk();
- pg_atomic_test_set_flag(&pgsa_state->stashes_ready);
+ pg_atomic_write_bool(&pgsa_state->stashes_ready, true);
}
/* Note the current change count so we can detect future changes. */
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 127bd9e7da3..287936efbf8 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -244,7 +244,7 @@ typedef struct WorkerInfoData
Oid wi_tableoid;
PGPROC *wi_proc;
TimestampTz wi_launchtime;
- pg_atomic_flag wi_dobalance;
+ pg_atomic_bool wi_dobalance;
bool wi_sharedrel;
} WorkerInfoData;
@@ -1657,7 +1657,7 @@ FreeWorkerInfo(int code, Datum arg)
MyWorkerInfo->wi_sharedrel = false;
MyWorkerInfo->wi_proc = NULL;
MyWorkerInfo->wi_launchtime = 0;
- pg_atomic_clear_flag(&MyWorkerInfo->wi_dobalance);
+ pg_atomic_write_bool(&MyWorkerInfo->wi_dobalance, false);
dclist_push_head(&AutoVacuumShmem->av_freeWorkers,
&MyWorkerInfo->wi_links);
/* not mine anymore */
@@ -1732,7 +1732,7 @@ VacuumUpdateCosts(void)
elog(DEBUG2,
"Autovacuum VacuumUpdateCosts(db=%u, rel=%u, dobalance=%s, cost_limit=%d, cost_delay=%g active=%s failsafe=%s)",
- dboid, tableoid, pg_atomic_unlocked_test_flag(&MyWorkerInfo->wi_dobalance) ? "no" : "yes",
+ dboid, tableoid, pg_atomic_read_bool(&MyWorkerInfo->wi_dobalance) ? "yes" : "no",
vacuum_cost_limit, vacuum_cost_delay,
vacuum_cost_delay > 0 ? "yes" : "no",
VacuumFailsafeActive ? "yes" : "no");
@@ -1770,7 +1770,7 @@ AutoVacuumUpdateCostLimit(void)
vacuum_cost_limit = VacuumCostLimit;
/* Only balance limit if no cost-related storage parameters specified */
- if (pg_atomic_unlocked_test_flag(&MyWorkerInfo->wi_dobalance))
+ if (!pg_atomic_read_bool(&MyWorkerInfo->wi_dobalance))
return;
Assert(vacuum_cost_limit > 0);
@@ -1810,7 +1810,7 @@ autovac_recalculate_workers_for_balance(void)
WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur);
if (worker->wi_proc == NULL ||
- pg_atomic_unlocked_test_flag(&worker->wi_dobalance))
+ !pg_atomic_read_bool(&worker->wi_dobalance))
continue;
nworkers_for_balance++;
@@ -2465,14 +2465,8 @@ do_autovacuum(void)
av_storage_param_cost_delay = tab->at_storage_param_vac_cost_delay;
av_storage_param_cost_limit = tab->at_storage_param_vac_cost_limit;
- /*
- * We only expect this worker to ever set the flag, so don't bother
- * checking the return value. We shouldn't have to retry.
- */
- if (tab->at_dobalance)
- pg_atomic_test_set_flag(&MyWorkerInfo->wi_dobalance);
- else
- pg_atomic_clear_flag(&MyWorkerInfo->wi_dobalance);
+ /* We only expect this worker to write the flag */
+ pg_atomic_write_bool(&MyWorkerInfo->wi_dobalance, tab->at_dobalance);
LWLockAcquire(AutovacuumLock, LW_SHARED);
autovac_recalculate_workers_for_balance();
@@ -2578,7 +2572,7 @@ deleted:
MyWorkerInfo->wi_tableoid = InvalidOid;
MyWorkerInfo->wi_sharedrel = false;
LWLockRelease(AutovacuumScheduleLock);
- pg_atomic_test_set_flag(&MyWorkerInfo->wi_dobalance);
+ pg_atomic_write_bool(&MyWorkerInfo->wi_dobalance, true);
}
list_free_deep(tables_to_process);
@@ -3574,7 +3568,7 @@ AutoVacuumShmemInit(void *arg)
{
dclist_push_head(&AutoVacuumShmem->av_freeWorkers,
&worker[i].wi_links);
- pg_atomic_init_flag(&worker[i].wi_dobalance);
+ pg_atomic_init_bool(&worker[i].wi_dobalance, false);
}
pg_atomic_init_u32(&AutoVacuumShmem->av_nworkersForBalance, 0);
diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h
index a605ea81d07..bd75d00a558 100644
--- a/src/include/port/atomics.h
+++ b/src/include/port/atomics.h
@@ -11,7 +11,6 @@
* implementations for the following operations should be provided:
* * pg_compiler_barrier(), pg_write_barrier(), pg_read_barrier()
* * pg_atomic_compare_exchange_u32(), pg_atomic_fetch_add_u32()
- * * pg_atomic_test_set_flag(), pg_atomic_init_flag(), pg_atomic_clear_flag()
* * PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY should be defined if appropriate.
*
* There exist generic, hardware independent, implementations for several
@@ -154,55 +153,6 @@
#define pg_read_barrier() pg_read_barrier_impl()
#define pg_write_barrier() pg_write_barrier_impl()
-/*
- * pg_atomic_init_flag - initialize atomic flag.
- *
- * No barrier semantics.
- */
-static inline void
-pg_atomic_init_flag(volatile pg_atomic_flag *ptr)
-{
- pg_atomic_init_flag_impl(ptr);
-}
-
-/*
- * pg_atomic_test_set_flag - TAS()
- *
- * Returns true if the flag has successfully been set, false otherwise.
- *
- * Acquire (including read barrier) semantics.
- */
-static inline bool
-pg_atomic_test_set_flag(volatile pg_atomic_flag *ptr)
-{
- return pg_atomic_test_set_flag_impl(ptr);
-}
-
-/*
- * pg_atomic_unlocked_test_flag - Check if the lock is free
- *
- * Returns true if the flag currently is not set, false otherwise.
- *
- * No barrier semantics.
- */
-static inline bool
-pg_atomic_unlocked_test_flag(volatile pg_atomic_flag *ptr)
-{
- return pg_atomic_unlocked_test_flag_impl(ptr);
-}
-
-/*
- * pg_atomic_clear_flag - release lock set by TAS()
- *
- * Release (including write barrier) semantics.
- */
-static inline void
-pg_atomic_clear_flag(volatile pg_atomic_flag *ptr)
-{
- pg_atomic_clear_flag_impl(ptr);
-}
-
-
/*
* pg_atomic_init_u32 - initialize atomic variable
*
@@ -611,6 +561,64 @@ pg_atomic_monotonic_advance_u64(volatile pg_atomic_uint64 *ptr, uint64 target)
return currval;
}
+/* ----
+ * The 'bool' operations have the same semantics as the u32 counterparts
+ * if they are available. Check the corresponding u32 function for
+ * documentation.
+ *
+ * Note: pg_atomic_bool is currently identical to pg_atomic_u32 on all
+ * platforms, but it's notationally nice to have a distinct type.
+ * ----
+ */
+
+static inline void
+pg_atomic_init_bool(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_init_bool_impl(ptr, val);
+}
+
+static inline bool
+pg_atomic_read_bool(volatile pg_atomic_bool *ptr)
+{
+ return pg_atomic_read_bool_impl(ptr);
+}
+
+static inline bool
+pg_atomic_read_membarrier_bool(volatile pg_atomic_bool *ptr)
+{
+ return pg_atomic_read_membarrier_bool_impl(ptr);
+}
+
+static inline void
+pg_atomic_write_bool(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_write_bool_impl(ptr, val);
+}
+
+static inline void
+pg_atomic_unlocked_write_bool(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_unlocked_write_bool_impl(ptr, val);
+}
+
+static inline void
+pg_atomic_write_membarrier_bool(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_write_membarrier_bool_impl(ptr, val);
+}
+
+static inline bool
+pg_atomic_exchange_bool(volatile pg_atomic_bool *ptr, bool newval)
+{
+ return pg_atomic_exchange_bool_impl(ptr, newval);
+}
+
+/*
+ * Note: There is no pg_atomic_compare_exchange_bool(). Because a boolean has
+ * only two possible values, it would be no different from
+ * pg_atomic_exchange_bool().
+ */
+
#undef INSIDE_ATOMICS_H
#endif /* ATOMICS_H */
diff --git a/src/include/port/atomics/arch-x86.h b/src/include/port/atomics/arch-x86.h
index 231831dcf59..05d2a2ce7f9 100644
--- a/src/include/port/atomics/arch-x86.h
+++ b/src/include/port/atomics/arch-x86.h
@@ -51,12 +51,6 @@
*/
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
-#define PG_HAVE_ATOMIC_FLAG_SUPPORT
-typedef struct pg_atomic_flag
-{
- volatile char value;
-} pg_atomic_flag;
-
#define PG_HAVE_ATOMIC_U32_SUPPORT
typedef struct pg_atomic_uint32
{
@@ -76,33 +70,6 @@ typedef struct pg_atomic_uint64
} pg_atomic_uint64;
#endif /* __x86_64__ */
-#define PG_HAVE_ATOMIC_TEST_SET_FLAG
-static inline bool
-pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
-{
- char _res = 1;
-
- __asm__ __volatile__(
- " lock \n"
- " xchgb %0,%1 \n"
-: "+q"(_res), "+m"(ptr->value)
-:
-: "memory");
- return _res == 0;
-}
-
-#define PG_HAVE_ATOMIC_CLEAR_FLAG
-static inline void
-pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
-{
- /*
- * On a TSO architecture like x86 it's sufficient to use a compiler
- * barrier to achieve release semantics.
- */
- __asm__ __volatile__("" ::: "memory");
- ptr->value = 0;
-}
-
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
static inline bool
pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr,
diff --git a/src/include/port/atomics/generic-gcc.h b/src/include/port/atomics/generic-gcc.h
index 5bfce82f687..9be820f72b1 100644
--- a/src/include/port/atomics/generic-gcc.h
+++ b/src/include/port/atomics/generic-gcc.h
@@ -61,27 +61,6 @@
#endif
-/* 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))
-
-#define PG_HAVE_ATOMIC_FLAG_SUPPORT
-typedef struct pg_atomic_flag
-{
- /*
- * If we have a choice, use int-width TAS, because that is more efficient
- * and/or more reliably implemented on most non-Intel platforms. (Note
- * that this code isn't used on x86[_64]; see arch-x86.h for that.)
- */
-#ifdef HAVE_GCC__SYNC_INT32_TAS
- volatile int value;
-#else
- volatile char value;
-#endif
-} pg_atomic_flag;
-
-#endif /* !ATOMIC_FLAG_SUPPORT && SYNC_INT32_TAS */
-
/* generic gcc based atomic uint32 implementation */
#if !defined(PG_HAVE_ATOMIC_U32_SUPPORT) \
&& (defined(HAVE_GCC__ATOMIC_INT32_CAS) || defined(HAVE_GCC__SYNC_INT32_CAS))
@@ -107,52 +86,6 @@ typedef struct pg_atomic_uint64
#endif /* defined(HAVE_GCC__ATOMIC_INT64_CAS) || defined(HAVE_GCC__SYNC_INT64_CAS) */
-#ifdef PG_HAVE_ATOMIC_FLAG_SUPPORT
-
-#if defined(HAVE_GCC__SYNC_CHAR_TAS) || defined(HAVE_GCC__SYNC_INT32_TAS)
-
-#ifndef PG_HAVE_ATOMIC_TEST_SET_FLAG
-#define PG_HAVE_ATOMIC_TEST_SET_FLAG
-static inline bool
-pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
-{
- /* NB: only an acquire barrier, not a full one */
- /* some platform only support a 1 here */
- return __sync_lock_test_and_set(&ptr->value, 1) == 0;
-}
-#endif
-
-#endif /* defined(HAVE_GCC__SYNC_*_TAS) */
-
-#ifndef PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
-#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
-static inline bool
-pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
-{
- return ptr->value == 0;
-}
-#endif
-
-#ifndef PG_HAVE_ATOMIC_CLEAR_FLAG
-#define PG_HAVE_ATOMIC_CLEAR_FLAG
-static inline void
-pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
-{
- __sync_lock_release(&ptr->value);
-}
-#endif
-
-#ifndef PG_HAVE_ATOMIC_INIT_FLAG
-#define PG_HAVE_ATOMIC_INIT_FLAG
-static inline void
-pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
-{
- pg_atomic_clear_flag_impl(ptr);
-}
-#endif
-
-#endif /* defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) */
-
/* prefer __atomic, it has a better API */
#if !defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32) && defined(HAVE_GCC__ATOMIC_INT32_CAS)
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
diff --git a/src/include/port/atomics/generic.h b/src/include/port/atomics/generic.h
index daa772e9a6d..c5a130c76a2 100644
--- a/src/include/port/atomics/generic.h
+++ b/src/include/port/atomics/generic.h
@@ -28,12 +28,6 @@
# define pg_write_barrier_impl pg_memory_barrier_impl
#endif
-/* provide fallback */
-#if !defined(PG_HAVE_ATOMIC_FLAG_SUPPORT) && defined(PG_HAVE_ATOMIC_U32_SUPPORT)
-#define PG_HAVE_ATOMIC_FLAG_SUPPORT
-typedef pg_atomic_uint32 pg_atomic_flag;
-#endif
-
#ifndef PG_HAVE_ATOMIC_READ_U32
#define PG_HAVE_ATOMIC_READ_U32
static inline uint32
@@ -61,84 +55,6 @@ pg_atomic_unlocked_write_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 val)
}
#endif
-/*
- * provide fallback for test_and_set using atomic_exchange if available
- */
-#if !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) && defined(PG_HAVE_ATOMIC_EXCHANGE_U32)
-
-#define PG_HAVE_ATOMIC_INIT_FLAG
-static inline void
-pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
-{
- pg_atomic_write_u32_impl(ptr, 0);
-}
-
-#define PG_HAVE_ATOMIC_TEST_SET_FLAG
-static inline bool
-pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
-{
- return pg_atomic_exchange_u32_impl(ptr, 1) == 0;
-}
-
-#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
-static inline bool
-pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
-{
- return pg_atomic_read_u32_impl(ptr) == 0;
-}
-
-
-#define PG_HAVE_ATOMIC_CLEAR_FLAG
-static inline void
-pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
-{
- /* XXX: release semantics suffice? */
- pg_memory_barrier_impl();
- pg_atomic_write_u32_impl(ptr, 0);
-}
-
-/*
- * provide fallback for test_and_set using atomic_compare_exchange if
- * available.
- */
-#elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
-
-#define PG_HAVE_ATOMIC_INIT_FLAG
-static inline void
-pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
-{
- pg_atomic_write_u32_impl(ptr, 0);
-}
-
-#define PG_HAVE_ATOMIC_TEST_SET_FLAG
-static inline bool
-pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
-{
- uint32 value = 0;
- return pg_atomic_compare_exchange_u32_impl(ptr, &value, 1);
-}
-
-#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
-static inline bool
-pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
-{
- return pg_atomic_read_u32_impl(ptr) == 0;
-}
-
-#define PG_HAVE_ATOMIC_CLEAR_FLAG
-static inline void
-pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
-{
- /* XXX: release semantics suffice? */
- pg_memory_barrier_impl();
- pg_atomic_write_u32_impl(ptr, 0);
-}
-
-#elif !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG)
-# error "No pg_atomic_test_and_set provided"
-#endif /* !defined(PG_HAVE_ATOMIC_TEST_SET_FLAG) */
-
-
#ifndef PG_HAVE_ATOMIC_INIT_U32
#define PG_HAVE_ATOMIC_INIT_U32
static inline void
@@ -427,4 +343,70 @@ pg_atomic_write_membarrier_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 val)
{
(void) pg_atomic_exchange_u64_impl(ptr, val);
}
+
+
+/* implement pg_atomic_bool over pg_atomic_u32 */
+#if !defined(PG_HAVE_ATOMIC_BOOL_SUPPORT) && defined(PG_HAVE_ATOMIC_U32_SUPPORT)
+#define PG_HAVE_ATOMIC_BOOL_SUPPORT
+typedef pg_atomic_uint32 pg_atomic_bool;
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_INIT_BOOL) && defined(PG_HAVE_ATOMIC_INIT_U32)
+static inline void
+pg_atomic_init_bool_impl(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_init_u32_impl(ptr, (uint32) val);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_READ_BOOL) && defined(PG_HAVE_ATOMIC_READ_U32)
+static inline bool
+pg_atomic_read_bool_impl(volatile pg_atomic_bool *ptr)
+{
+ return (bool) pg_atomic_read_u32_impl(ptr);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_READ_MEMBARRIER_BOOL) && defined(PG_HAVE_ATOMIC_READ_MEMBARRIER_U32)
+static inline bool
+pg_atomic_read_membarrier_bool_impl(volatile pg_atomic_bool *ptr)
+{
+ return (bool) pg_atomic_read_membarrier_u32_impl(ptr);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_WRITE_BOOL) && defined(PG_HAVE_ATOMIC_WRITE_U32)
+static inline void
+pg_atomic_write_bool_impl(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_write_u32_impl(ptr, (uint32) val);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_UNLOCKED_WRITE_BOOL) && defined(PG_HAVE_ATOMIC_UNLOCKED_WRITE_U32)
+static inline void
+pg_atomic_unlocked_write_bool_impl(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_unlocked_write_u32_impl(ptr, (uint32) val);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_WRITE_MEMBARRIER_BOOL) && defined(PG_HAVE_ATOMIC_WRITE_MEMBARRIER_U32)
+static inline void
+pg_atomic_write_membarrier_bool_impl(volatile pg_atomic_bool *ptr, bool val)
+{
+ pg_atomic_write_membarrier_u32_impl(ptr, (uint32) val);
+}
+#endif
+
+#if !defined(PG_HAVE_ATOMIC_EXCHANGE_BOOL) && defined(PG_HAVE_ATOMIC_EXCHANGE_U32)
+static inline bool
+pg_atomic_exchange_bool_impl(volatile pg_atomic_bool *ptr, bool newval)
+{
+ return (bool) pg_atomic_exchange_u32_impl(ptr, (uint32) newval);
+}
+#endif
+
+
+
#endif
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index d5aafdf370c..7287197a1b6 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -63,6 +63,14 @@
#expr, __FILE__, __LINE__); \
} while (0)
+#define EXPECT_FALSE(expr) \
+ do { \
+ if ((expr)) \
+ elog(ERROR, \
+ "%s was unexpectedly true in file \"%s\" line %u", \
+ #expr, __FILE__, __LINE__); \
+ } while (0)
+
#define EXPECT_EQ_U32(result_expr, expected_expr) \
do { \
uint32 actual_result = (result_expr); \
@@ -503,19 +511,19 @@ wait_pid(PG_FUNCTION_ARGS)
}
static void
-test_atomic_flag(void)
+test_atomic_bool(void)
{
- pg_atomic_flag flag;
-
- pg_atomic_init_flag(&flag);
- EXPECT_TRUE(pg_atomic_unlocked_test_flag(&flag));
- EXPECT_TRUE(pg_atomic_test_set_flag(&flag));
- EXPECT_TRUE(!pg_atomic_unlocked_test_flag(&flag));
- EXPECT_TRUE(!pg_atomic_test_set_flag(&flag));
- pg_atomic_clear_flag(&flag);
- EXPECT_TRUE(pg_atomic_unlocked_test_flag(&flag));
- EXPECT_TRUE(pg_atomic_test_set_flag(&flag));
- pg_atomic_clear_flag(&flag);
+ pg_atomic_bool flag;
+
+ pg_atomic_init_bool(&flag, false);
+ EXPECT_FALSE(pg_atomic_read_bool(&flag));
+ pg_atomic_write_bool(&flag, true);
+ EXPECT_TRUE(pg_atomic_read_bool(&flag));
+
+ EXPECT_TRUE(pg_atomic_exchange_bool(&flag, true));
+ EXPECT_TRUE(pg_atomic_exchange_bool(&flag, false));
+ EXPECT_FALSE(pg_atomic_exchange_bool(&flag, false));
+ EXPECT_FALSE(pg_atomic_exchange_bool(&flag, true));
}
static void
@@ -710,7 +718,7 @@ PG_FUNCTION_INFO_V1(test_atomic_ops);
Datum
test_atomic_ops(PG_FUNCTION_ARGS)
{
- test_atomic_flag();
+ test_atomic_bool();
test_atomic_uint32();
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 117e7379f10..4d5f9bbb5cd 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -4020,7 +4020,7 @@ pe_test_vector
pendingPosition
pending_label
pgParameterStatus
-pg_atomic_flag
+pg_atomic_bool
pg_atomic_uint32
pg_atomic_uint64
pg_be_sasl_mech
--
2.47.3