[glib: 1/4] gatomic: Use new __atomic_*() intrinsics for all atomic operations
- From: Sebastian Dröge <sdroege src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/4] gatomic: Use new __atomic_*() intrinsics for all atomic operations
- Date: Thu, 14 Nov 2019 13:41:12 +0000 (UTC)
commit 2eb37622418a5c9f31a9d728a99bc621d3157ab0
Author: Philip Withnall <withnall endlessm com>
Date: Sat Sep 21 17:34:37 2019 +0200
gatomic: Use new __atomic_*() intrinsics for all atomic operations
Previously we used the old `__sync_fetch_*()` intrinsics for some of the
atomic operations, such as `g_atomic_int_compare_and_exchange()`. When
available, use the new `__atomic_*()` intrinsics for those instead.
As with the rest of our use of `__atomic_*()` intrinsics, we use the
`__ATOMIC_SEQ_CST` memory model. If people want to use a less
restrictive memory model to get better performance in certain
situations, they can use the compiler intrinsics directly themselves.
`g_atomic_*()` aim to be as fast as possible while remaining general
purpose.
Tested using:
```
meson test --repeat 1000 atomic atomic-test
```
Signed-off-by: Philip Withnall <withnall endlessm com>
Fixes: #1750
glib/gatomic.h | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 88 insertions(+), 2 deletions(-)
---
diff --git a/glib/gatomic.h b/glib/gatomic.h
index 61a99adf2..712553e69 100644
--- a/glib/gatomic.h
+++ b/glib/gatomic.h
@@ -118,6 +118,92 @@ G_END_DECLS
__atomic_store ((gpointer *)(atomic), &gaps_temp, __ATOMIC_SEQ_CST); \
}))
+#define g_atomic_int_inc(atomic) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ *(atomic) : 1); \
+ (void) __atomic_fetch_add ((atomic), 1, __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_int_dec_and_test(atomic) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ *(atomic) : 1); \
+ __atomic_fetch_sub ((atomic), 1, __ATOMIC_SEQ_CST) == 1; \
+ }))
+#define g_atomic_int_compare_and_exchange(atomic, oldval, newval) \
+ (G_GNUC_EXTENSION ({ \
+ gint gaicae_oldval = (oldval); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (newval) ^ (oldval) : 1); \
+ __atomic_compare_exchange_n ((atomic), &gaicae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST) ? TRUE : FALSE; \
+ }))
+#define g_atomic_int_add(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (val) : 1); \
+ (gint) __atomic_fetch_add ((atomic), (val), __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_int_and(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (val) : 1); \
+ (guint) __atomic_fetch_and ((atomic), (val), __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_int_or(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (val) : 1); \
+ (guint) __atomic_fetch_or ((atomic), (val), __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_int_xor(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
+ (void) (0 ? *(atomic) ^ (val) : 1); \
+ (guint) __atomic_fetch_xor ((atomic), (val), __ATOMIC_SEQ_CST); \
+ }))
+
+#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
+ (G_GNUC_EXTENSION ({ \
+ __typeof__ ((oldval)) gapcae_oldval = (oldval); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST) ? TRUE : FALSE; \
+ }))
+#define g_atomic_pointer_add(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (void) (0 ? (val) ^ (val) : 1); \
+ (gssize) __atomic_fetch_add ((atomic), (val), __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_pointer_and(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ volatile gsize *gapa_atomic = (volatile gsize *) (atomic); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (void) (0 ? (val) ^ (val) : 1); \
+ (gsize) __atomic_fetch_and (gapa_atomic, (val), __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_pointer_or(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ volatile gsize *gapo_atomic = (volatile gsize *) (atomic); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (void) (0 ? (val) ^ (val) : 1); \
+ (gsize) __atomic_fetch_or (gapo_atomic, (val), __ATOMIC_SEQ_CST); \
+ }))
+#define g_atomic_pointer_xor(atomic, val) \
+ (G_GNUC_EXTENSION ({ \
+ volatile gsize *gapx_atomic = (volatile gsize *) (atomic); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \
+ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \
+ (void) (0 ? (gpointer) *(atomic) : NULL); \
+ (void) (0 ? (val) ^ (val) : 1); \
+ (gsize) __atomic_fetch_xor (gapx_atomic, (val), __ATOMIC_SEQ_CST); \
+ }))
+
#else /* defined(__ATOMIC_SEQ_CST) */
/* We want to achieve __ATOMIC_SEQ_CST semantics here. See
@@ -184,8 +270,6 @@ G_END_DECLS
*(atomic) = (__typeof__ (*(atomic))) (gsize) (newval); \
}))
-#endif /* !defined(__ATOMIC_SEQ_CST) */
-
#define g_atomic_int_inc(atomic) \
(G_GNUC_EXTENSION ({ \
G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gint)); \
@@ -264,6 +348,8 @@ G_END_DECLS
(gsize) __sync_fetch_and_xor ((atomic), (val)); \
}))
+#endif /* !defined(__ATOMIC_SEQ_CST) */
+
#else /* defined(G_ATOMIC_LOCK_FREE) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) */
#define g_atomic_int_get(atomic) \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]