From c95bf0514cf2474bd88c2753601ce96e4a1bfa00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 29 Nov 2022 20:53:06 +0100 Subject: [PATCH] gobject: Use compare and exchange full to re-read old ref value In case g_atomic_int_compare_and_exchange() check fails we ended up doing another atomic get to figure out what it was the old reference count, however, we can avoid this by using the full version of the function that returns the value before the exchange happened as an out value. --- gobject/gobject.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gobject/gobject.c b/gobject/gobject.c index c1a69a896..95d3375c4 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -3789,14 +3789,16 @@ g_object_unref (gpointer _object) g_return_if_fail (G_IS_OBJECT (object)); /* here we want to atomically do: if (ref_count>1) { ref_count--; return; } */ - retry_atomic_decrement1: old_ref = g_atomic_int_get (&object->ref_count); + retry_atomic_decrement1: if (old_ref > 1) { /* valid if last 2 refs are owned by this call to unref and the toggle_ref */ gboolean has_toggle_ref = OBJECT_HAS_TOGGLE_REF (object); - if (!g_atomic_int_compare_and_exchange ((int *)&object->ref_count, old_ref, old_ref - 1)) + if (!g_atomic_int_compare_and_exchange_full ((int *)&object->ref_count, + old_ref, old_ref - 1, + &old_ref)) goto retry_atomic_decrement1; TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref)); @@ -3868,14 +3870,16 @@ g_object_unref (gpointer _object) TRACE (GOBJECT_OBJECT_DISPOSE_END(object,G_TYPE_FROM_INSTANCE(object), 1)); /* may have been re-referenced meanwhile */ - retry_atomic_decrement2: old_ref = g_atomic_int_get ((int *)&object->ref_count); + retry_atomic_decrement2: if (old_ref > 1) { /* valid if last 2 refs are owned by this call to unref and the toggle_ref */ gboolean has_toggle_ref = OBJECT_HAS_TOGGLE_REF (object); - if (!g_atomic_int_compare_and_exchange ((int *)&object->ref_count, old_ref, old_ref - 1)) + if (!g_atomic_int_compare_and_exchange_full ((int *)&object->ref_count, + old_ref, old_ref - 1, + &old_ref)) goto retry_atomic_decrement2; /* emit all notifications that have been queued during dispose() */