From 3ada5198498ff861edd0c1afa2211a471f369ec1 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Thu, 14 Mar 2024 07:07:38 +0000 Subject: [PATCH v14 1/4] Add monotonic advancement functions for atomics This commit adds functions for monotonically advancing the given atomic variable with full barrier semantics. An upcoming commit uses 64-bit monotonic function. But this commit also adds 32-bit version just for the sake of completeness. --- src/include/port/atomics.h | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h index ff47782cdb..53e1a337a4 100644 --- a/src/include/port/atomics.h +++ b/src/include/port/atomics.h @@ -438,6 +438,35 @@ pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_) return pg_atomic_sub_fetch_u32_impl(ptr, sub_); } +/* + * Monotonically advance the given variable using only atomic operations until + * it's at least the target value. + * + * Full barrier semantics (even when value is unchanged). + */ +static inline void +pg_atomic_monotonic_advance_u32(volatile pg_atomic_uint32 *ptr, uint32 target_) +{ + uint32 currval; + + AssertPointerAlignment(ptr, 4); + + currval = pg_atomic_read_u32_impl(ptr); + if (currval >= target_) + { + pg_memory_barrier(); + return; + } + + AssertPointerAlignment(&currval, 4); + + while (currval < target_) + { + if (pg_atomic_compare_exchange_u32_impl(ptr, &currval, target_)) + break; + } +} + /* ---- * The 64 bit operations have the same semantics as their 32bit counterparts * if they are available. Check the corresponding 32bit function for @@ -570,6 +599,33 @@ pg_atomic_sub_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 sub_) return pg_atomic_sub_fetch_u64_impl(ptr, sub_); } +static inline void +pg_atomic_monotonic_advance_u64(volatile pg_atomic_uint64 *ptr, uint64 target_) +{ + uint64 currval; + +#ifndef PG_HAVE_ATOMIC_U64_SIMULATION + AssertPointerAlignment(ptr, 8); +#endif + + currval = pg_atomic_read_u64_impl(ptr); + if (currval >= target_) + { + pg_memory_barrier(); + return; + } + +#ifndef PG_HAVE_ATOMIC_U64_SIMULATION + AssertPointerAlignment(&currval, 8); +#endif + + while (currval < target_) + { + if (pg_atomic_compare_exchange_u64_impl(ptr, &currval, target_)) + break; + } +} + #undef INSIDE_ATOMICS_H #endif /* ATOMICS_H */ -- 2.34.1