prevent race covered by g_once_init_enter(), by checking for previous

Tue Aug 14 02:06:10 2007  Tim Janik  <timj@imendio.com>

        * glib/gthread.c (g_once_init_enter_impl): prevent race covered
        by g_once_init_enter(), by checking for previous initializations
        before entering initialisation branch.

        * tests/onceinit.c: added multi-thread/multi-initializer stress test
        using unoptimized g_once_init_enter_impl().



svn path=/trunk/; revision=5701
This commit is contained in:
Tim Janik
2007-08-14 00:05:52 +00:00
committed by Tim Janik
parent db68b8efa9
commit d5c4370813
4 changed files with 155 additions and 15 deletions

View File

@@ -202,18 +202,19 @@ g_once_impl (GOnce *once,
gboolean
g_once_init_enter_impl (volatile gsize *value_location)
{
gboolean need_init;
gboolean need_init = FALSE;
g_mutex_lock (g_once_mutex);
if (!g_once_init_list || !g_slist_find (g_once_init_list, (void*) value_location))
if (g_atomic_pointer_get ((void**) value_location) == 0)
{
g_once_init_list = g_slist_prepend (g_once_init_list, (void*) value_location);
need_init = TRUE;
}
else
{
while (g_slist_find (g_once_init_list, (void*) value_location))
g_cond_wait (g_once_cond, g_once_mutex);
need_init = FALSE;
if (!g_slist_find (g_once_init_list, (void*) value_location))
{
need_init = TRUE;
g_once_init_list = g_slist_prepend (g_once_init_list, (void*) value_location);
}
else
do
g_cond_wait (g_once_cond, g_once_mutex);
while (g_slist_find (g_once_init_list, (void*) value_location));
}
g_mutex_unlock (g_once_mutex);
return need_init;