From e4f8f3b95c2a3b4188a38378bd30b548dba505c2 Mon Sep 17 00:00:00 2001 From: Sebastian Wilhelmi Date: Wed, 10 May 2006 00:44:50 +0000 Subject: [PATCH] Renamed to glib/gthreadprivate.h and moved system thread identifier 2006-05-09 Sebastian Wilhelmi * glib/gthreadinit.h: Renamed to glib/gthreadprivate.h and moved system thread identifier comparision and assignment macros from glib/gthread.c to glib/gthreadprivate.h. * glib/Makefile.am, glib/gatomic.c, glib/gconvert.c, glib/gmain.c, glib/gmem.c, glib/gmessages.c, glib/grand.c, glib/gslice.c, glib/gthread.c, glib/gutils.c, gthread/gthread-impl.c: Use glib/gthreadprivate.h instead of glib/gthreadinit.h. * gthread/gthread-impl.c: Use GSystemThread instead of GThread for owner determination. This fixes #311043 and is mostly modeled after the patch from jylefort@FreeBSD.org. --- ChangeLog | 15 ++++ ChangeLog.pre-2-12 | 15 ++++ glib/Makefile.am | 2 +- glib/gatomic.c | 2 +- glib/gconvert.c | 2 +- glib/gmain.c | 2 +- glib/gmem.c | 2 +- glib/gmessages.c | 2 +- glib/grand.c | 2 +- glib/gslice.c | 2 +- glib/gthread.c | 19 +---- glib/{gthreadinit.h => gthreadprivate.h} | 35 +++++++-- glib/gutils.c | 2 +- gthread/gthread-impl.c | 57 ++++++++------ tests/.cvsignore | 1 + tests/Makefile.am | 3 +- tests/errorcheck-mutex-test.c | 131 +++++++++++++++++++++++++++++++ 17 files changed, 236 insertions(+), 58 deletions(-) rename glib/{gthreadinit.h => gthreadprivate.h} (57%) create mode 100644 tests/errorcheck-mutex-test.c diff --git a/ChangeLog b/ChangeLog index 37279d0..39e8010 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,20 @@ 2006-05-09 Sebastian Wilhelmi + * glib/gthreadinit.h: Renamed to glib/gthreadprivate.h and moved + system thread identifier comparision and assignment macros from + glib/gthread.c to glib/gthreadprivate.h. + + * glib/Makefile.am, glib/gatomic.c, glib/gconvert.c, glib/gmain.c, + glib/gmem.c, glib/gmessages.c, glib/grand.c, glib/gslice.c, + glib/gthread.c, glib/gutils.c, gthread/gthread-impl.c: Use + glib/gthreadprivate.h instead of glib/gthreadinit.h. + + * gthread/gthread-impl.c: Use GSystemThread instead of GThread for + owner determination. (#311043, jylefort@FreeBSD.org) + + * tests/Makefile.am, tests/errorcheck-mutex-test: New test program + to test for all checked violations. + * glib/gprintf.c, glib/gspawn-win32.c, glib/gutf8.c, gthread/gthread-impl.c, gthread/gthread-posix.c, gthread/gthread-win32.c: Use canonical include form for internal diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 37279d0..39e8010 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,5 +1,20 @@ 2006-05-09 Sebastian Wilhelmi + * glib/gthreadinit.h: Renamed to glib/gthreadprivate.h and moved + system thread identifier comparision and assignment macros from + glib/gthread.c to glib/gthreadprivate.h. + + * glib/Makefile.am, glib/gatomic.c, glib/gconvert.c, glib/gmain.c, + glib/gmem.c, glib/gmessages.c, glib/grand.c, glib/gslice.c, + glib/gthread.c, glib/gutils.c, gthread/gthread-impl.c: Use + glib/gthreadprivate.h instead of glib/gthreadinit.h. + + * gthread/gthread-impl.c: Use GSystemThread instead of GThread for + owner determination. (#311043, jylefort@FreeBSD.org) + + * tests/Makefile.am, tests/errorcheck-mutex-test: New test program + to test for all checked violations. + * glib/gprintf.c, glib/gspawn-win32.c, glib/gutf8.c, gthread/gthread-impl.c, gthread/gthread-posix.c, gthread/gthread-win32.c: Use canonical include form for internal diff --git a/glib/Makefile.am b/glib/Makefile.am index a55f6e6..8cb352b 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -112,7 +112,7 @@ libglib_2_0_la_SOURCES = \ gstrfuncs.c \ gstring.c \ gthread.c \ - gthreadinit.h \ + gthreadprivate.h \ gthreadpool.c \ gtimer.c \ gtree.c \ diff --git a/glib/gatomic.c b/glib/gatomic.c index 8202d05..3e9ee43 100644 --- a/glib/gatomic.c +++ b/glib/gatomic.c @@ -23,7 +23,7 @@ #include "config.h" #include "glib.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.h" #if defined (__GNUC__) diff --git a/glib/gconvert.c b/glib/gconvert.c index eec413c..9b9c64b 100644 --- a/glib/gconvert.c +++ b/glib/gconvert.c @@ -30,7 +30,7 @@ #include "glib.h" #include "gprintfint.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #ifdef G_PLATFORM_WIN32 #define STRICT diff --git a/glib/gmain.c b/glib/gmain.c index 3fe0c1a..8a0cbb9 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -37,7 +37,7 @@ /* #define G_MAIN_POLL_DEBUG */ #include "glib.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include #include #include diff --git a/glib/gmem.c b/glib/gmem.c index 2e3ca93..59229dd 100644 --- a/glib/gmem.c +++ b/glib/gmem.c @@ -35,7 +35,7 @@ #include #include "glib.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.h" #define MEM_PROFILE_TABLE_SIZE 4096 diff --git a/glib/gmessages.c b/glib/gmessages.c index 726db4e..7ab390f 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -44,7 +44,7 @@ #include "glib.h" #include "gdebug.h" #include "gprintfint.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.h" #ifdef G_OS_WIN32 diff --git a/glib/grand.c b/glib/grand.c index 68274f9..55f8970 100644 --- a/glib/grand.c +++ b/glib/grand.c @@ -48,7 +48,7 @@ #endif #include "glib.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.h" #ifdef G_OS_WIN32 diff --git a/glib/gslice.c b/glib/gslice.c index afc6b72..5cb12d3 100644 --- a/glib/gslice.c +++ b/glib/gslice.c @@ -31,7 +31,7 @@ #include #include #include "gmem.h" /* gslice.h */ -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.h" #include "glib.h" #ifdef HAVE_UNISTD_H diff --git a/glib/gthread.c b/glib/gthread.c index 684a284..72ffcb0 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -41,26 +41,9 @@ #include #include "glib.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.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))) - GQuark g_thread_error_quark (void) { diff --git a/glib/gthreadinit.h b/glib/gthreadprivate.h similarity index 57% rename from glib/gthreadinit.h rename to glib/gthreadprivate.h index bf66849..9b41b77 100644 --- a/glib/gthreadinit.h +++ b/glib/gthreadprivate.h @@ -1,4 +1,6 @@ -/* gthreadinit.h - GLib internal thread initialization functions +/* GLIB - Library of useful routines for C programming + * + * gthreadprivate.h - GLib internal thread system related declarations. * * Copyright (C) 2003 Sebastian Wilhelmi * @@ -18,11 +20,29 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __G_THREADINIT_H__ -#define __G_THREADINIT_H__ +#ifndef __G_THREADPRIVATE_H__ +#define __G_THREADPRIVATE_H__ G_BEGIN_DECLS +/* System thread identifier comparision and assignment */ +#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))) + /* Is called from gthread/gthread-impl.c */ void g_thread_init_glib (void); @@ -32,16 +52,17 @@ void _g_mem_thread_init_noprivate_nomessage (void) G_GNUC_INTERNAL; void _g_slice_thread_init_nomessage (void) G_GNUC_INTERNAL; void _g_messages_thread_init_nomessage (void) G_GNUC_INTERNAL; -/* full fledged initializersa */ +/* full fledged initializers */ void _g_convert_thread_init (void) G_GNUC_INTERNAL; void _g_rand_thread_init (void) G_GNUC_INTERNAL; void _g_main_thread_init (void) G_GNUC_INTERNAL; void _g_atomic_thread_init (void) G_GNUC_INTERNAL; void _g_utils_thread_init (void) G_GNUC_INTERNAL; + #ifdef G_OS_WIN32 void _g_win32_thread_init (void) G_GNUC_INTERNAL; -#endif +#endif /* G_OS_WIN32 */ G_END_DECLS - -#endif /* __G_THREADINIT_H__ */ + +#endif /* __G_THREADPRIVATE_H__ */ diff --git a/glib/gutils.c b/glib/gutils.c index eba093e..b448260 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -56,7 +56,7 @@ #define __G_UTILS_C__ #include "glib.h" #include "gprintfint.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #include "galias.h" #ifdef MAXPATHLEN diff --git a/gthread/gthread-impl.c b/gthread/gthread-impl.c index 7c20b65..89e7ffc 100644 --- a/gthread/gthread-impl.c +++ b/gthread/gthread-impl.c @@ -34,10 +34,11 @@ #include "config.h" #include "glib.h" -#include "gthreadinit.h" +#include "gthreadprivate.h" #ifdef G_THREADS_ENABLED +static GSystemThread zero_thread; /* This is initialized to all zero */ static gboolean thread_system_already_initialized = FALSE; static gint g_thread_priority_map [G_THREAD_PRIORITY_URGENT + 1]; @@ -74,7 +75,7 @@ typedef struct _ErrorCheckInfo ErrorCheckInfo; struct _ErrorCheckInfo { gchar *location; - GThread *owner; + GSystemThread owner; }; static GMutex * @@ -92,7 +93,9 @@ g_mutex_lock_errorcheck_impl (GMutex *mutex, gchar *location) { ErrorCheckInfo *info; - GThread *self = g_thread_self (); + GSystemThread self; + + g_thread_functions_for_glib_use.thread_self (&self); if (magic != G_MUTEX_DEBUG_MAGIC) location = "unknown"; @@ -114,14 +117,14 @@ g_mutex_lock_errorcheck_impl (GMutex *mutex, } info = G_MUTEX_DEBUG_INFO (mutex); - if (info->owner == self) + if (g_system_thread_equal (info->owner, self)) 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); - info->owner = self; + g_system_thread_assign (info->owner, self); info->location = location; } @@ -131,7 +134,9 @@ g_mutex_trylock_errorcheck_impl (GMutex *mutex, gchar *location) { ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); - GThread *self = g_thread_self (); + GSystemThread self; + + g_thread_functions_for_glib_use.thread_self (&self); if (magic != G_MUTEX_DEBUG_MAGIC) location = "unknown"; @@ -143,7 +148,7 @@ g_mutex_trylock_errorcheck_impl (GMutex *mutex, return TRUE; } - if (info->owner == self) + if (g_system_thread_equal (info->owner, self)) g_error ("Trying to recursivly lock a mutex at '%s', " "previously locked at '%s'", location, info->location); @@ -151,7 +156,7 @@ g_mutex_trylock_errorcheck_impl (GMutex *mutex, if (!g_thread_functions_for_glib_use_default.mutex_trylock (mutex)) return FALSE; - info->owner = self; + g_system_thread_assign (info->owner, self); info->location = location; return TRUE; @@ -163,20 +168,22 @@ g_mutex_unlock_errorcheck_impl (GMutex *mutex, gchar *location) { ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); - GThread *self = g_thread_self (); + GSystemThread self; + + g_thread_functions_for_glib_use.thread_self (&self); if (magic != G_MUTEX_DEBUG_MAGIC) location = "unknown"; - if (!info || info->owner == NULL) + if (!info || g_system_thread_equal (info->owner, zero_thread)) g_error ("Trying to unlock an unlocked mutex at '%s'", location); - if (info->owner != self) + if (!g_system_thread_equal (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; + g_system_thread_assign (info->owner, zero_thread); info->location = NULL; g_thread_functions_for_glib_use_default.mutex_unlock (mutex); @@ -192,7 +199,7 @@ g_mutex_free_errorcheck_impl (GMutex *mutex, if (magic != G_MUTEX_DEBUG_MAGIC) location = "unknown"; - if (info && info->owner != NULL) + if (info && !g_system_thread_equal (info->owner, zero_thread)) g_error ("Trying to free a locked mutex at '%s', " "which was previously locked at '%s'", location, info->location); @@ -209,25 +216,27 @@ g_cond_wait_errorcheck_impl (GCond *cond, { ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); - GThread *self = g_thread_self (); + GSystemThread self; + + g_thread_functions_for_glib_use.thread_self (&self); if (magic != G_MUTEX_DEBUG_MAGIC) location = "unknown"; - if (!info || info->owner == NULL) + if (!info || g_system_thread_equal (info->owner, zero_thread)) g_error ("Trying to use an unlocked mutex in g_cond_wait() at '%s'", location); - if (info->owner != self) + if (!g_system_thread_equal (info->owner, self)) g_error ("Trying to use a mutex locked by another thread in " "g_cond_wait() at '%s'", location); - info->owner = NULL; + g_system_thread_assign (info->owner, zero_thread); location = info->location; g_thread_functions_for_glib_use_default.cond_wait (cond, mutex); - info->owner = self; + g_system_thread_assign (info->owner, self); info->location = location; } @@ -240,28 +249,30 @@ g_cond_timed_wait_errorcheck_impl (GCond *cond, gchar *location) { ErrorCheckInfo *info = G_MUTEX_DEBUG_INFO (mutex); - GThread *self = g_thread_self (); + GSystemThread self; gboolean retval; + g_thread_functions_for_glib_use.thread_self (&self); + if (magic != G_MUTEX_DEBUG_MAGIC) location = "unknown"; - if (!info || info->owner == NULL) + if (!info || g_system_thread_equal (info->owner, zero_thread)) g_error ("Trying to use an unlocked mutex in g_cond_timed_wait() at '%s'", location); - if (info->owner != self) + if (!g_system_thread_equal (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; + g_system_thread_assign (info->owner, zero_thread); location = info->location; retval = g_thread_functions_for_glib_use_default.cond_timed_wait (cond, mutex, end_time); - info->owner = self; + g_system_thread_assign (info->owner, self); info->location = location; return retval; diff --git a/tests/.cvsignore b/tests/.cvsignore index 5fbe9a9..8cc3651 100644 --- a/tests/.cvsignore +++ b/tests/.cvsignore @@ -25,6 +25,7 @@ cxx-test date-test dirname-test env-test +errorcheck-mutex-test file-test file-test-get-contents hash-test diff --git a/tests/Makefile.am b/tests/Makefile.am index 11a4c86..a4d5e74 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -49,12 +49,13 @@ endif if ENABLE_TIMELOOP timeloop = timeloop timeloop-closure endif -noinst_PROGRAMS = testglib testgdate testgdateparser unicode-normalize unicode-collate $(timeloop) +noinst_PROGRAMS = testglib testgdate testgdateparser unicode-normalize unicode-collate $(timeloop) errorcheck-mutex-test testglib_LDADD = $(libglib) patterntest_LDADD = $(libglib) testgdate_LDADD = $(libglib) testgdateparser_LDADD = $(libglib) unicode_normalize_LDADD = $(libglib) +errorcheck_mutex_test_LDADD = $(libglib) $(libgthread) if ENABLE_TIMELOOP timeloop_LDADD = $(libglib) timeloop_closure_LDADD = $(libglib) $(libgobject) diff --git a/tests/errorcheck-mutex-test.c b/tests/errorcheck-mutex-test.c new file mode 100644 index 0000000..a245299 --- /dev/null +++ b/tests/errorcheck-mutex-test.c @@ -0,0 +1,131 @@ +#undef G_DISABLE_ASSERT +#undef G_LOG_DOMAIN +#define G_ERRORCHECK_MUTEXES + +#include +#include +#include + +static gpointer +locking_thread (gpointer mutex) +{ + g_mutex_lock ((GMutex*)mutex); + + return NULL; +} + +static void +lock_locked_mutex () +{ + GMutex* mutex = g_mutex_new (); + g_mutex_lock (mutex); + g_mutex_lock (mutex); +} + +static void +trylock_locked_mutex () +{ + GMutex* mutex = g_mutex_new (); + g_mutex_lock (mutex); + g_mutex_trylock (mutex); +} + +static void +unlock_unlocked_mutex () +{ + GMutex* mutex = g_mutex_new (); + g_mutex_lock (mutex); + g_mutex_unlock (mutex); + g_mutex_unlock (mutex); +} + +static void +free_locked_mutex () +{ + GMutex* mutex = g_mutex_new (); + g_mutex_lock (mutex); + g_mutex_free (mutex); +} + +static void +wait_on_unlocked_mutex () +{ + GMutex* mutex = g_mutex_new (); + GCond* cond = g_cond_new (); + g_cond_wait (cond, mutex); +} + +static void +wait_on_otherwise_locked_mutex () +{ + GMutex* mutex = g_mutex_new (); + GCond* cond = g_cond_new (); + GThread* thread = g_thread_create (locking_thread, mutex, TRUE, NULL); + g_assert (thread != NULL); + g_usleep (G_USEC_PER_SEC); + g_cond_wait (cond, mutex); +} + +static void +timed_wait_on_unlocked_mutex () +{ + GMutex* mutex = g_mutex_new (); + GCond* cond = g_cond_new (); + g_cond_timed_wait (cond, mutex, NULL); +} + +static void +timed_wait_on_otherwise_locked_mutex () +{ + GMutex* mutex = g_mutex_new (); + GCond* cond = g_cond_new (); + GThread* thread = g_thread_create (locking_thread, mutex, TRUE, NULL); + g_assert (thread != NULL); + g_usleep (G_USEC_PER_SEC); + g_cond_timed_wait (cond, mutex, NULL); +} + +struct +{ + char *name; + void (*func)(); +} func_table[] = +{ + {"lock_locked_mutex", lock_locked_mutex}, + {"trylock_locked_mutex", trylock_locked_mutex}, + {"unlock_unlocked_mutex", unlock_unlocked_mutex}, + {"free_locked_mutex", free_locked_mutex}, + {"wait_on_unlocked_mutex", wait_on_unlocked_mutex}, + {"wait_on_otherwise_locked_mutex", wait_on_otherwise_locked_mutex}, + {"timed_wait_on_unlocked_mutex", timed_wait_on_unlocked_mutex}, + {"timed_wait_on_otherwise_locked_mutex", + timed_wait_on_otherwise_locked_mutex} +}; + +int +main (int argc, char* argv[]) +{ + int i; + + if (argc == 2) + { + for (i = 0; i < G_N_ELEMENTS (func_table); i++) + { + if (strcmp (func_table[i].name, argv[1]) == 0) + { + g_thread_init (NULL); + func_table[i].func (); + g_assert_not_reached (); + } + } + } + + fprintf (stderr, "Usage: errorcheck-mutex-test [TEST]\n\n"); + fprintf (stderr, " where TEST can be one of:\n\n"); + for (i = 0; i < G_N_ELEMENTS (func_table); i++) + { + fprintf (stderr, " %s\n", func_table[i].name); + } + + return 0; +} -- 2.7.4