X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgthread.c;h=72ffcb087ef51b5de69decf1004b3865bd46ac09;hb=e4f8f3b95c2a3b4188a38378bd30b548dba505c2;hp=9505b1593e9373b32d8a1217dff66003ba7cd554;hpb=dafdffd7516324a67db519372e9dcfddfd4fdeb0;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gthread.c b/glib/gthread.c index 9505b15..72ffcb0 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -40,34 +40,14 @@ #include -#include "galias.h" #include "glib.h" -#include "gthreadinit.h" - -#if GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P -# define g_system_thread_equal_simple(thread1, thread2) \ - ((thread1).dummy_pointer == (thread2).dummy_pointer) -# define g_system_thread_assign(dest, src) \ - ((dest).dummy_pointer = (src).dummy_pointer) -#else /* GLIB_SIZEOF_SYSTEM_THREAD != SIZEOF_VOID_P */ -# define g_system_thread_equal_simple(thread1, thread2) \ - (memcmp (&(thread1), &(thread2), GLIB_SIZEOF_SYSTEM_THREAD) == 0) -# define g_system_thread_assign(dest, src) \ - (memcpy (&(dest), &(src), GLIB_SIZEOF_SYSTEM_THREAD)) -#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */ - -#define g_system_thread_equal(thread1, thread2) \ - (g_thread_functions_for_glib_use.thread_equal ? \ - g_thread_functions_for_glib_use.thread_equal (&(thread1), &(thread2)) :\ - g_system_thread_equal_simple((thread1), (thread2))) +#include "gthreadprivate.h" +#include "galias.h" GQuark g_thread_error_quark (void) { - static GQuark quark; - if (!quark) - quark = g_quark_from_static_string ("g_thread_error"); - return quark; + return g_quark_from_static_string ("g_thread_error"); } /* Keep this in sync with GRealThread in gmain.c! */ @@ -76,6 +56,7 @@ struct _GRealThread { GThread thread; gpointer private_data; + GRealThread *next; gpointer retval; GSystemThread system_thread; }; @@ -126,7 +107,7 @@ GThreadFunctions g_thread_functions_for_glib_use = { static GMutex *g_once_mutex = NULL; static GCond *g_once_cond = NULL; static GPrivate *g_thread_specific_private = NULL; -static GSList *g_thread_all_threads = NULL; +static GRealThread *g_thread_all_threads = NULL; static GSList *g_thread_free_indeces = NULL; G_LOCK_DEFINE_STATIC (g_thread); @@ -143,25 +124,34 @@ g_thread_init_glib (void) */ GRealThread* main_thread = (GRealThread*) g_thread_self (); + /* mutex and cond creation works without g_threads_got_initialized */ g_once_mutex = g_mutex_new (); g_once_cond = g_cond_new (); - _g_convert_thread_init (); - _g_rand_thread_init (); - _g_main_thread_init (); - _g_mem_thread_init (); - _g_messages_thread_init (); - _g_atomic_thread_init (); - - g_threads_got_initialized = TRUE; + /* we may only create mutex and cond in here */ + _g_mem_thread_init_noprivate_nomessage (); + /* setup the basic threading system */ + g_threads_got_initialized = TRUE; g_thread_specific_private = g_private_new (g_thread_cleanup); g_private_set (g_thread_specific_private, main_thread); G_THREAD_UF (thread_self, (&main_thread->system_thread)); - _g_mem_thread_private_init (); - _g_messages_thread_private_init (); + /* complete memory system initialization, g_private_*() works now */ + _g_slice_thread_init_nomessage (); + /* accomplish log system initialization to enable messaging */ + _g_messages_thread_init_nomessage (); + + /* we may run full-fledged initializers from here */ + _g_convert_thread_init (); + _g_rand_thread_init (); + _g_main_thread_init (); + _g_atomic_thread_init (); + _g_utils_thread_init (); +#ifdef G_OS_WIN32 + _g_win32_thread_init (); +#endif } #endif /* G_THREADS_ENABLED */ @@ -195,7 +185,7 @@ g_once_impl (GOnce *once, void g_static_mutex_init (GStaticMutex *mutex) { - static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT; + static const GStaticMutex init_mutex = G_STATIC_MUTEX_INIT; g_return_if_fail (mutex); @@ -249,7 +239,7 @@ g_static_mutex_free (GStaticMutex* mutex) void g_static_rec_mutex_init (GStaticRecMutex *mutex) { - static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT; + static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT; g_return_if_fail (mutex); @@ -331,6 +321,9 @@ g_static_rec_mutex_lock_full (GStaticRecMutex *mutex, if (!g_thread_supported ()) return; + if (depth == 0) + return; + G_THREAD_UF (thread_self, (&self)); if (g_system_thread_equal (self, mutex->owner)) @@ -458,7 +451,7 @@ void g_static_private_free (GStaticPrivate *private_key) { guint index = private_key->index; - GSList *list; + GRealThread *thread; if (!index) return; @@ -466,12 +459,12 @@ g_static_private_free (GStaticPrivate *private_key) private_key->index = 0; G_LOCK (g_thread); - list = g_thread_all_threads; - while (list) + + thread = g_thread_all_threads; + while (thread) { - GRealThread *thread = list->data; GArray *array = thread->private_data; - list = list->next; + thread = thread->next; if (array && index <= array->len) { @@ -522,8 +515,20 @@ g_thread_cleanup (gpointer data) it is, the structure is freed in g_thread_join */ if (!thread->thread.joinable) { + GRealThread *t, *p; + G_LOCK (g_thread); - g_thread_all_threads = g_slist_remove (g_thread_all_threads, data); + for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next) + { + if (t == thread) + { + if (p) + p->next = t->next; + else + g_thread_all_threads = t->next; + break; + } + } G_UNLOCK (g_thread); /* Just to make sure, this isn't used any more */ @@ -574,7 +579,7 @@ g_thread_create_full (GThreadFunc func, g_return_val_if_fail (priority >= G_THREAD_PRIORITY_LOW, NULL); g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL); - result = g_new (GRealThread, 1); + result = g_new0 (GRealThread, 1); result->thread.joinable = joinable; result->thread.priority = priority; @@ -585,7 +590,8 @@ g_thread_create_full (GThreadFunc func, G_THREAD_UF (thread_create, (g_thread_create_proxy, result, stack_size, joinable, bound, priority, &result->system_thread, &local_error)); - g_thread_all_threads = g_slist_prepend (g_thread_all_threads, result); + result->next = g_thread_all_threads; + g_thread_all_threads = result; G_UNLOCK (g_thread); if (local_error) @@ -610,6 +616,7 @@ gpointer g_thread_join (GThread* thread) { GRealThread* real = (GRealThread*) thread; + GRealThread *p, *t; gpointer retval; g_return_val_if_fail (thread, NULL); @@ -622,7 +629,17 @@ g_thread_join (GThread* thread) retval = real->retval; G_LOCK (g_thread); - g_thread_all_threads = g_slist_remove (g_thread_all_threads, thread); + for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next) + { + if (t == (GRealThread*) thread) + { + if (p) + p->next = t->next; + else + g_thread_all_threads = t->next; + break; + } + } G_UNLOCK (g_thread); /* Just to make sure, this isn't used any more */ @@ -665,7 +682,7 @@ g_thread_self (void) /* If no thread data is available, provide and set one. This can happen for the main thread and for threads, that are not created by GLib. */ - thread = g_new (GRealThread, 1); + thread = g_new0 (GRealThread, 1); thread->thread.joinable = FALSE; /* This is a save guess */ thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is just a guess */ @@ -679,7 +696,8 @@ g_thread_self (void) g_private_set (g_thread_specific_private, thread); G_LOCK (g_thread); - g_thread_all_threads = g_slist_prepend (g_thread_all_threads, thread); + thread->next = g_thread_all_threads; + g_thread_all_threads = thread; G_UNLOCK (g_thread); } @@ -689,14 +707,14 @@ g_thread_self (void) void g_static_rw_lock_init (GStaticRWLock* lock) { - static GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT; + static const GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT; g_return_if_fail (lock); *lock = init_lock; } -static void inline +inline static void g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex) { if (!*cond) @@ -704,7 +722,7 @@ g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex) g_cond_wait (*cond, g_static_mutex_get_mutex (mutex)); } -static void inline +inline static void g_static_rw_lock_signal (GStaticRWLock* lock) { if (lock->want_to_write && lock->write_cond) @@ -833,3 +851,52 @@ g_static_rw_lock_free (GStaticRWLock* lock) } g_static_mutex_free (&lock->mutex); } + +/** + * g_thread_foreach + * @thread_func: function to call for all GThread structures + * @user_data: second argument to @thread_func + * + * Call @thread_func on all existing #GThread structures. Note that + * threads may decide to exit while @thread_func is running, so + * without intimate knowledge about the lifetime of foreign threads, + * @thread_func shouldn't access the GThread* pointer passed in as + * first argument. However, @thread_func will not be called for threads + * which are known to have exited already. + * + * Due to thread lifetime checks, this function has an execution complexity + * which is quadratic in the number of existing threads. + * + * Since: 2.10 + */ +void +g_thread_foreach (GFunc thread_func, + gpointer user_data) +{ + GSList *slist = NULL; + GRealThread *thread; + g_return_if_fail (thread_func != NULL); + /* snapshot the list of threads for iteration */ + G_LOCK (g_thread); + for (thread = g_thread_all_threads; thread; thread = thread->next) + slist = g_slist_prepend (slist, thread); + G_UNLOCK (g_thread); + /* walk the list, skipping non-existant threads */ + while (slist) + { + GSList *node = slist; + slist = node->next; + /* check whether the current thread still exists */ + G_LOCK (g_thread); + for (thread = g_thread_all_threads; thread; thread = thread->next) + if (thread == node->data) + break; + G_UNLOCK (g_thread); + if (thread) + thread_func (thread, user_data); + g_slist_free_1 (node); + } +} + +#define __G_THREAD_C__ +#include "galiasdef.c"