From c762d511346d3cb84cea3557a246ccf8873b4a1c Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 14 Dec 2022 23:55:17 +0000 Subject: [PATCH] gatomic: Use g(u)intptr where appropriate This is required for CHERI systems such as Arm Morello, where gsize is not large enough to hold a pointer. For all other architectures this should not result in any functional changes since gsize is already the same size (and I believe for most architectures even the same type) as guintptr. This is fully ABI compatible with all currently supported architectures and should also be fully API compatible except for some rather unlikely examples such as someone happening to use something like `decltype(g_atomic_pointer_add(&a, 0))` in a C++ context where it changes name mangling of some function. Helps: https://gitlab.gnome.org/GNOME/glib/-/issues/2842 --- glib/gatomic.c | 58 +++++++++++++++--------- glib/gatomic.h | 40 ++++++++--------- glib/tests/atomic.c | 104 ++++++++++++++++++++++---------------------- 3 files changed, 109 insertions(+), 93 deletions(-) diff --git a/glib/gatomic.c b/glib/gatomic.c index 6c1ea768e..a40885d92 100644 --- a/glib/gatomic.c +++ b/glib/gatomic.c @@ -34,7 +34,7 @@ * * The macros that have 'int' in the name will operate on pointers to * #gint and #guint. The macros with 'pointer' in the name will operate - * on pointers to any pointer-sized value, including #gsize. There is + * on pointers to any pointer-sized value, including #guintptr. There is * no support for 64bit operations on platforms with 32bit pointers * because it is not generally possible to perform these operations * atomically. @@ -538,11 +538,15 @@ gpointer * While @atomic has a `volatile` qualifier, this is a historical artifact and * the pointer passed to it should not be `volatile`. * + * In GLib 2.80, the return type was changed from #gssize to #gintptr to add + * support for platforms with 128-bit pointers. This should not affect existing + * code. + * * Returns: the value of @atomic before the add, signed * * Since: 2.30 **/ -gssize +gintptr (g_atomic_pointer_add) (volatile void *atomic, gssize val) { @@ -565,11 +569,15 @@ gssize * While @atomic has a `volatile` qualifier, this is a historical artifact and * the pointer passed to it should not be `volatile`. * + * In GLib 2.80, the return type was changed from #gsize to #guintptr to add + * support for platforms with 128-bit pointers. This should not affect existing + * code. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 **/ -gsize +guintptr (g_atomic_pointer_and) (volatile void *atomic, gsize val) { @@ -592,11 +600,15 @@ gsize * While @atomic has a `volatile` qualifier, this is a historical artifact and * the pointer passed to it should not be `volatile`. * + * In GLib 2.80, the return type was changed from #gsize to #guintptr to add + * support for platforms with 128-bit pointers. This should not affect existing + * code. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 **/ -gsize +guintptr (g_atomic_pointer_or) (volatile void *atomic, gsize val) { @@ -619,11 +631,15 @@ gsize * While @atomic has a `volatile` qualifier, this is a historical artifact and * the pointer passed to it should not be `volatile`. * + * In GLib 2.80, the return type was changed from #gsize to #guintptr to add + * support for platforms with 128-bit pointers. This should not affect existing + * code. + * * Returns: the value of @atomic before the operation, unsigned * * Since: 2.30 **/ -gsize +guintptr (g_atomic_pointer_xor) (volatile void *atomic, gsize val) { @@ -820,7 +836,7 @@ gpointer return InterlockedExchangePointer (atomic, newval); } -gssize +gintptr (g_atomic_pointer_add) (volatile void *atomic, gssize val) { @@ -831,7 +847,7 @@ gssize #endif } -gsize +guintptr (g_atomic_pointer_and) (volatile void *atomic, gsize val) { @@ -842,7 +858,7 @@ gsize #endif } -gsize +guintptr (g_atomic_pointer_or) (volatile void *atomic, gsize val) { @@ -853,7 +869,7 @@ gsize #endif } -gsize +guintptr (g_atomic_pointer_xor) (volatile void *atomic, gsize val) { @@ -1112,12 +1128,12 @@ gpointer return oldval; } -gssize +gintptr (g_atomic_pointer_add) (volatile void *atomic, gssize val) { - gssize *ptr = atomic; - gssize oldval; + gintptr *ptr = atomic; + gintptr oldval; pthread_mutex_lock (&g_atomic_lock); oldval = *ptr; @@ -1127,12 +1143,12 @@ gssize return oldval; } -gsize +guintptr (g_atomic_pointer_and) (volatile void *atomic, gsize val) { - gsize *ptr = atomic; - gsize oldval; + guintptr *ptr = atomic; + guintptr oldval; pthread_mutex_lock (&g_atomic_lock); oldval = *ptr; @@ -1142,12 +1158,12 @@ gsize return oldval; } -gsize +guintptr (g_atomic_pointer_or) (volatile void *atomic, gsize val) { - gsize *ptr = atomic; - gsize oldval; + guintptr *ptr = atomic; + guintptr oldval; pthread_mutex_lock (&g_atomic_lock); oldval = *ptr; @@ -1157,12 +1173,12 @@ gsize return oldval; } -gsize +guintptr (g_atomic_pointer_xor) (volatile void *atomic, gsize val) { - gsize *ptr = atomic; - gsize oldval; + guintptr *ptr = atomic; + guintptr oldval; pthread_mutex_lock (&g_atomic_lock); oldval = *ptr; diff --git a/glib/gatomic.h b/glib/gatomic.h index 148424dc3..93998880c 100644 --- a/glib/gatomic.h +++ b/glib/gatomic.h @@ -83,16 +83,16 @@ GLIB_AVAILABLE_IN_2_74 gpointer g_atomic_pointer_exchange (void *atomic, gpointer newval); GLIB_AVAILABLE_IN_ALL -gssize g_atomic_pointer_add (volatile void *atomic, +gintptr g_atomic_pointer_add (volatile void *atomic, gssize val); GLIB_AVAILABLE_IN_2_30 -gsize g_atomic_pointer_and (volatile void *atomic, +guintptr g_atomic_pointer_and (volatile void *atomic, gsize val); GLIB_AVAILABLE_IN_2_30 -gsize g_atomic_pointer_or (volatile void *atomic, +guintptr g_atomic_pointer_or (volatile void *atomic, gsize val); GLIB_AVAILABLE_IN_ALL -gsize g_atomic_pointer_xor (volatile void *atomic, +guintptr g_atomic_pointer_xor (volatile void *atomic, gsize val); GLIB_DEPRECATED_IN_2_30_FOR(g_atomic_int_add) @@ -280,34 +280,34 @@ G_END_DECLS 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); \ + (gintptr) __atomic_fetch_add ((atomic), (val), __ATOMIC_SEQ_CST); \ })) #define g_atomic_pointer_and(atomic, val) \ (G_GNUC_EXTENSION ({ \ - gsize *gapa_atomic = (gsize *) (atomic); \ + guintptr *gapa_atomic = (guintptr *) (atomic); \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (guintptr)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gsize) __atomic_fetch_and (gapa_atomic, (val), __ATOMIC_SEQ_CST); \ + (guintptr) __atomic_fetch_and (gapa_atomic, (val), __ATOMIC_SEQ_CST); \ })) #define g_atomic_pointer_or(atomic, val) \ (G_GNUC_EXTENSION ({ \ - gsize *gapo_atomic = (gsize *) (atomic); \ + guintptr *gapo_atomic = (guintptr *) (atomic); \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (guintptr)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gsize) __atomic_fetch_or (gapo_atomic, (val), __ATOMIC_SEQ_CST); \ + (guintptr) __atomic_fetch_or (gapo_atomic, (val), __ATOMIC_SEQ_CST); \ })) #define g_atomic_pointer_xor(atomic, val) \ (G_GNUC_EXTENSION ({ \ - gsize *gapx_atomic = (gsize *) (atomic); \ + guintptr *gapx_atomic = (guintptr *) (atomic); \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ - G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gsize)); \ + G_STATIC_ASSERT (sizeof *(atomic) == sizeof (guintptr)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gsize) __atomic_fetch_xor (gapx_atomic, (val), __ATOMIC_SEQ_CST); \ + (guintptr) __atomic_fetch_xor (gapx_atomic, (val), __ATOMIC_SEQ_CST); \ })) #else /* defined(__ATOMIC_SEQ_CST) */ @@ -374,7 +374,7 @@ G_END_DECLS (void) (0 ? (gpointer) *(atomic) : NULL); \ __sync_synchronize (); \ __asm__ __volatile__ ("" : : : "memory"); \ - *(atomic) = (glib_typeof (*(atomic))) (gsize) (newval); \ + *(atomic) = (glib_typeof (*(atomic))) (guintptr) (newval); \ })) #else /* if !(defined(glib_typeof) */ #define g_atomic_pointer_set(atomic, newval) \ @@ -383,7 +383,7 @@ G_END_DECLS (void) (0 ? (gpointer) *(atomic) : NULL); \ __sync_synchronize (); \ __asm__ __volatile__ ("" : : : "memory"); \ - *(atomic) = (gpointer) (gsize) (newval); \ + *(atomic) = (gpointer) (guintptr) (newval); \ })) #endif /* if defined(glib_typeof) */ @@ -498,28 +498,28 @@ G_END_DECLS G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gssize) __sync_fetch_and_add ((atomic), (val)); \ + (gintptr) __sync_fetch_and_add ((atomic), (val)); \ })) #define g_atomic_pointer_and(atomic, val) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gsize) __sync_fetch_and_and ((atomic), (val)); \ + (guintptr) __sync_fetch_and_and ((atomic), (val)); \ })) #define g_atomic_pointer_or(atomic, val) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gsize) __sync_fetch_and_or ((atomic), (val)); \ + (guintptr) __sync_fetch_and_or ((atomic), (val)); \ })) #define g_atomic_pointer_xor(atomic, val) \ (G_GNUC_EXTENSION ({ \ G_STATIC_ASSERT (sizeof *(atomic) == sizeof (gpointer)); \ (void) (0 ? (gpointer) *(atomic) : NULL); \ (void) (0 ? (val) ^ (val) : 1); \ - (gsize) __sync_fetch_and_xor ((atomic), (val)); \ + (guintptr) __sync_fetch_and_xor ((atomic), (val)); \ })) #endif /* !defined(__ATOMIC_SEQ_CST) */ diff --git a/glib/tests/atomic.c b/glib/tests/atomic.c index 614d5aa4b..9d57d2114 100644 --- a/glib/tests/atomic.c +++ b/glib/tests/atomic.c @@ -31,7 +31,7 @@ test_types (void) const char *str = "Hello"; const char *old_str; int *ip, *ip2; - gsize gs, gs2; + guintptr gu, gu2; gboolean res; csp = &s; @@ -158,36 +158,36 @@ test_types (void) res = g_atomic_pointer_compare_and_exchange_full (&ip, NULL, &s, &ip2); g_assert_true (res); g_assert_true (ip == &s); - g_assert_cmpuint ((gsize) ip2, ==, 0); + g_assert_cmpuint ((guintptr) ip2, ==, 0); res = g_atomic_pointer_compare_and_exchange_full (&ip, NULL, NULL, &ip2); g_assert_false (res); g_assert_true (ip == &s); g_assert_true (ip2 == &s); - g_atomic_pointer_set (&gs, 0); - vp2 = (gpointer) g_atomic_pointer_get (&gs); - gs2 = (gsize) vp2; - g_assert_cmpuint (gs2, ==, 0); - res = g_atomic_pointer_compare_and_exchange (&gs, NULL, (gsize) NULL); + g_atomic_pointer_set (&gu, 0); + vp2 = (gpointer) g_atomic_pointer_get (&gu); + gu2 = (guintptr) vp2; + g_assert_cmpuint (gu2, ==, 0); + res = g_atomic_pointer_compare_and_exchange (&gu, NULL, (guintptr) NULL); g_assert_true (res); - g_assert_cmpuint (gs, ==, 0); - res = g_atomic_pointer_compare_and_exchange_full (&gs, (gsize) NULL, (gsize) NULL, &gs2); + g_assert_cmpuint (gu, ==, 0); + res = g_atomic_pointer_compare_and_exchange_full (&gu, (guintptr) NULL, (guintptr) NULL, &gu2); g_assert_true (res); - g_assert_cmpuint (gs, ==, 0); - g_assert_cmpuint (gs2, ==, 0); - gs2 = (gsize) g_atomic_pointer_add (&gs, 5); - g_assert_cmpuint (gs2, ==, 0); - g_assert_cmpuint (gs, ==, 5); - gs2 = g_atomic_pointer_and (&gs, 6); - g_assert_cmpuint (gs2, ==, 5); - g_assert_cmpuint (gs, ==, 4); - gs2 = g_atomic_pointer_or (&gs, 8); - g_assert_cmpuint (gs2, ==, 4); - g_assert_cmpuint (gs, ==, 12); - gs2 = g_atomic_pointer_xor (&gs, 4); - g_assert_cmpuint (gs2, ==, 12); - g_assert_cmpuint (gs, ==, 8); + g_assert_cmpuint (gu, ==, 0); + g_assert_cmpuint (gu2, ==, 0); + gu2 = (guintptr) g_atomic_pointer_add (&gu, 5); + g_assert_cmpuint (gu2, ==, 0); + g_assert_cmpuint (gu, ==, 5); + gu2 = g_atomic_pointer_and (&gu, 6); + g_assert_cmpuint (gu2, ==, 5); + g_assert_cmpuint (gu, ==, 4); + gu2 = g_atomic_pointer_or (&gu, 8); + g_assert_cmpuint (gu2, ==, 4); + g_assert_cmpuint (gu, ==, 12); + gu2 = g_atomic_pointer_xor (&gu, 4); + g_assert_cmpuint (gu2, ==, 12); + g_assert_cmpuint (gu, ==, 8); vp_str2 = g_atomic_pointer_exchange (&vp_str, str); g_assert_cmpstr (vp_str, ==, str); g_assert_null (vp_str2); @@ -340,41 +340,41 @@ G_GNUC_END_IGNORE_DEPRECATIONS res = g_atomic_pointer_compare_and_exchange_full (&ip, NULL, (gpointer) 1, &cp); g_assert_true (res); - g_assert_cmpint ((gsize) ip, ==, 1); - g_assert_cmpuint ((gsize) cp, ==, 0); + g_assert_cmpint ((guintptr) ip, ==, 1); + g_assert_cmpuint ((guintptr) cp, ==, 0); res = g_atomic_pointer_compare_and_exchange_full (&ip, NULL, NULL, &cp); g_assert_false (res); - g_assert_cmpuint ((gsize) ip, ==, 1); - g_assert_cmpuint ((gsize) cp, ==, 1); + g_assert_cmpuint ((guintptr) ip, ==, 1); + g_assert_cmpuint ((guintptr) cp, ==, 1); - g_atomic_pointer_set (&gs, 0); - vp = g_atomic_pointer_get (&gs); - gs2 = (gsize) vp; - g_assert_cmpuint (gs2, ==, 0); - res = g_atomic_pointer_compare_and_exchange (&gs, NULL, NULL); + g_atomic_pointer_set (&gu, 0); + vp = g_atomic_pointer_get (&gu); + gu2 = (guintptr) vp; + g_assert_cmpuint (gu2, ==, 0); + res = g_atomic_pointer_compare_and_exchange (&gu, NULL, NULL); g_assert_true (res); - g_assert_cmpuint (gs, ==, 0); - res = g_atomic_pointer_compare_and_exchange_full (&gs, NULL, NULL, &cp); + g_assert_cmpuint (gu, ==, 0); + res = g_atomic_pointer_compare_and_exchange_full (&gu, NULL, NULL, &cp); g_assert_true (res); - g_assert_cmpuint (gs, ==, 0); - g_assert_cmpuint ((gsize) cp, ==, 0); - gs2 = (gsize) g_atomic_pointer_add (&gs, 5); - g_assert_cmpuint (gs2, ==, 0); - g_assert_cmpuint (gs, ==, 5); - gs2 = g_atomic_pointer_and (&gs, 6); - g_assert_cmpuint (gs2, ==, 5); - g_assert_cmpuint (gs, ==, 4); - gs2 = g_atomic_pointer_or (&gs, 8); - g_assert_cmpuint (gs2, ==, 4); - g_assert_cmpuint (gs, ==, 12); - gs2 = g_atomic_pointer_xor (&gs, 4); - g_assert_cmpuint (gs2, ==, 12); - g_assert_cmpuint (gs, ==, 8); - vp2 = g_atomic_pointer_exchange (&gs, NULL); - gs2 = (gsize) vp2; - g_assert_cmpuint (gs2, ==, 8); - g_assert_null ((gpointer) gs); + g_assert_cmpuint (gu, ==, 0); + g_assert_cmpuint ((guintptr) cp, ==, 0); + gu2 = (guintptr) g_atomic_pointer_add (&gu, 5); + g_assert_cmpuint (gu2, ==, 0); + g_assert_cmpuint (gu, ==, 5); + gu2 = g_atomic_pointer_and (&gu, 6); + g_assert_cmpuint (gu2, ==, 5); + g_assert_cmpuint (gu, ==, 4); + gu2 = g_atomic_pointer_or (&gu, 8); + g_assert_cmpuint (gu2, ==, 4); + g_assert_cmpuint (gu, ==, 12); + gu2 = g_atomic_pointer_xor (&gu, 4); + g_assert_cmpuint (gu2, ==, 12); + g_assert_cmpuint (gu, ==, 8); + vp2 = g_atomic_pointer_exchange (&gu, NULL); + gu2 = (guintptr) vp2; + g_assert_cmpuint (gu2, ==, 8); + g_assert_null ((gpointer) gu); g_assert_cmpint (g_atomic_int_get (csp), ==, s); g_assert_true (g_atomic_pointer_get (cspp) == csp);