mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-21 08:28:53 +02:00
Make ClassData->init_state atomic
This is necessary to make g_type_class_ref() lockless. https://bugzilla.gnome.org/show_bug.cgi?id=585375 Also includes fix for: https://bugzilla.gnome.org/show_bug.cgi?id=587892
This commit is contained in:
committed by
Alexander Larsson
parent
4c243b1cba
commit
00a4470ad0
@@ -313,7 +313,7 @@ struct _ClassData
|
|||||||
{
|
{
|
||||||
CommonData common;
|
CommonData common;
|
||||||
guint16 class_size;
|
guint16 class_size;
|
||||||
guint init_state : 4;
|
int volatile init_state; /* atomic - g_type_class_ref reads it unlocked */
|
||||||
GBaseInitFunc class_init_base;
|
GBaseInitFunc class_init_base;
|
||||||
GBaseFinalizeFunc class_finalize_base;
|
GBaseFinalizeFunc class_finalize_base;
|
||||||
GClassInitFunc class_init;
|
GClassInitFunc class_init;
|
||||||
@@ -326,7 +326,7 @@ struct _InstanceData
|
|||||||
{
|
{
|
||||||
CommonData common;
|
CommonData common;
|
||||||
guint16 class_size;
|
guint16 class_size;
|
||||||
guint init_state : 4;
|
int volatile init_state; /* atomic - g_type_class_ref reads it unlocked */
|
||||||
GBaseInitFunc class_init_base;
|
GBaseInitFunc class_init_base;
|
||||||
GBaseFinalizeFunc class_finalize_base;
|
GBaseFinalizeFunc class_finalize_base;
|
||||||
GClassInitFunc class_init;
|
GClassInitFunc class_init;
|
||||||
@@ -2057,7 +2057,7 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
|
|
||||||
class = g_malloc0 (node->data->class.class_size);
|
class = g_malloc0 (node->data->class.class_size);
|
||||||
node->data->class.class = class;
|
node->data->class.class = class;
|
||||||
node->data->class.init_state = BASE_CLASS_INIT;
|
g_atomic_int_set (&node->data->class.init_state, BASE_CLASS_INIT);
|
||||||
|
|
||||||
if (pclass)
|
if (pclass)
|
||||||
{
|
{
|
||||||
@@ -2094,7 +2094,7 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
|
|
||||||
G_WRITE_LOCK (&type_rw_lock);
|
G_WRITE_LOCK (&type_rw_lock);
|
||||||
|
|
||||||
node->data->class.init_state = BASE_IFACE_INIT;
|
g_atomic_int_set (&node->data->class.init_state, BASE_IFACE_INIT);
|
||||||
|
|
||||||
/* Before we initialize the class, base initialize all interfaces, either
|
/* Before we initialize the class, base initialize all interfaces, either
|
||||||
* from parent, or through our holder info
|
* from parent, or through our holder info
|
||||||
@@ -2150,7 +2150,7 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->data->class.init_state = CLASS_INIT;
|
g_atomic_int_set (&node->data->class.init_state, CLASS_INIT);
|
||||||
|
|
||||||
G_WRITE_UNLOCK (&type_rw_lock);
|
G_WRITE_UNLOCK (&type_rw_lock);
|
||||||
|
|
||||||
@@ -2159,7 +2159,7 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
|
|
||||||
G_WRITE_LOCK (&type_rw_lock);
|
G_WRITE_LOCK (&type_rw_lock);
|
||||||
|
|
||||||
node->data->class.init_state = IFACE_INIT;
|
g_atomic_int_set (&node->data->class.init_state, IFACE_INIT);
|
||||||
|
|
||||||
/* finish initializing the interfaces through our holder info.
|
/* finish initializing the interfaces through our holder info.
|
||||||
* inherited interfaces are already init_state == INITIALIZED, because
|
* inherited interfaces are already init_state == INITIALIZED, because
|
||||||
@@ -2190,7 +2190,7 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->data->class.init_state = INITIALIZED;
|
g_atomic_int_set (&node->data->class.init_state, INITIALIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2821,8 +2821,7 @@ g_type_class_ref (GType type)
|
|||||||
G_WRITE_LOCK (&type_rw_lock);
|
G_WRITE_LOCK (&type_rw_lock);
|
||||||
node = lookup_type_node_I (type);
|
node = lookup_type_node_I (type);
|
||||||
if (node && node->is_classed && node->data &&
|
if (node && node->is_classed && node->data &&
|
||||||
node->data->class.class &&
|
g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
|
||||||
node->data->class.init_state == INITIALIZED)
|
|
||||||
{
|
{
|
||||||
type_data_ref_Wm (node);
|
type_data_ref_Wm (node);
|
||||||
G_WRITE_UNLOCK (&type_rw_lock);
|
G_WRITE_UNLOCK (&type_rw_lock);
|
||||||
@@ -2933,7 +2932,9 @@ g_type_class_peek (GType type)
|
|||||||
|
|
||||||
node = lookup_type_node_I (type);
|
node = lookup_type_node_I (type);
|
||||||
G_READ_LOCK (&type_rw_lock);
|
G_READ_LOCK (&type_rw_lock);
|
||||||
if (node && node->is_classed && node->data && node->data->class.class) /* ref_count _may_ be 0 */
|
if (node && node->is_classed && node->data &&
|
||||||
|
g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
|
||||||
|
/* ref_count _may_ be 0 */
|
||||||
class = node->data->class.class;
|
class = node->data->class.class;
|
||||||
else
|
else
|
||||||
class = NULL;
|
class = NULL;
|
||||||
@@ -2963,7 +2964,8 @@ g_type_class_peek_static (GType type)
|
|||||||
G_READ_LOCK (&type_rw_lock);
|
G_READ_LOCK (&type_rw_lock);
|
||||||
if (node && node->is_classed && node->data &&
|
if (node && node->is_classed && node->data &&
|
||||||
/* peek only static types: */ node->plugin == NULL &&
|
/* peek only static types: */ node->plugin == NULL &&
|
||||||
node->data->class.class) /* ref_count _may_ be 0 */
|
g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
|
||||||
|
/* ref_count _may_ be 0 */
|
||||||
class = node->data->class.class;
|
class = node->data->class.class;
|
||||||
else
|
else
|
||||||
class = NULL;
|
class = NULL;
|
||||||
|
Reference in New Issue
Block a user