Now abort, if a mutex/cond/private is allocated before the thread system

1998-12-10  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>

	* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
	allocated before the thread system is set up.

	* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
	as it is not necessary. Changed the error message. Corrected logic
	for g_thread_use_default_impl.

	* gmutex.c (g_mutex_init): Keep the thread private data array
	after calling g_thread_init().
This commit is contained in:
Sebastian Wilhelmi 1998-12-10 09:12:57 +00:00 committed by Sebastian Wilhelmi
parent c3ba51da2c
commit 502084745c
13 changed files with 193 additions and 87 deletions

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

View File

@ -1,3 +1,15 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix

50
glib.h
View File

@ -2597,10 +2597,7 @@ gint gwin_closedir (DIR *dir);
#endif /* NATIVE_WIN32 */
/* functions for mutex and condition support for glib. */
/* glib is not completly thread safe now, make 'grep -L "MT safe" g*.c'
to see the files, that are not yet made thread safe */
/* functions for thread support for glib. */
typedef struct _GMutex GMutex;
typedef struct _GCond GCond;
@ -2610,12 +2607,12 @@ typedef struct _GStaticPrivate GStaticPrivate;
typedef struct _GThreadFunctions GThreadFunctions;
struct _GThreadFunctions
{
GMutex* (*mutex_new) ();
GMutex* (*mutex_new) (void);
void (*mutex_lock) (GMutex* mutex);
gboolean (*mutex_trylock) (GMutex* mutex);
void (*mutex_unlock) (GMutex* mutex);
void (*mutex_free) (GMutex* mutex);
GCond* (*cond_new) ();
GCond* (*cond_new) (void);
void (*cond_signal) (GCond* cond);
void (*cond_broadcast) (GCond* cond);
void (*cond_wait) (GCond* cond, GMutex* mutex);
@ -2631,34 +2628,29 @@ GUTILS_C_VAR GThreadFunctions g_thread_functions_for_glib_use;
GUTILS_C_VAR gboolean g_thread_use_default_impl;
GUTILS_C_VAR gboolean g_thread_supported;
/* initializes the mutex/cond implementation for glib, might only be
* called once, and must not be called directly or indirectly from
* another glib-function, e.g. as a callback.
*/
/* initializes the mutex/cond/private implementation for glib, might
* only be called once, and must not be called directly or indirectly
* from another glib-function, e.g. as a callback. */
void g_thread_init(GThreadFunctions* init);
/* like above, but might be called several times, returning TRUE, if
* it was the first call to this function, otherwise FALSE is returned
* and the init vector is ignored
*/
gboolean g_thread_try_init(GThreadFunctions* init);
/* Internal functions for fallback static mutex implementation
* Please don't use it directly
* Please don't use it directly
*/
GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex);
#define G_USE_THREAD_FUNC_UNCOND(name,arg) \
(*g_thread_functions_for_glib_use.name)arg
#define G_USE_THREAD_FUNC(name,fail,arg) \
(g_thread_supported ? (*g_thread_functions_for_glib_use.name)arg : (fail))
(g_thread_supported ? G_USE_THREAD_FUNC_UNCOND(name,arg) : (fail))
/* keep in mind, all those mutexes and static mutexes are not
recursive in general, don't rely on that */
#define g_mutex_new() G_USE_THREAD_FUNC(mutex_new,NULL,())
/* keep in mind, all those mutexes and static mutexes are not
* recursive in general, don't rely on that */
#define g_mutex_new() G_USE_THREAD_FUNC_UNCOND(mutex_new,())
#define g_mutex_lock(mutex) G_USE_THREAD_FUNC(mutex_lock,(void)0,(mutex))
#define g_mutex_trylock(mutex) G_USE_THREAD_FUNC(mutex_trylock,TRUE,(mutex))
#define g_mutex_unlock(mutex) G_USE_THREAD_FUNC(mutex_unlock,(void)0,(mutex))
#define g_mutex_free(mutex) G_USE_THREAD_FUNC(mutex_free,(void)0,(mutex))
#define g_cond_new() G_USE_THREAD_FUNC(cond_new,NULL,())
#define g_cond_new() G_USE_THREAD_FUNC_UNCOND(cond_new,())
#define g_cond_signal(cond) G_USE_THREAD_FUNC(cond_signal,(void)0,(cond))
#define g_cond_broadcast(cond) G_USE_THREAD_FUNC(cond_broadcast,(void)0,(cond))
#define g_cond_wait(cond,mutex) G_USE_THREAD_FUNC(cond_wait,(void)0,(cond,mutex))
@ -2667,7 +2659,7 @@ GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex);
#define g_cond_free(cond) G_USE_THREAD_FUNC(cond_free,(void)0,(cond))
#define g_private_new(destructor) \
G_USE_THREAD_FUNC(private_new,NULL,(destructor))
G_USE_THREAD_FUNC_UNCOND(private_new,(destructor))
#define g_private_get(private) \
G_USE_THREAD_FUNC(private_get,((gpointer)private),(private))
#define g_private_set(private,value) \
@ -2675,9 +2667,9 @@ GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex);
(private,value))
/* GStaticMutex'es can be statically initialized with the value
G_STATIC_MUTEX_INIT, and then they can directly be used, that is
much easier, than having to explicitly allocate the mutex before
use */
* G_STATIC_MUTEX_INIT, and then they can directly be used, that is
* much easier, than having to explicitly allocate the mutex before
* use */
#define g_static_mutex_lock(mutex) \
g_mutex_lock( g_static_mutex_get_mutex(mutex) )
#define g_static_mutex_trylock(mutex) \
@ -2698,9 +2690,9 @@ void g_static_private_set (GStaticPrivate *private,
GDestroyNotify notify);
/* these are some convenience macros, for using StaticMutex'es, you
define them by G_LOCK_DEFINE(name), where name could for example be the
name of the protected varibale, and you (un)lock them with
g_(un)lock(name) */
* define them by G_LOCK_DEFINE(name), where name could for example be the
* name of the protected varibale, and you (un)lock them with
* g_(un)lock(name) */
#define g_lock_name(name) (name ## _lock)
#define G_LOCK_DEFINE(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT

View File

@ -2597,10 +2597,7 @@ gint gwin_closedir (DIR *dir);
#endif /* NATIVE_WIN32 */
/* functions for mutex and condition support for glib. */
/* glib is not completly thread safe now, make 'grep -L "MT safe" g*.c'
to see the files, that are not yet made thread safe */
/* functions for thread support for glib. */
typedef struct _GMutex GMutex;
typedef struct _GCond GCond;
@ -2610,12 +2607,12 @@ typedef struct _GStaticPrivate GStaticPrivate;
typedef struct _GThreadFunctions GThreadFunctions;
struct _GThreadFunctions
{
GMutex* (*mutex_new) ();
GMutex* (*mutex_new) (void);
void (*mutex_lock) (GMutex* mutex);
gboolean (*mutex_trylock) (GMutex* mutex);
void (*mutex_unlock) (GMutex* mutex);
void (*mutex_free) (GMutex* mutex);
GCond* (*cond_new) ();
GCond* (*cond_new) (void);
void (*cond_signal) (GCond* cond);
void (*cond_broadcast) (GCond* cond);
void (*cond_wait) (GCond* cond, GMutex* mutex);
@ -2631,34 +2628,29 @@ GUTILS_C_VAR GThreadFunctions g_thread_functions_for_glib_use;
GUTILS_C_VAR gboolean g_thread_use_default_impl;
GUTILS_C_VAR gboolean g_thread_supported;
/* initializes the mutex/cond implementation for glib, might only be
* called once, and must not be called directly or indirectly from
* another glib-function, e.g. as a callback.
*/
/* initializes the mutex/cond/private implementation for glib, might
* only be called once, and must not be called directly or indirectly
* from another glib-function, e.g. as a callback. */
void g_thread_init(GThreadFunctions* init);
/* like above, but might be called several times, returning TRUE, if
* it was the first call to this function, otherwise FALSE is returned
* and the init vector is ignored
*/
gboolean g_thread_try_init(GThreadFunctions* init);
/* Internal functions for fallback static mutex implementation
* Please don't use it directly
* Please don't use it directly
*/
GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex);
#define G_USE_THREAD_FUNC_UNCOND(name,arg) \
(*g_thread_functions_for_glib_use.name)arg
#define G_USE_THREAD_FUNC(name,fail,arg) \
(g_thread_supported ? (*g_thread_functions_for_glib_use.name)arg : (fail))
(g_thread_supported ? G_USE_THREAD_FUNC_UNCOND(name,arg) : (fail))
/* keep in mind, all those mutexes and static mutexes are not
recursive in general, don't rely on that */
#define g_mutex_new() G_USE_THREAD_FUNC(mutex_new,NULL,())
/* keep in mind, all those mutexes and static mutexes are not
* recursive in general, don't rely on that */
#define g_mutex_new() G_USE_THREAD_FUNC_UNCOND(mutex_new,())
#define g_mutex_lock(mutex) G_USE_THREAD_FUNC(mutex_lock,(void)0,(mutex))
#define g_mutex_trylock(mutex) G_USE_THREAD_FUNC(mutex_trylock,TRUE,(mutex))
#define g_mutex_unlock(mutex) G_USE_THREAD_FUNC(mutex_unlock,(void)0,(mutex))
#define g_mutex_free(mutex) G_USE_THREAD_FUNC(mutex_free,(void)0,(mutex))
#define g_cond_new() G_USE_THREAD_FUNC(cond_new,NULL,())
#define g_cond_new() G_USE_THREAD_FUNC_UNCOND(cond_new,())
#define g_cond_signal(cond) G_USE_THREAD_FUNC(cond_signal,(void)0,(cond))
#define g_cond_broadcast(cond) G_USE_THREAD_FUNC(cond_broadcast,(void)0,(cond))
#define g_cond_wait(cond,mutex) G_USE_THREAD_FUNC(cond_wait,(void)0,(cond,mutex))
@ -2667,7 +2659,7 @@ GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex);
#define g_cond_free(cond) G_USE_THREAD_FUNC(cond_free,(void)0,(cond))
#define g_private_new(destructor) \
G_USE_THREAD_FUNC(private_new,NULL,(destructor))
G_USE_THREAD_FUNC_UNCOND(private_new,(destructor))
#define g_private_get(private) \
G_USE_THREAD_FUNC(private_get,((gpointer)private),(private))
#define g_private_set(private,value) \
@ -2675,9 +2667,9 @@ GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex);
(private,value))
/* GStaticMutex'es can be statically initialized with the value
G_STATIC_MUTEX_INIT, and then they can directly be used, that is
much easier, than having to explicitly allocate the mutex before
use */
* G_STATIC_MUTEX_INIT, and then they can directly be used, that is
* much easier, than having to explicitly allocate the mutex before
* use */
#define g_static_mutex_lock(mutex) \
g_mutex_lock( g_static_mutex_get_mutex(mutex) )
#define g_static_mutex_trylock(mutex) \
@ -2698,9 +2690,9 @@ void g_static_private_set (GStaticPrivate *private,
GDestroyNotify notify);
/* these are some convenience macros, for using StaticMutex'es, you
define them by G_LOCK_DEFINE(name), where name could for example be the
name of the protected varibale, and you (un)lock them with
g_(un)lock(name) */
* define them by G_LOCK_DEFINE(name), where name could for example be the
* name of the protected varibale, and you (un)lock them with
* g_(un)lock(name) */
#define g_lock_name(name) (name ## _lock)
#define G_LOCK_DEFINE(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT

View File

@ -35,12 +35,29 @@ struct _GStaticPrivateNode {
};
static void g_static_private_free_data (gpointer data);
static void g_thread_fail (void);
/* Global variables */
gboolean g_thread_use_default_impl = TRUE;
gboolean g_thread_supported = FALSE;
GThreadFunctions g_thread_functions_for_glib_use; /* is NULLified as default */
GThreadFunctions g_thread_functions_for_glib_use = {
(GMutex*(*)())g_thread_fail, /* mutex_new */
NULL, /* mutex_lock */
NULL, /* mutex_trylock */
NULL, /* mutex_unlock */
NULL, /* mutex_free */
(GCond*(*)())g_thread_fail, /* cond_new */
NULL, /* cond_signal */
NULL, /* cond_broadcast */
NULL, /* cond_wait */
NULL, /* cond_timed_wait */
NULL, /* cond_free */
(GPrivate*(*)(GDestroyNotify))g_thread_fail, /* private_new */
NULL, /* private_get */
NULL, /* private_set */
};
/* Local data */
@ -54,10 +71,14 @@ static GPrivate *g_thread_specific_private = NULL;
void
g_mutex_init (void)
{
/* We let the main thread (the one that calls g_thread_init) inherit
the data, that it set before calling g_thread_init */
gpointer private_old = g_thread_specific_private;
g_thread_specific_private = g_private_new (g_static_private_free_data);
g_private_set (g_thread_specific_private, private_old);
g_mutex_protect_static_mutex_allocation = g_mutex_new();
g_thread_specific_mutex = g_mutex_new();
g_thread_specific_private = g_private_new (g_static_private_free_data);
}
GMutex *
@ -143,3 +164,9 @@ g_static_private_free_data (gpointer data)
}
}
}
static void
g_thread_fail (void)
{
g_error ("The thread system is not yet initialized.");
}

View File

@ -35,21 +35,20 @@ static gboolean thread_system_already_initialized = FALSE;
#include G_THREAD_SOURCE
void g_mutex_init();
void g_mutex_init (void);
gboolean
g_thread_try_init(GThreadFunctions* init)
void
g_thread_init(GThreadFunctions* init)
{
if (thread_system_already_initialized)
return FALSE;
g_error ("the glib thread system may only be initialized once.");
thread_system_already_initialized = TRUE;
if (init == NULL)
{
g_thread_use_default_impl = TRUE;
init = &g_thread_functions_for_glib_use_default;
}
init = &g_thread_functions_for_glib_use_default;
else
g_thread_use_default_impl = FALSE;
g_thread_functions_for_glib_use = *init;
@ -69,25 +68,19 @@ g_thread_try_init(GThreadFunctions* init)
init->private_get &&
init->private_get;
/* if somebody is calling g_thread_init(), it means that he wants to
/* if somebody is calling g_thread_init (), it means that he wants to
have thread support, so check this */
if (!g_thread_supported)
g_error( "Mutex functions missing." );
{
if (g_thread_use_default_impl)
g_error ("Threads are not supported on this platform.");
else
g_error ("The supplied thread function vector is invalid.");
}
/* now call the thread initialization functions of the different
glib modules. BTW: order does matter, g_mutex_init MUST be first */
g_mutex_init();
return TRUE;
g_mutex_init ();
}
void
g_thread_init(GThreadFunctions* init)
{
/* Make sure, this function is only called once. */
if (!g_thread_try_init (init))
g_error( "the glib thread system may only be initialized once." );
}

View File

@ -15,8 +15,11 @@ test_mutexes()
GStaticMutex static_mutex = G_STATIC_MUTEX_INIT;
G_LOCK_DEFINE(test_me);
mutex = g_mutex_new();
cond = g_cond_new();
if( g_thread_supported )
{
mutex = g_mutex_new();
cond = g_cond_new();
}
g_mutex_lock(mutex);
g_mutex_unlock(mutex);
@ -30,8 +33,11 @@ test_mutexes()
g_lock(test_me);
g_unlock(test_me);
g_cond_free(cond);
g_mutex_free(mutex);
if( g_thread_supported )
{
g_cond_free(cond);
g_mutex_free(mutex);
}
}
#if defined(DEFAULTMUTEX) /* we are using solaris threads */