Renamed to glib/gthreadprivate.h and moved system thread identifier
authorSebastian Wilhelmi <wilhelmi@google.com>
Wed, 10 May 2006 00:44:50 +0000 (00:44 +0000)
committerSebastian Wilhelmi <wilhelmi@src.gnome.org>
Wed, 10 May 2006 00:44:50 +0000 (00:44 +0000)
2006-05-09  Sebastian Wilhelmi  <wilhelmi@google.com>

* 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.

17 files changed:
ChangeLog
ChangeLog.pre-2-12
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/gthreadprivate.h [moved from glib/gthreadinit.h with 57% similarity]
glib/gutils.c
gthread/gthread-impl.c
tests/.cvsignore
tests/Makefile.am
tests/errorcheck-mutex-test.c [new file with mode: 0644]

index 37279d0..39e8010 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 2006-05-09  Sebastian Wilhelmi  <wilhelmi@google.com>
 
+       * 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
index 37279d0..39e8010 100644 (file)
@@ -1,5 +1,20 @@
 2006-05-09  Sebastian Wilhelmi  <wilhelmi@google.com>
 
+       * 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
index a55f6e6..8cb352b 100644 (file)
@@ -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                 \
index 8202d05..3e9ee43 100644 (file)
@@ -23,7 +23,7 @@
 #include "config.h"
 
 #include "glib.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
 #include "galias.h"
 
 #if defined (__GNUC__)
index eec413c..9b9c64b 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "glib.h"
 #include "gprintfint.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
 
 #ifdef G_PLATFORM_WIN32
 #define STRICT
index 3fe0c1a..8a0cbb9 100644 (file)
@@ -37,7 +37,7 @@
 /* #define G_MAIN_POLL_DEBUG */
 
 #include "glib.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
 #include <signal.h>
 #include <sys/types.h>
 #include <time.h>
index 2e3ca93..59229dd 100644 (file)
@@ -35,7 +35,7 @@
 #include <signal.h>
 
 #include "glib.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
 #include "galias.h"
 
 #define MEM_PROFILE_TABLE_SIZE 4096
index 726db4e..7ab390f 100644 (file)
@@ -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
index 68274f9..55f8970 100644 (file)
@@ -48,7 +48,7 @@
 #endif
 
 #include "glib.h"
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
 #include "galias.h"
 
 #ifdef G_OS_WIN32
index afc6b72..5cb12d3 100644 (file)
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <errno.h>
 #include "gmem.h"               /* gslice.h */
-#include "gthreadinit.h"
+#include "gthreadprivate.h"
 #include "galias.h"
 #include "glib.h"
 #ifdef HAVE_UNISTD_H
index 684a284..72ffcb0 100644 (file)
 #include <string.h>
 
 #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)
 {
similarity index 57%
rename from glib/gthreadinit.h
rename to glib/gthreadprivate.h
index bf66849..9b41b77 100644 (file)
@@ -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
  *
  *   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__ */
index eba093e..b448260 100644 (file)
@@ -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
index 7c20b65..89e7ffc 100644 (file)
 #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;
index 5fbe9a9..8cc3651 100644 (file)
@@ -25,6 +25,7 @@ cxx-test
 date-test
 dirname-test
 env-test
+errorcheck-mutex-test
 file-test
 file-test-get-contents
 hash-test
index 11a4c86..a4d5e74 100644 (file)
@@ -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 (file)
index 0000000..a245299
--- /dev/null
@@ -0,0 +1,131 @@
+#undef G_DISABLE_ASSERT
+#undef G_LOG_DOMAIN
+#define G_ERRORCHECK_MUTEXES
+
+#include <glib.h>
+#include <stdio.h>
+#include <string.h>
+
+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;
+}