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
This commit is contained in:
Alex Richardson 2022-12-14 23:55:17 +00:00
parent 877c575cd9
commit c762d51134
3 changed files with 109 additions and 93 deletions

View File

@ -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;

View File

@ -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) */

View File

@ -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);