summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Freund2014-09-25 20:45:08 +0000
committerAndres Freund2014-10-01 16:01:47 +0000
commitd871e5f720000b7ca3de795f37e3f5307d776c3c (patch)
treebebbffe23cbd7f736624e996407a188131b440ff
parenteedffb0e25b6cc1fa37dce9c8b548605e46a26c5 (diff)
Add pg_atomic_fetch_add_until_u32().rwlock-contention
-rw-r--r--src/include/port/atomics.h17
-rw-r--r--src/include/port/atomics/generic.h24
2 files changed, 41 insertions, 0 deletions
diff --git a/src/include/port/atomics.h b/src/include/port/atomics.h
index 5893543768..2aebbf7186 100644
--- a/src/include/port/atomics.h
+++ b/src/include/port/atomics.h
@@ -135,6 +135,8 @@ STATIC_IF_INLINE_DECLARE uint32 pg_atomic_fetch_and_u32(volatile pg_atomic_uint3
STATIC_IF_INLINE_DECLARE uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_);
STATIC_IF_INLINE_DECLARE uint32 pg_atomic_add_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 add_);
STATIC_IF_INLINE_DECLARE uint32 pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_);
+STATIC_IF_INLINE_DECLARE uint32 pg_atomic_fetch_add_until_u32(volatile pg_atomic_uint32 *ptr,
+ int32 add_, uint32 until);
#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
@@ -431,6 +433,21 @@ pg_atomic_sub_fetch_u32(volatile pg_atomic_uint32 *ptr, int32 sub_)
return pg_atomic_sub_fetch_u32_impl(ptr, sub_);
}
+/*
+ * pg_fetch_add_until_u32 - saturated addition to variable
+ *
+ * Returns the the value of ptr after the arithmetic operation.
+ *
+ * Full barrier semantics.
+ */
+STATIC_IF_INLINE uint32
+pg_atomic_fetch_add_until_u32(volatile pg_atomic_uint32 *ptr, int32 add_,
+ uint32 until)
+{
+ AssertPointerAlignment(ptr, 4);
+ return pg_atomic_fetch_add_until_u32_impl(ptr, add_, until);
+}
+
/* ----
* The 64 bit operations have the same semantics as their 32bit counterparts
* if they are available. Check the corresponding 32bit function for
diff --git a/src/include/port/atomics/generic.h b/src/include/port/atomics/generic.h
index fa751237a5..4d07b82cb6 100644
--- a/src/include/port/atomics/generic.h
+++ b/src/include/port/atomics/generic.h
@@ -248,6 +248,30 @@ pg_atomic_sub_fetch_u32_impl(volatile pg_atomic_uint32 *ptr, int32 sub_)
}
#endif
+#if !defined(PG_HAVE_ATOMIC_FETCH_ADD_UNTIL_U32) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32)
+#define PG_HAVE_ATOMIC_FETCH_ADD_UNTIL_U32
+static inline uint32
+pg_atomic_fetch_add_until_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_, uint32 until)
+{
+ uint32 old;
+ while (true)
+ {
+ uint32 new_val;
+ old = pg_atomic_read_u32_impl(ptr);
+ if (old >= until)
+ break;
+
+ new_val = old + add_;
+ if (new_val > until)
+ new_val = until;
+
+ if (pg_atomic_compare_exchange_u32_impl(ptr, &old, new_val))
+ break;
+ }
+ return old;
+}
+#endif
+
#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
#if !defined(PG_HAVE_ATOMIC_EXCHANGE_U64) && defined(PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64)