From fe0f325777257b9266955bc4e091c9deea327a39 Mon Sep 17 00:00:00 2001 From: Sebastian Wilhelmi Date: Tue, 28 Nov 2000 12:56:57 +0000 Subject: [PATCH] Revamped errorcheck mutexes and added errorcheck cond_wait() and 2000-11-28 Sebastian Wilhelmi * gthread-impl.c: Revamped errorcheck mutexes and added errorcheck cond_wait() and cond_timed_wait() funtions. This makes he whole thing work. Now we only show the location of the locking/unlocking for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. * gthread.c: Set the thread data before locking the mutex, because the locking call might use g_thread_self (). * gthread.h: Do only show the location of the locking/unlocking for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the errorcheck capability for g_cond_wait and g_cond_timed_wait as well. --- ChangeLog | 10 +++ ChangeLog.pre-2-0 | 10 +++ ChangeLog.pre-2-10 | 10 +++ ChangeLog.pre-2-12 | 10 +++ ChangeLog.pre-2-2 | 10 +++ ChangeLog.pre-2-4 | 10 +++ ChangeLog.pre-2-6 | 10 +++ ChangeLog.pre-2-8 | 10 +++ glib/gthread.c | 9 +-- glib/gthread.h | 77 +++++++++++---------- gthread.c | 9 +-- gthread.h | 77 +++++++++++---------- gthread/ChangeLog | 7 ++ gthread/gthread-impl.c | 150 +++++++++++++++++++++++++++++------------ 14 files changed, 287 insertions(+), 122 deletions(-) diff --git a/ChangeLog b/ChangeLog index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 491ea7d2b..265d42d2b 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,13 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread.c: Set the thread data before locking the mutex, because + the locking call might use g_thread_self (). + + * gthread.h: Do only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. Add the + errorcheck capability for g_cond_wait and g_cond_timed_wait as + well. + 2000-11-27 Havoc Pennington * gthread.h: Add void in empty function arg list diff --git a/glib/gthread.c b/glib/gthread.c index 7151b7539..479ef9c74 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -391,11 +391,12 @@ g_thread_create_proxy (gpointer data) g_assert (data); - /* the lock makes sure, that thread->system_thread is written, - before thread->func is called. See g_thread_create */ - - G_LOCK (g_thread_create); + /* This has to happen before G_LOCK, as that might call g_thread_self */ g_private_set (g_thread_specific_private, data); + + /* the lock makes sure, that thread->system_thread is written, + before thread->func is called. See g_thread_create. */ + G_LOCK (g_thread_create); G_UNLOCK (g_thread_create); thread->func (thread->arg); diff --git a/glib/gthread.h b/glib/gthread.h index 733600f43..e99c78d5e 100644 --- a/glib/gthread.h +++ b/glib/gthread.h @@ -129,7 +129,7 @@ void g_thread_init (GThreadFunctions *vtable); * mutexes will check for re-locking and re-unlocking */ /* Initialize thread system with errorcheck mutexes. vtable must be - * NULL.Do not call directly. Use #define G_ERRORCHECK_MUTEXES + * NULL. Do not call directly. Use #define G_ERRORCHECK_MUTEXES * instead. */ void g_thread_init_with_errorcheck_mutexes (GThreadFunctions* vtable); @@ -145,51 +145,56 @@ void g_thread_init_with_errorcheck_mutexes (GThreadFunctions* vtable); GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex); /* shorthands for conditional and unconditional function calls */ -#define G_THREAD_UF(op, arglist) \ + +#define G_THREAD_UF(op, arglist) \ (*g_thread_functions_for_glib_use . op) arglist -#define G_THREAD_CF(op, fail, arg) \ +#define G_THREAD_CF(op, fail, arg) \ (g_thread_supported () ? G_THREAD_UF (op, arg) : (fail)) -#define G_THREAD_ECF(op, fail, mutex, name, type) \ - (g_thread_supported () ? \ - ((type(*)(GMutex*, gulong, gchar*, gchar*)) \ - (*g_thread_functions_for_glib_use . op)) \ - (mutex, G_MUTEX_DEBUG_MAGIC, G_STRINGIFY (name), G_STRLOC) : (fail)) +#define G_THREAD_ECF(op, fail, mutex, type) \ + (g_thread_supported () ? ((type(*)(GMutex*, gulong, gchar*)) \ + (*g_thread_functions_for_glib_use . op)) \ + (mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (fail)) + #ifndef G_ERRORCHECK_MUTEXES -#define g_mutex_lock_with_debug_name(mutex, name) \ - G_THREAD_CF (mutex_lock, (void)0, (mutex)) -#define g_mutex_trylock_with_debug_name(mutex, name) \ - G_THREAD_CF (mutex_trylock, TRUE, (mutex)) -#define g_mutex_unlock_with_debug_name(mutex, name) \ - G_THREAD_CF (mutex_unlock, (void)0, (mutex)) +# define g_mutex_lock(mutex) \ + G_THREAD_CF (mutex_lock, (void)0, (mutex)) +# define g_mutex_trylock(mutex) \ + G_THREAD_CF (mutex_trylock, TRUE, (mutex)) +# define g_mutex_unlock(mutex) \ + G_THREAD_CF (mutex_unlock, (void)0, (mutex)) +# define g_cond_wait(cond, mutex) \ + G_THREAD_CF (cond_wait, (void)0, (cond, mutex)) +# define g_cond_timed_wait(cond, mutex, abs_time) \ + G_THREAD_CF (cond_timed_wait, TRUE, (cond, mutex, abs_time)) #else /* G_ERRORCHECK_MUTEXES */ -#define g_mutex_lock_with_debug_name(mutex, name) \ - G_THREAD_ECF (mutex_lock, (void)0, mutex, name, void) -#define g_mutex_trylock_with_debug_name(mutex, name) \ - G_THREAD_ECF (mutex_trylock, TRUE, mutex, name, gboolean) -#define g_mutex_unlock_with_debug_name(mutex, name) \ - G_THREAD_ECF (mutex_unlock, (void)0, mutex, name, void) +# define g_mutex_lock(mutex) \ + G_THREAD_ECF (mutex_lock, (void)0, mutex, void) +# define g_mutex_trylock(mutex) \ + G_THREAD_ECF (mutex_trylock, TRUE, mutex, gboolean) +# define g_mutex_unlock(mutex) \ + G_THREAD_ECF (mutex_unlock, (void)0, mutex, void) +# define g_cond_wait(cond, mutex) \ + (g_thread_supported () ? ((void(*)(GCond*, GMutex*, gulong, gchar*))\ + g_thread_functions_for_glib_use.cond_wait) \ + (cond, mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (void) 0) +# define g_cond_timed_wait(cond, mutex, abs_time) \ + (g_thread_supported () ? \ + ((gboolean(*)(GCond*, GMutex*, GTimeVal*, gulong, gchar*)) \ + g_thread_functions_for_glib_use.cond_timed_wait) \ + (cond, mutex, abs_time, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : TRUE) #endif /* G_ERRORCHECK_MUTEXES */ #define g_thread_supported() (g_threads_got_initialized) #define g_mutex_new() G_THREAD_UF (mutex_new, ()) -#define g_mutex_lock(mutex) g_mutex_lock_with_debug_name(mutex, mutex) -#define g_mutex_trylock(mutex) g_mutex_trylock_with_debug_name(mutex, mutex) -#define g_mutex_unlock(mutex) g_mutex_unlock_with_debug_name(mutex, mutex) #define g_mutex_free(mutex) G_THREAD_CF (mutex_free, (void)0, (mutex)) #define g_cond_new() G_THREAD_UF (cond_new, ()) #define g_cond_signal(cond) G_THREAD_CF (cond_signal, (void)0, (cond)) #define g_cond_broadcast(cond) G_THREAD_CF (cond_broadcast, (void)0, (cond)) -#define g_cond_wait(cond, mutex) G_THREAD_CF (cond_wait, (void)0, (cond, \ - mutex)) #define g_cond_free(cond) G_THREAD_CF (cond_free, (void)0, (cond)) -#define g_cond_timed_wait(cond, mutex, abs_time) G_THREAD_CF (cond_timed_wait, \ - TRUE, \ - (cond, mutex, \ - abs_time)) -#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor)) -#define g_private_get(private_key) G_THREAD_CF (private_get, \ - ((gpointer)private_key), \ - (private_key)) +#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor)) +#define g_private_get(private_key) G_THREAD_CF (private_get, \ + ((gpointer)private_key), \ + (private_key)) #define g_private_set(private_key, value) G_THREAD_CF (private_set, \ (void) (private_key = \ (GPrivate*) (value)), \ @@ -215,11 +220,11 @@ void g_thread_set_priority (GThread *thread, * use */ #define g_static_mutex_lock(mutex) \ - g_mutex_lock_with_debug_name (g_static_mutex_get_mutex (mutex), mutex) + g_mutex_lock (g_static_mutex_get_mutex (mutex)) #define g_static_mutex_trylock(mutex) \ - g_mutex_trylock_with_debug_name (g_static_mutex_get_mutex (mutex), mutex) + g_mutex_trylock (g_static_mutex_get_mutex (mutex)) #define g_static_mutex_unlock(mutex) \ - g_mutex_unlock_with_debug_name (g_static_mutex_get_mutex (mutex), mutex) + g_mutex_unlock (g_static_mutex_get_mutex (mutex)) struct _GStaticPrivate { diff --git a/gthread.c b/gthread.c index 7151b7539..479ef9c74 100644 --- a/gthread.c +++ b/gthread.c @@ -391,11 +391,12 @@ g_thread_create_proxy (gpointer data) g_assert (data); - /* the lock makes sure, that thread->system_thread is written, - before thread->func is called. See g_thread_create */ - - G_LOCK (g_thread_create); + /* This has to happen before G_LOCK, as that might call g_thread_self */ g_private_set (g_thread_specific_private, data); + + /* the lock makes sure, that thread->system_thread is written, + before thread->func is called. See g_thread_create. */ + G_LOCK (g_thread_create); G_UNLOCK (g_thread_create); thread->func (thread->arg); diff --git a/gthread.h b/gthread.h index 733600f43..e99c78d5e 100644 --- a/gthread.h +++ b/gthread.h @@ -129,7 +129,7 @@ void g_thread_init (GThreadFunctions *vtable); * mutexes will check for re-locking and re-unlocking */ /* Initialize thread system with errorcheck mutexes. vtable must be - * NULL.Do not call directly. Use #define G_ERRORCHECK_MUTEXES + * NULL. Do not call directly. Use #define G_ERRORCHECK_MUTEXES * instead. */ void g_thread_init_with_errorcheck_mutexes (GThreadFunctions* vtable); @@ -145,51 +145,56 @@ void g_thread_init_with_errorcheck_mutexes (GThreadFunctions* vtable); GMutex* g_static_mutex_get_mutex_impl (GMutex **mutex); /* shorthands for conditional and unconditional function calls */ -#define G_THREAD_UF(op, arglist) \ + +#define G_THREAD_UF(op, arglist) \ (*g_thread_functions_for_glib_use . op) arglist -#define G_THREAD_CF(op, fail, arg) \ +#define G_THREAD_CF(op, fail, arg) \ (g_thread_supported () ? G_THREAD_UF (op, arg) : (fail)) -#define G_THREAD_ECF(op, fail, mutex, name, type) \ - (g_thread_supported () ? \ - ((type(*)(GMutex*, gulong, gchar*, gchar*)) \ - (*g_thread_functions_for_glib_use . op)) \ - (mutex, G_MUTEX_DEBUG_MAGIC, G_STRINGIFY (name), G_STRLOC) : (fail)) +#define G_THREAD_ECF(op, fail, mutex, type) \ + (g_thread_supported () ? ((type(*)(GMutex*, gulong, gchar*)) \ + (*g_thread_functions_for_glib_use . op)) \ + (mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (fail)) + #ifndef G_ERRORCHECK_MUTEXES -#define g_mutex_lock_with_debug_name(mutex, name) \ - G_THREAD_CF (mutex_lock, (void)0, (mutex)) -#define g_mutex_trylock_with_debug_name(mutex, name) \ - G_THREAD_CF (mutex_trylock, TRUE, (mutex)) -#define g_mutex_unlock_with_debug_name(mutex, name) \ - G_THREAD_CF (mutex_unlock, (void)0, (mutex)) +# define g_mutex_lock(mutex) \ + G_THREAD_CF (mutex_lock, (void)0, (mutex)) +# define g_mutex_trylock(mutex) \ + G_THREAD_CF (mutex_trylock, TRUE, (mutex)) +# define g_mutex_unlock(mutex) \ + G_THREAD_CF (mutex_unlock, (void)0, (mutex)) +# define g_cond_wait(cond, mutex) \ + G_THREAD_CF (cond_wait, (void)0, (cond, mutex)) +# define g_cond_timed_wait(cond, mutex, abs_time) \ + G_THREAD_CF (cond_timed_wait, TRUE, (cond, mutex, abs_time)) #else /* G_ERRORCHECK_MUTEXES */ -#define g_mutex_lock_with_debug_name(mutex, name) \ - G_THREAD_ECF (mutex_lock, (void)0, mutex, name, void) -#define g_mutex_trylock_with_debug_name(mutex, name) \ - G_THREAD_ECF (mutex_trylock, TRUE, mutex, name, gboolean) -#define g_mutex_unlock_with_debug_name(mutex, name) \ - G_THREAD_ECF (mutex_unlock, (void)0, mutex, name, void) +# define g_mutex_lock(mutex) \ + G_THREAD_ECF (mutex_lock, (void)0, mutex, void) +# define g_mutex_trylock(mutex) \ + G_THREAD_ECF (mutex_trylock, TRUE, mutex, gboolean) +# define g_mutex_unlock(mutex) \ + G_THREAD_ECF (mutex_unlock, (void)0, mutex, void) +# define g_cond_wait(cond, mutex) \ + (g_thread_supported () ? ((void(*)(GCond*, GMutex*, gulong, gchar*))\ + g_thread_functions_for_glib_use.cond_wait) \ + (cond, mutex, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : (void) 0) +# define g_cond_timed_wait(cond, mutex, abs_time) \ + (g_thread_supported () ? \ + ((gboolean(*)(GCond*, GMutex*, GTimeVal*, gulong, gchar*)) \ + g_thread_functions_for_glib_use.cond_timed_wait) \ + (cond, mutex, abs_time, G_MUTEX_DEBUG_MAGIC, G_STRLOC) : TRUE) #endif /* G_ERRORCHECK_MUTEXES */ #define g_thread_supported() (g_threads_got_initialized) #define g_mutex_new() G_THREAD_UF (mutex_new, ()) -#define g_mutex_lock(mutex) g_mutex_lock_with_debug_name(mutex, mutex) -#define g_mutex_trylock(mutex) g_mutex_trylock_with_debug_name(mutex, mutex) -#define g_mutex_unlock(mutex) g_mutex_unlock_with_debug_name(mutex, mutex) #define g_mutex_free(mutex) G_THREAD_CF (mutex_free, (void)0, (mutex)) #define g_cond_new() G_THREAD_UF (cond_new, ()) #define g_cond_signal(cond) G_THREAD_CF (cond_signal, (void)0, (cond)) #define g_cond_broadcast(cond) G_THREAD_CF (cond_broadcast, (void)0, (cond)) -#define g_cond_wait(cond, mutex) G_THREAD_CF (cond_wait, (void)0, (cond, \ - mutex)) #define g_cond_free(cond) G_THREAD_CF (cond_free, (void)0, (cond)) -#define g_cond_timed_wait(cond, mutex, abs_time) G_THREAD_CF (cond_timed_wait, \ - TRUE, \ - (cond, mutex, \ - abs_time)) -#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor)) -#define g_private_get(private_key) G_THREAD_CF (private_get, \ - ((gpointer)private_key), \ - (private_key)) +#define g_private_new(destructor) G_THREAD_UF (private_new, (destructor)) +#define g_private_get(private_key) G_THREAD_CF (private_get, \ + ((gpointer)private_key), \ + (private_key)) #define g_private_set(private_key, value) G_THREAD_CF (private_set, \ (void) (private_key = \ (GPrivate*) (value)), \ @@ -215,11 +220,11 @@ void g_thread_set_priority (GThread *thread, * use */ #define g_static_mutex_lock(mutex) \ - g_mutex_lock_with_debug_name (g_static_mutex_get_mutex (mutex), mutex) + g_mutex_lock (g_static_mutex_get_mutex (mutex)) #define g_static_mutex_trylock(mutex) \ - g_mutex_trylock_with_debug_name (g_static_mutex_get_mutex (mutex), mutex) + g_mutex_trylock (g_static_mutex_get_mutex (mutex)) #define g_static_mutex_unlock(mutex) \ - g_mutex_unlock_with_debug_name (g_static_mutex_get_mutex (mutex), mutex) + g_mutex_unlock (g_static_mutex_get_mutex (mutex)) struct _GStaticPrivate { diff --git a/gthread/ChangeLog b/gthread/ChangeLog index 2a2650912..0d33faec5 100644 --- a/gthread/ChangeLog +++ b/gthread/ChangeLog @@ -1,3 +1,10 @@ +2000-11-28 Sebastian Wilhelmi + + * gthread-impl.c: Revamped errorcheck mutexes and added errorcheck + cond_wait() and cond_timed_wait() funtions. This makes he whole + thing work. Now we only show the location of the locking/unlocking + for -DG_ERRORCHECK_MUTEXES and not the name of the mutex. + 2000-11-21 Sebastian Wilhelmi * gthread-impl.c, gthread-posix.c, gthread-solaris.c: Removed diff --git a/gthread/gthread-impl.c b/gthread/gthread-impl.c index 61668cdb4..c8f01d09c 100644 --- a/gthread/gthread-impl.c +++ b/gthread/gthread-impl.c @@ -69,7 +69,6 @@ void g_messages_init (void); typedef struct _ErrorCheckInfo ErrorCheckInfo; struct _ErrorCheckInfo { - gchar *name; gchar *location; GThread *owner; }; @@ -83,42 +82,26 @@ g_mutex_new_errorcheck_impl (void) return retval; } -static inline void -fill_info (ErrorCheckInfo *info, - GThread *self, - gulong magic, - gchar *name, - gchar *location) -{ - info->owner = self; - if (magic == G_MUTEX_DEBUG_MAGIC) - { - /* We are used with special instrumented calls, where name and - * location is provided as well, so use them */ - info->name = name; - info->location = location; - } - else - info->name = info->location = "unknown"; -} - static void g_mutex_lock_errorcheck_impl (GMutex *mutex, - gulong magic, - gchar *name, + gulong magic, gchar *location) { ErrorCheckInfo *info; GThread *self = g_thread_self (); + + if (magic != G_MUTEX_DEBUG_MAGIC) + location = "unknown"; + if (G_MUTEX_DEBUG_INFO (mutex) == NULL) { /* if the debug info is NULL, we have not yet locked that mutex, * so we do it now */ g_thread_functions_for_glib_use_default.mutex_lock (mutex); - /* Now we have to check again, because anothe thread might mave - * locked the mutex at the same time, we did. This technique is - * not 100% save on systems without decent cache coherence, - * but we have no choice */ + /* Now we have to check again, because another thread might have + * tried to lock the mutex at the same time we did. This + * technique is not 100% save on systems without decent cache + * coherence, but we have no choice */ if (G_MUTEX_DEBUG_INFO (mutex) == NULL) { info = G_MUTEX_DEBUG_INFO (mutex) = g_new0 (ErrorCheckInfo, 1); @@ -128,56 +111,70 @@ g_mutex_lock_errorcheck_impl (GMutex *mutex, info = G_MUTEX_DEBUG_INFO (mutex); if (info->owner == self) - g_error ("Trying to recursivly lock the mutex '%s' at '%s', " - "previously locked by name '%s' at '%s'", - name, location, info->name, info->location); + g_error ("Trying to recursivly lock a mutex at '%s', " + "previously locked at '%s'", + location, info->location); g_thread_functions_for_glib_use_default.mutex_lock (mutex); - fill_info (info, self, magic, name, location); + info->owner = self; + info->location = location; } static gboolean g_mutex_trylock_errorcheck_impl (GMutex *mutex, gulong magic, - gchar *name, gchar *location) { ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); GThread *self = g_thread_self (); + + if (magic != G_MUTEX_DEBUG_MAGIC) + location = "unknown"; + if (!info) { /* This mutex has not yet been used, so simply lock and return TRUE */ - g_mutex_lock_errorcheck_impl (mutex, magic, name, location); + g_mutex_lock_errorcheck_impl (mutex, magic, location); return TRUE; } + if (info->owner == self) - g_error ("Trying to recursivly lock the mutex '%s' at '%s', " - "previously locked by name '%s' at '%s'", - name, location, info->name, info->location); + g_error ("Trying to recursivly lock a mutex at '%s', " + "previously locked at '%s'", + location, info->location); if (!g_thread_functions_for_glib_use_default.mutex_trylock (mutex)) return FALSE; - fill_info (info, self, magic, name, location); + info->owner = self; + info->location = location; + return TRUE; } static void g_mutex_unlock_errorcheck_impl (GMutex *mutex, gulong magic, - gchar *name, gchar *location) { ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); GThread *self = g_thread_self (); + if (magic != G_MUTEX_DEBUG_MAGIC) - name = location = "unknown"; - if (!info || info->owner != self) - g_error ("Trying to unlock the unlocked mutex '%s' at '%s'", - name, location); + location = "unknown"; + + if (!info || info->owner == NULL) + g_error ("Trying to unlock an unlocked mutex at '%s'", location); + + if (info->owner != self) + g_warning ("Trying to unlock a mutex at '%s', " + "previously locked by a different thread at '%s'", + location, info->location); + info->owner = NULL; - info->name = info->location = NULL; + info->location = NULL; + g_thread_functions_for_glib_use_default.mutex_unlock (mutex); } @@ -188,6 +185,73 @@ g_mutex_free_errorcheck_impl (GMutex *mutex) g_thread_functions_for_glib_use_default.mutex_free (mutex); } +static void +g_cond_wait_errorcheck_impl (GCond *cond, + GMutex *mutex, + gulong magic, + gchar *location) +{ + + ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); + GThread *self = g_thread_self (); + + if (magic != G_MUTEX_DEBUG_MAGIC) + location = "unknown"; + + if (!info || info->owner == NULL) + g_error ("Trying to use an unlocked mutex in g_cond_wait() at '%s'", + location); + + if (info->owner != self) + g_error ("Trying to use a mutex locked by another thread in " + "g_cond_wait() at '%s'", location); + + info->owner = NULL; + location = info->location; + + g_thread_functions_for_glib_use_default.cond_wait (cond, mutex); + + info->owner = self; + info->location = location; +} + + +static gboolean +g_cond_timed_wait_errorcheck_impl (GCond *cond, + GMutex *mutex, + GTimeVal *end_time, + gulong magic, + gchar *location) +{ + ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); + GThread *self = g_thread_self (); + gboolean retval; + + if (magic != G_MUTEX_DEBUG_MAGIC) + location = "unknown"; + + if (!info || info->owner == NULL) + g_error ("Trying to use an unlocked mutex in g_cond_timed_wait() at '%s'", + location); + + if (info->owner != self) + g_error ("Trying to use a mutex locked by another thread in " + "g_cond_timed_wait() at '%s'", location); + + info->owner = NULL; + location = info->location; + + retval = g_thread_functions_for_glib_use_default.cond_timed_wait (cond, + mutex, + end_time); + + info->owner = self; + info->location = location; + + return retval; +} + + /* unshadow function declaration. See glib.h */ #undef g_thread_init @@ -207,6 +271,8 @@ g_thread_init_with_errorcheck_mutexes (GThreadFunctions* init) errorcheck_functions.mutex_unlock = (void (*)(GMutex *)) g_mutex_unlock_errorcheck_impl; errorcheck_functions.mutex_free = g_mutex_free_errorcheck_impl; + errorcheck_functions.cond_wait = g_cond_wait_errorcheck_impl; + errorcheck_functions.cond_timed_wait = g_cond_timed_wait_errorcheck_impl; g_thread_init (&errorcheck_functions); }