summaryrefslogtreecommitdiff
path: root/glib
diff options
context:
space:
mode:
authorTim Janik <timj@imendio.com>2007-08-14 00:05:52 +0000
committerTim Janik <timj@src.gnome.org>2007-08-14 00:05:52 +0000
commitd5c437081366ba9617c9a23a09d167aede52a8b9 (patch)
tree902d15f49200c90cb1e64adbb874efae80b5eaae /glib
parentdb68b8efa9b6aff53a640d82a0bf7ed6f819c4f0 (diff)
downloadglib-d5c437081366ba9617c9a23a09d167aede52a8b9.tar.gz
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
Diffstat (limited to 'glib')
-rw-r--r--glib/gthread.c21
-rw-r--r--glib/gthread.h2
2 files changed, 12 insertions, 11 deletions
diff --git a/glib/gthread.c b/glib/gthread.c
index 5468e596f..fdff396ea 100644
--- a/glib/gthread.c
+++ b/glib/gthread.c
@@ -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;
diff --git a/glib/gthread.h b/glib/gthread.h
index 3aaf14ecb..ea801fb76 100644
--- a/glib/gthread.h
+++ b/glib/gthread.h
@@ -332,7 +332,7 @@ void g_once_init_leave (volatile gsize *value_location,
G_INLINE_FUNC gboolean
g_once_init_enter (volatile gsize *value_location)
{
- if G_LIKELY (g_atomic_pointer_get ((void**) value_location) !=0)
+ if G_LIKELY (g_atomic_pointer_get ((void**) value_location) != 0)
return FALSE;
else
return g_once_init_enter_impl (value_location);