From 46a5b9451830a870bb23e80fec8428854a807970 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Wed, 21 Feb 2024 10:46:02 +0000 Subject: [PATCH v12 1/3] Add functions for monotonic advancement of atomic variables 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 | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h index bf151037f7..b1f1c04b9f 100644 --- a/src/include/port/atomics.h +++ b/src/include/port/atomics.h @@ -400,6 +400,36 @@ 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(ptr, 4); + 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 @@ -514,6 +544,40 @@ pg_atomic_sub_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 sub_) return pg_atomic_sub_fetch_u64_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_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(ptr, 8); + 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