Renamed to glib/gthreadprivate.h and moved system thread identifier

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.
This commit is contained in:
Sebastian Wilhelmi 2006-05-10 00:44:50 +00:00 committed by Sebastian Wilhelmi
parent 307391459d
commit e4f8f3b95c
17 changed files with 236 additions and 58 deletions

View 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

View 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

View 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 \

View File

@ -23,7 +23,7 @@
#include "config.h"
#include "glib.h"
#include "gthreadinit.h"
#include "gthreadprivate.h"
#include "galias.h"
#if defined (__GNUC__)

View File

@ -30,7 +30,7 @@
#include "glib.h"
#include "gprintfint.h"
#include "gthreadinit.h"
#include "gthreadprivate.h"
#ifdef G_PLATFORM_WIN32
#define STRICT

View 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>

View 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

View 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

View File

@ -48,7 +48,7 @@
#endif
#include "glib.h"
#include "gthreadinit.h"
#include "gthreadprivate.h"
#include "galias.h"
#ifdef G_OS_WIN32

View 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

View File

@ -41,26 +41,9 @@
#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)
{

View 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
*
@ -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__ */

View 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

View File

@ -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;

View File

@ -25,6 +25,7 @@ cxx-test
date-test
dirname-test
env-test
errorcheck-mutex-test
file-test
file-test-get-contents
hash-test

View 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)

View File

@ -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;
}