v3-0003-Assert-that-pg_atomic_flag-is-initialized.patch
text/x-patch
Filename: v3-0003-Assert-that-pg_atomic_flag-is-initialized.patch
Type: text/x-patch
Part: 2
Patch
Format: format-patch
Series: patch v3-0003
Subject: Assert that pg_atomic_flag is initialized.
| File | + | − |
|---|---|---|
| src/include/port/atomics/arch-x86.h | 45 | 3 |
From 8cf5d1088b22d0261423fe9e9060e6f9066c8fb5 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 1 Aug 2024 11:09:44 +1200
Subject: [PATCH v3 3/3] Assert that pg_atomic_flag is initialized.
On x86, use 1 and 2 as the clear and set values for pg_atomic_flag.
This way we can add a useful assertion that spinlocks, built on top of
pg_atomic_flag, have been initialized before use and are not relying on
zeroed memory.
---
src/include/port/atomics/arch-x86.h | 48 +++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/src/include/port/atomics/arch-x86.h b/src/include/port/atomics/arch-x86.h
index c12f8a60697..b0c4ae566a0 100644
--- a/src/include/port/atomics/arch-x86.h
+++ b/src/include/port/atomics/arch-x86.h
@@ -130,11 +130,41 @@ pg_spin_delay_impl(void)
#if defined(__GNUC__) || defined(__INTEL_COMPILER)
+/*
+ * Note: This implementation uses non-zero values to help detect uninitialized
+ * usage on a common platform. Note that, like the C11 atomic_flag interface
+ * that it is modeled on, pg_atomic_flag never reveals the actual values to
+ * callers and contents of memory are not specified.
+ */
+#define PG_ATOMIC_FLAG_SET 1
+#define PG_ATOMIC_FLAG_CLEAR 2
+
+static inline void
+pg_atomic_check_flag(volatile pg_atomic_flag *ptr)
+{
+#if USE_ASSERT_CHECKING
+ char value = ptr->value;
+
+ /* Sanity check that flag has been initialized. */
+ Assert(value == PG_ATOMIC_FLAG_SET || value == PG_ATOMIC_FLAG_CLEAR);
+#endif
+}
+
+#define PG_HAVE_ATOMIC_INIT_FLAG
+static inline void
+pg_atomic_init_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ ptr->value = PG_ATOMIC_FLAG_CLEAR;
+ __asm__ __volatile__("" ::: "memory");
+}
+
#define PG_HAVE_ATOMIC_TEST_SET_FLAG
static inline bool
pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
{
- char _res = 1;
+ char _res = PG_ATOMIC_FLAG_SET;
+
+ pg_atomic_check_flag(ptr);
__asm__ __volatile__(
" lock \n"
@@ -142,19 +172,31 @@ pg_atomic_test_set_flag_impl(volatile pg_atomic_flag *ptr)
: "+q"(_res), "+m"(ptr->value)
:
: "memory");
- return _res == 0;
+ return _res == PG_ATOMIC_FLAG_CLEAR;
}
#define PG_HAVE_ATOMIC_CLEAR_FLAG
static inline void
pg_atomic_clear_flag_impl(volatile pg_atomic_flag *ptr)
{
+ pg_atomic_check_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;
+ ptr->value = PG_ATOMIC_FLAG_CLEAR;
+}
+
+#define PG_HAVE_ATOMIC_UNLOCKED_TEST_FLAG
+static inline bool
+pg_atomic_unlocked_test_flag_impl(volatile pg_atomic_flag *ptr)
+{
+ pg_atomic_check_flag(ptr);
+
+ __asm__ __volatile__("" ::: "memory");
+ return ptr->value == PG_ATOMIC_FLAG_CLEAR;
}
#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
--
2.45.2