summaryrefslogtreecommitdiff
path: root/glib
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>1998-12-15 05:28:02 +0000
committerOwen Taylor <otaylor@src.gnome.org>1998-12-15 05:28:02 +0000
commit931ea952650b013b834041b91b0c37a748ffd449 (patch)
tree0c97c450b0e07953d836f1603c6fcb0357a58149 /glib
parentc8ba100dab8949c49097f11004c09ef36ea5136f (diff)
downloadglib-931ea952650b013b834041b91b0c37a748ffd449.tar.gz
This commit merges the glib-threads branch into the main
branch. See the ChangeLog for details of the changes. In brief overview: - The set of threading functions can be set - A default implementation is provided in -lgthread - All static data structures are locked using these functions if g_thread_init() is called.
Diffstat (limited to 'glib')
-rw-r--r--glib/Makefile.am5
-rw-r--r--glib/garray.c19
-rw-r--r--glib/gbacktrace.c5
-rw-r--r--glib/gcache.c11
-rw-r--r--glib/gcompletion.c4
-rw-r--r--glib/gdataset.c76
-rw-r--r--glib/gdate.c24
-rw-r--r--glib/gerror.c5
-rw-r--r--glib/ghash.c13
-rw-r--r--glib/ghook.c5
-rw-r--r--glib/giochannel.c4
-rw-r--r--glib/giounix.c4
-rw-r--r--glib/glib.h134
-rw-r--r--glib/glist.c44
-rw-r--r--glib/gmain.c158
-rw-r--r--glib/gmem.c89
-rw-r--r--glib/gmessages.c115
-rw-r--r--glib/gnode.c36
-rw-r--r--glib/gprimes.c5
-rw-r--r--glib/grel.c5
-rw-r--r--glib/gscanner.c5
-rw-r--r--glib/gslist.c37
-rw-r--r--glib/gstrfuncs.c26
-rw-r--r--glib/gstring.c11
-rw-r--r--glib/gtimer.c4
-rw-r--r--glib/gtree.c18
-rw-r--r--glib/gutils.c34
27 files changed, 784 insertions, 112 deletions
diff --git a/glib/Makefile.am b/glib/Makefile.am
index d2a10f588..a06082fa3 100644
--- a/glib/Makefile.am
+++ b/glib/Makefile.am
@@ -1,7 +1,7 @@
## Process this file with automake to produce Makefile.in
# build . first, then SUBDIRS
-SUBDIRS = gmodule docs
+SUBDIRS = gmodule gthread docs
all-recursive-am: all-am
# alpha `automake' supports this better
#SUBDIRS = . gmodule docs
@@ -50,7 +50,8 @@ libglib_la_SOURCES = \
gstring.c \
gstrfuncs.c \
gscanner.c \
- gutils.c
+ gutils.c \
+ gmutex.c
include_HEADERS = \
glib.h
diff --git a/glib/garray.c b/glib/garray.c
index 0247972ec..7f0803e3e 100644
--- a/glib/garray.c
+++ b/glib/garray.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include <string.h>
#include "glib.h"
@@ -40,9 +45,8 @@ static gint g_nearest_pow (gint num);
static void g_array_maybe_expand (GRealArray *array,
gint len);
-
static GMemChunk *array_mem_chunk = NULL;
-
+static G_LOCK_DEFINE(array_mem_chunk);
GArray*
g_array_new (gboolean zero_terminated,
@@ -51,12 +55,14 @@ g_array_new (gboolean zero_terminated,
{
GRealArray *array;
+ g_lock (array_mem_chunk);
if (!array_mem_chunk)
array_mem_chunk = g_mem_chunk_new ("array mem chunk",
sizeof (GRealArray),
1024, G_ALLOC_AND_FREE);
array = g_chunk_new (GRealArray, array_mem_chunk);
+ g_unlock (array_mem_chunk);
array->data = NULL;
array->len = 0;
@@ -75,7 +81,9 @@ g_array_free (GArray *array,
if (free_segment)
g_free (array->data);
+ g_lock (array_mem_chunk);
g_mem_chunk_free (array_mem_chunk, array);
+ g_unlock (array_mem_chunk);
}
GArray*
@@ -241,9 +249,8 @@ struct _GRealPtrArray
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
gint len);
-
static GMemChunk *ptr_array_mem_chunk = NULL;
-
+static G_LOCK_DEFINE(ptr_array_mem_chunk);
GPtrArray*
@@ -251,12 +258,14 @@ g_ptr_array_new (void)
{
GRealPtrArray *array;
+ g_lock (ptr_array_mem_chunk);
if (!ptr_array_mem_chunk)
ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk",
sizeof (GRealPtrArray),
1024, G_ALLOC_AND_FREE);
array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk);
+ g_unlock (ptr_array_mem_chunk);
array->pdata = NULL;
array->len = 0;
@@ -274,7 +283,9 @@ g_ptr_array_free (GPtrArray *array,
if (free_segment)
g_free (array->pdata);
+ g_lock (ptr_array_mem_chunk);
g_mem_chunk_free (ptr_array_mem_chunk, array);
+ g_unlock (ptr_array_mem_chunk);
}
static void
diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c
index 6aeb8b517..2615ce2b4 100644
--- a/glib/gbacktrace.c
+++ b/glib/gbacktrace.c
@@ -17,6 +17,11 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe ; except for g_on_error_stack_trace, but who wants thread safety
+ * then
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
diff --git a/glib/gcache.c b/glib/gcache.c
index b2fe77910..800bb2b13 100644
--- a/glib/gcache.c
+++ b/glib/gcache.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
@@ -56,7 +61,7 @@ static void g_cache_node_destroy (GCacheNode *node);
static GMemChunk *node_mem_chunk = NULL;
-
+static G_LOCK_DEFINE(node_mem_chunk);
GCache*
g_cache_new (GCacheNewFunc value_new_func,
@@ -193,11 +198,13 @@ g_cache_node_new (gpointer value)
{
GCacheNode *node;
+ g_lock (node_mem_chunk);
if (!node_mem_chunk)
node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode),
1024, G_ALLOC_AND_FREE);
node = g_chunk_new (GCacheNode, node_mem_chunk);
+ g_unlock (node_mem_chunk);
node->value = value;
node->ref_count = 1;
@@ -208,5 +215,7 @@ g_cache_node_new (gpointer value)
static void
g_cache_node_destroy (GCacheNode *node)
{
+ g_lock (node_mem_chunk);
g_mem_chunk_free (node_mem_chunk, node);
+ g_unlock (node_mem_chunk);
}
diff --git a/glib/gcompletion.c b/glib/gcompletion.c
index 62ec244bc..cba2a86cb 100644
--- a/glib/gcompletion.c
+++ b/glib/gcompletion.c
@@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#include "glib.h"
#include <string.h>
diff --git a/glib/gdataset.c b/glib/gdataset.c
index 7dafc2191..f22b21d59 100644
--- a/glib/gdataset.c
+++ b/glib/gdataset.c
@@ -18,6 +18,12 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe ; FIXME: might still freeze, watch out, not thoroughly
+ * looked at yet.
+ */
+
#include <string.h>
#include "glib.h"
@@ -61,18 +67,24 @@ static inline GQuark g_quark_new (gchar *string);
/* --- variables --- */
+static G_LOCK_DEFINE(g_dataset_global);
static GHashTable *g_dataset_location_ht = NULL;
-static GDataset *g_dataset_cached = NULL;
+static GDataset *g_dataset_cached = NULL; /* should this be
+ threadspecific? */
static GMemChunk *g_dataset_mem_chunk = NULL;
static GMemChunk *g_data_mem_chunk = NULL;
static GData *g_data_cache = NULL;
static guint g_data_cache_length = 0;
+
+static G_LOCK_DEFINE(g_quark_global);
static GHashTable *g_quark_ht = NULL;
static gchar **g_quarks = NULL;
static GQuark g_quark_seq_id = 0;
/* --- functions --- */
+
+/* HOLDS: g_dataset_global_lock */
static inline void
g_datalist_clear_i (GData **datalist)
{
@@ -109,13 +121,16 @@ g_datalist_clear (GData **datalist)
{
g_return_if_fail (datalist != NULL);
+ g_lock (g_dataset_global);
if (!g_dataset_location_ht)
g_data_initialize ();
while (*datalist)
g_datalist_clear_i (datalist);
+ g_unlock (g_dataset_global);
}
+/* HOLDS: g_dataset_global_lock */
static inline GDataset*
g_dataset_lookup (gconstpointer dataset_location)
{
@@ -131,6 +146,7 @@ g_dataset_lookup (gconstpointer dataset_location)
return dataset;
}
+/* HOLDS: g_dataset_global_lock */
static void
g_dataset_destroy_internal (GDataset *dataset)
{
@@ -158,6 +174,7 @@ g_dataset_destroy (gconstpointer dataset_location)
{
g_return_if_fail (dataset_location != NULL);
+ g_lock (g_dataset_global);
if (g_dataset_location_ht)
{
register GDataset *dataset;
@@ -166,8 +183,10 @@ g_dataset_destroy (gconstpointer dataset_location)
if (dataset)
g_dataset_destroy_internal (dataset);
}
+ g_unlock (g_dataset_global);
}
+/* HOLDS: g_dataset_global_lock */
static inline void
g_data_set_internal (GData **datalist,
GQuark key_id,
@@ -293,9 +312,10 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
return;
}
+ g_lock (g_dataset_global);
if (!g_dataset_location_ht)
g_data_initialize ();
-
+
dataset = g_dataset_lookup (dataset_location);
if (!dataset)
{
@@ -308,6 +328,7 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
}
g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
+ g_unlock (g_dataset_global);
}
void
@@ -327,10 +348,12 @@ g_datalist_id_set_data_full (GData **datalist,
return;
}
+ g_lock (g_dataset_global);
if (!g_dataset_location_ht)
g_data_initialize ();
g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
+ g_unlock (g_dataset_global);
}
void
@@ -339,6 +362,7 @@ g_dataset_id_remove_no_notify (gconstpointer dataset_location,
{
g_return_if_fail (dataset_location != NULL);
+ g_lock (g_dataset_global);
if (key_id && g_dataset_location_ht)
{
GDataset *dataset;
@@ -346,7 +370,8 @@ g_dataset_id_remove_no_notify (gconstpointer dataset_location,
dataset = g_dataset_lookup (dataset_location);
if (dataset)
g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset);
- }
+ }
+ g_unlock (g_dataset_global);
}
void
@@ -355,8 +380,10 @@ g_datalist_id_remove_no_notify (GData **datalist,
{
g_return_if_fail (datalist != NULL);
+ g_lock (g_dataset_global);
if (key_id && g_dataset_location_ht)
g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL);
+ g_unlock (g_dataset_global);
}
gpointer
@@ -365,6 +392,7 @@ g_dataset_id_get_data (gconstpointer dataset_location,
{
g_return_val_if_fail (dataset_location != NULL, NULL);
+ g_lock (g_dataset_global);
if (key_id && g_dataset_location_ht)
{
register GDataset *dataset;
@@ -376,10 +404,14 @@ g_dataset_id_get_data (gconstpointer dataset_location,
for (list = dataset->datalist; list; list = list->next)
if (list->id == key_id)
- return list->data;
+ {
+ g_unlock (g_dataset_global);
+ return list->data;
+ }
}
}
-
+ g_unlock (g_dataset_global);
+
return NULL;
}
@@ -411,17 +443,23 @@ g_dataset_foreach (gconstpointer dataset_location,
g_return_if_fail (dataset_location != NULL);
g_return_if_fail (func != NULL);
+ g_lock (g_dataset_global);
if (g_dataset_location_ht)
{
dataset = g_dataset_lookup (dataset_location);
+ g_unlock (g_dataset_global);
if (dataset)
{
register GData *list;
for (list = dataset->datalist; list; list = list->next)
- func (list->id, list->data, user_data);
+ func (list->id, list->data, user_data);
}
}
+ else
+ {
+ g_unlock (g_dataset_global);
+ }
}
void
@@ -446,6 +484,7 @@ g_datalist_init (GData **datalist)
*datalist = NULL;
}
+/* HOLDS: g_dataset_global_lock */
static void
g_data_initialize (void)
{
@@ -468,12 +507,15 @@ g_data_initialize (void)
GQuark
g_quark_try_string (const gchar *string)
{
+ GQuark quark = 0;
g_return_val_if_fail (string != NULL, 0);
+ g_lock (g_quark_global);
if (g_quark_ht)
- return (gulong) g_hash_table_lookup (g_quark_ht, string);
- else
- return 0;
+ quark = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
+ g_unlock (g_quark_global);
+
+ return quark;
}
GQuark
@@ -483,6 +525,7 @@ g_quark_from_string (const gchar *string)
g_return_val_if_fail (string != NULL, 0);
+ g_lock (g_quark_global);
if (g_quark_ht)
quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
else
@@ -493,6 +536,7 @@ g_quark_from_string (const gchar *string)
if (!quark)
quark = g_quark_new (g_strdup (string));
+ g_unlock (g_quark_global);
return quark;
}
@@ -504,6 +548,7 @@ g_quark_from_static_string (const gchar *string)
g_return_val_if_fail (string != NULL, 0);
+ g_lock (g_quark_global);
if (g_quark_ht)
quark = (gulong) g_hash_table_lookup (g_quark_ht, string);
else
@@ -514,19 +559,24 @@ g_quark_from_static_string (const gchar *string)
if (!quark)
quark = g_quark_new ((gchar*) string);
-
+ g_unlock (g_quark_global);
+
return quark;
}
gchar*
g_quark_to_string (GQuark quark)
{
+ gchar* result = NULL;
+ g_lock (g_quark_global);
if (quark > 0 && quark <= g_quark_seq_id)
- return g_quarks[quark - 1];
- else
- return NULL;
+ result = g_quarks[quark - 1];
+ g_unlock (g_quark_global);
+
+ return result;
}
+/* HOLDS: g_quark_global_lock */
static inline GQuark
g_quark_new (gchar *string)
{
diff --git a/glib/gdate.c b/glib/gdate.c
index 69c337def..7c60e23d9 100644
--- a/glib/gdate.c
+++ b/glib/gdate.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
#include <time.h>
@@ -383,6 +388,8 @@ g_date_clear (GDate *d, guint ndates)
memset (d, 0x0, ndates*sizeof (GDate));
}
+static G_LOCK_DEFINE(g_date_global);
+
/* These are for the parser, output to the user should use *
* g_date_strftime () - this creates more never-freed memory to annoy
* all those memory debugger users. :-)
@@ -429,6 +436,7 @@ typedef struct _GDateParseTokens GDateParseTokens;
#define NUM_LEN 10
+/* HOLDS: g_date_global_lock */
static void
g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
{
@@ -488,7 +496,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
if (found != NULL)
{
pt->month = i;
- return;
+ return;
}
}
@@ -502,12 +510,13 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
return;
}
}
-
+
++i;
- }
+ }
}
}
+/* HOLDS: g_date_global_lock */
static void
g_date_prepare_to_parse (const gchar *str, GDateParseTokens *pt)
{
@@ -641,6 +650,8 @@ g_date_set_parse (GDate *d,
/* set invalid */
g_date_clear (d, 1);
+ g_lock (g_date_global);
+
g_date_prepare_to_parse (str, &pt);
#ifdef G_ENABLE_DEBUG
@@ -649,7 +660,11 @@ g_date_set_parse (GDate *d,
#endif
- if (pt.num_ints == 4) return; /* presumably a typo; bail out. */
+ if (pt.num_ints == 4)
+ {
+ g_unlock (g_date_global);
+ return; /* presumably a typo; bail out. */
+ }
if (pt.num_ints > 1)
{
@@ -765,6 +780,7 @@ g_date_set_parse (GDate *d,
else
g_message ("Rejected DMY %u %u %u", day, m, y);
#endif
+ g_unlock (g_date_global);
}
void
diff --git a/glib/gerror.c b/glib/gerror.c
index 6aeb8b517..2615ce2b4 100644
--- a/glib/gerror.c
+++ b/glib/gerror.c
@@ -17,6 +17,11 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe ; except for g_on_error_stack_trace, but who wants thread safety
+ * then
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
diff --git a/glib/ghash.c b/glib/ghash.c
index 4ab82b3fa..724036388 100644
--- a/glib/ghash.c
+++ b/glib/ghash.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
@@ -52,6 +57,8 @@ static void g_hash_node_destroy (GHashNode *hash_node);
static void g_hash_nodes_destroy (GHashNode *hash_node);
+static G_LOCK_DEFINE(g_hash_global);
+
static GMemChunk *node_mem_chunk = NULL;
static GHashNode *node_free_list = NULL;
@@ -338,6 +345,7 @@ g_hash_node_new (gpointer key,
{
GHashNode *hash_node;
+ g_lock (g_hash_global);
if (node_free_list)
{
hash_node = node_free_list;
@@ -352,6 +360,7 @@ g_hash_node_new (gpointer key,
hash_node = g_chunk_new (GHashNode, node_mem_chunk);
}
+ g_unlock (g_hash_global);
hash_node->key = key;
hash_node->value = value;
@@ -363,8 +372,10 @@ g_hash_node_new (gpointer key,
static void
g_hash_node_destroy (GHashNode *hash_node)
{
+ g_lock (g_hash_global);
hash_node->next = node_free_list;
node_free_list = hash_node;
+ g_unlock (g_hash_global);
}
static void
@@ -380,6 +391,8 @@ g_hash_nodes_destroy (GHashNode *hash_node)
while (node->next)
node = node->next;
+ g_lock (g_hash_global);
node->next = node_free_list;
node_free_list = hash_node;
+ g_unlock (g_hash_global);
}
diff --git a/glib/ghook.c b/glib/ghook.c
index 47a2874a4..b683b7c31 100644
--- a/glib/ghook.c
+++ b/glib/ghook.c
@@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
diff --git a/glib/giochannel.c b/glib/giochannel.c
index fa4262602..0693a084b 100644
--- a/glib/giochannel.c
+++ b/glib/giochannel.c
@@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#include "glib.h"
#include <unistd.h>
diff --git a/glib/giounix.c b/glib/giounix.c
index 5e605a478..82944be89 100644
--- a/glib/giounix.c
+++ b/glib/giounix.c
@@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#include "glib.h"
#include <sys/types.h>
#include <unistd.h>
diff --git a/glib/glib.h b/glib/glib.h
index 33fa042e9..d4d1aaa77 100644
--- a/glib/glib.h
+++ b/glib/glib.h
@@ -2597,6 +2597,140 @@ gint gwin_closedir (DIR *dir);
#endif /* NATIVE_WIN32 */
+/* functions for thread support for glib. */
+
+typedef struct _GMutex GMutex;
+typedef struct _GCond GCond;
+typedef struct _GPrivate GPrivate;
+typedef struct _GStaticPrivate GStaticPrivate;
+
+typedef struct _GThreadFunctions GThreadFunctions;
+struct _GThreadFunctions
+{
+ 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) (void);
+ void (*cond_signal) (GCond* cond);
+ void (*cond_broadcast) (GCond* cond);
+ void (*cond_wait) (GCond* cond, GMutex* mutex);
+ gboolean (*cond_timed_wait) (GCond* cond, GMutex* mutex,
+ GTimeVal *end_time);
+ void (*cond_free) (GCond* cond);
+ GPrivate* (*private_new) (GDestroyNotify destructor);
+ gpointer (*private_get) (GPrivate* private);
+ void (*private_set) (GPrivate* private, gpointer value);
+};
+
+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/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);
+
+/* Internal functions for fallback static mutex implementation
+ * 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_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_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_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))
+#define g_cond_timed_wait(cond,mutex,abs_time) \
+ G_USE_THREAD_FUNC(cond_timed_wait,TRUE,(cond,mutex,abs_time))
+#define g_cond_free(cond) G_USE_THREAD_FUNC(cond_free,(void)0,(cond))
+
+#define g_private_new(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) \
+ G_USE_THREAD_FUNC(private_set,(void)(private=(GPrivate *)(value)), \
+ (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 */
+#define g_static_mutex_lock(mutex) \
+ g_mutex_lock( g_static_mutex_get_mutex(mutex) )
+#define g_static_mutex_trylock(mutex) \
+ g_mutex_trylock( g_static_mutex_get_mutex(mutex) )
+#define g_static_mutex_unlock(mutex) \
+ g_mutex_unlock( g_static_mutex_get_mutex(mutex) )
+
+struct _GStaticPrivate
+{
+ guint index;
+};
+
+#define G_STATIC_PRIVATE_INIT { 0 }
+
+gpointer g_static_private_get (GStaticPrivate* private);
+void g_static_private_set (GStaticPrivate *private,
+ gpointer data,
+ 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 g_lock_name(name) (name ## _lock)
+#define G_LOCK_DEFINE(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT
+
+#ifdef G_DEBUG_LOCKS
+#define g_lock(name) G_STMT_START{ \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_MESSAGE, \
+ "file %s: line %d (%s): locking: %s ", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #name); \
+ g_static_mutex_lock(g_lock_name(name)); \
+ }G_STMT_END
+#define g_unlock(name) G_STMT_START{ \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_MESSAGE, \
+ "file %s: line %d (%s): unlocking: %s ", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #name); \
+ g_static_mutex_unlock(g_lock_name(name)); \
+ }G_STMT_END
+#define g_trylock(name) G_STMT_START{ \
+ g_log (G_LOG_DOMAIN, \
+ G_LOG_LEVEL_MESSAGE, \
+ "file %s: line %d (%s): try locking: %s ", \
+ __FILE__, \
+ __LINE__, \
+ __PRETTY_FUNCTION__, \
+ #name); \
+ }G_STMT_END, g_static_mutex_trylock(g_lock_name(name))
+#else /* !G_DEBUG_LOCKS */
+#define g_lock(name) g_static_mutex_lock(g_lock_name(name))
+#define g_unlock(name) g_static_mutex_unlock(g_lock_name(name))
+#define g_trylock(name) g_static_mutex_trylock(g_lock_name(name))
+#endif
#ifdef __cplusplus
}
diff --git a/glib/glist.c b/glib/glist.c
index 41a09dd18..e74dee872 100644
--- a/glib/glist.c
+++ b/glib/glist.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
@@ -31,9 +36,11 @@ struct _GAllocator /* from gmem.c */
};
static GAllocator *current_allocator = NULL;
+static G_LOCK_DEFINE(current_allocator);
-void
-g_list_push_allocator (GAllocator *allocator)
+/* HOLDS: current_allocator_lock */
+static void
+g_list_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@@ -58,13 +65,22 @@ g_list_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
+}
+
+void
+g_list_push_allocator(GAllocator *allocator)
+{
+ g_list_validate_allocator ( allocator );
+ g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
+ g_unlock (current_allocator);
}
void
g_list_pop_allocator (void)
{
+ g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@@ -74,6 +90,7 @@ g_list_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
+ g_unlock (current_allocator);
}
GList*
@@ -81,9 +98,15 @@ g_list_alloc (void)
{
GList *list;
+ g_lock (current_allocator);
if (!current_allocator)
- g_list_push_allocator (g_allocator_new ("GLib default GList allocator", 1024));
-
+ {
+ GAllocator *allocator = g_allocator_new ("GLib default GList allocator",
+ 1024);
+ g_list_validate_allocator (allocator);
+ allocator->last = NULL;
+ current_allocator = allocator;
+ }
if (!current_allocator->free_lists)
{
list = g_chunk_new (GList, current_allocator->mem_chunk);
@@ -103,6 +126,7 @@ g_list_alloc (void)
current_allocator->free_lists = list->next;
}
}
+ g_unlock (current_allocator);
list->next = NULL;
list->prev = NULL;
@@ -112,23 +136,31 @@ g_list_alloc (void)
void
g_list_free (GList *list)
{
+#if 0
if (list)
{
- list->data = list->next;
+ list->data = list->next;
+ g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
+ g_unlock (current_allocator);
}
+#endif
}
void
g_list_free_1 (GList *list)
{
+#if 0
if (list)
{
- list->data = NULL;
+ list->data = NULL;
+ g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
+ g_unlock (current_allocator);
}
+#endif
}
GList*
diff --git a/glib/gmain.c b/glib/gmain.c
index 1f13e9097..5d3ae8d46 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -20,9 +20,14 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#include "glib.h"
#include <sys/time.h>
#include <unistd.h>
+#include <errno.h>
#include "config.h"
/* Types */
@@ -65,9 +70,12 @@ struct _GPollRec {
/* Forward declarations */
-static void g_main_poll (gint timeout,
- gboolean use_priority,
- gint priority);
+static void g_main_poll (gint timeout,
+ gboolean use_priority,
+ gint priority);
+static void g_main_poll_add_unlocked (gint priority,
+ GPollFD *fd);
+
static gboolean g_timeout_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout);
@@ -90,6 +98,11 @@ static gboolean g_idle_dispatch (gpointer source_data,
static GSList *pending_dispatches = NULL;
static GHookList source_list = { 0 };
+/* The following lock is used for both the list of sources
+ * and the list of poll records
+ */
+static G_LOCK_DEFINE (main_loop);
+
static GSourceFuncs timeout_funcs = {
g_timeout_prepare,
g_timeout_check,
@@ -104,6 +117,17 @@ static GSourceFuncs idle_funcs = {
(GDestroyNotify)g_free
};
+static GPollRec *poll_records = NULL;
+static GPollRec *poll_free_list = NULL;
+static GMemChunk *poll_chunk;
+static guint n_poll_records = 0;
+
+/* this pipe is used to wake up the main loop when a source is added.
+ */
+static gint wake_up_pipe[2] = { -1, -1 };
+static GPollFD wake_up_rec;
+static gboolean poll_waiting = FALSE;
+
#ifdef HAVE_POLL
static GPollFunc poll_func = (GPollFunc)poll;
#else
@@ -205,8 +229,11 @@ g_source_add (gint priority,
gpointer user_data,
GDestroyNotify notify)
{
+ guint return_val;
GSource *source;
+ g_lock (main_loop);
+
if (!source_list.is_setup)
g_hook_list_init (&source_list, sizeof(GSource));
@@ -224,31 +251,55 @@ g_source_add (gint priority,
if (can_recurse)
source->hook.flags |= G_SOURCE_CAN_RECURSE;
- return source->hook.hook_id;
+ return_val = source->hook.hook_id;
+
+ /* Now wake up the main loop if it is waiting in the poll() */
+
+ if (poll_waiting)
+ {
+ poll_waiting = FALSE;
+ write (wake_up_pipe[1], "A", 1);
+ }
+
+ g_unlock (main_loop);
+
+ return return_val;
}
void
g_source_remove (guint tag)
{
- GHook *hook = g_hook_get (&source_list, tag);
+ GHook *hook;
+
+ g_lock (main_loop);
+
+ hook = g_hook_get (&source_list, tag);
if (hook)
{
GSource *source = (GSource *)hook;
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
+
+ g_unlock (main_loop);
}
void
g_source_remove_by_user_data (gpointer user_data)
{
- GHook *hook = g_hook_find_data (&source_list, TRUE, user_data);
+ GHook *hook;
+
+ g_lock (main_loop);
+
+ hook = g_hook_find_data (&source_list, TRUE, user_data);
if (hook)
{
GSource *source = (GSource *)hook;
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
+
+ g_unlock (main_loop);
}
static gboolean
@@ -262,7 +313,11 @@ g_source_find_source_data (GHook *hook,
void
g_source_remove_by_source_data (gpointer source_data)
{
- GHook *hook = g_hook_find (&source_list, TRUE,
+ GHook *hook;
+
+ g_lock (main_loop);
+
+ hook = g_hook_find (&source_list, TRUE,
g_source_find_source_data, source_data);
if (hook)
{
@@ -270,6 +325,8 @@ g_source_remove_by_source_data (gpointer source_data)
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
+
+ g_unlock (main_loop);
}
void g_get_current_time (GTimeVal *result)
@@ -279,6 +336,7 @@ void g_get_current_time (GTimeVal *result)
/* Running the main loop */
+/* HOLDS: main_loop_lock */
static void
g_main_dispatch (GTimeVal *current_time)
{
@@ -294,10 +352,20 @@ g_main_dispatch (GTimeVal *current_time)
if (G_HOOK_IS_VALID (source))
{
+ gboolean (*dispatch) (gpointer, GTimeVal *, gpointer);
+ gpointer hook_data = source->hook.data;
+ gpointer source_data = source->source_data;
+
+ dispatch = ((GSourceFuncs *)source->hook.func)->dispatch;
+
source->hook.flags |= G_HOOK_FLAG_IN_CALL;
- need_destroy = !((GSourceFuncs *)source->hook.func)->dispatch (source->source_data,
- current_time,
- source->hook.data);
+
+ g_unlock (main_loop);
+ need_destroy = ! dispatch(source_data,
+ current_time,
+ hook_data);
+ g_lock (main_loop);
+
source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
if (need_destroy)
@@ -320,10 +388,13 @@ g_main_iterate (gboolean block, gboolean dispatch)
gint nready = 0;
gint current_priority = 0;
gint timeout;
+ gboolean retval = FALSE;
g_return_val_if_fail (!block || dispatch, FALSE);
g_get_current_time (&current_time);
+
+ g_lock (main_loop);
/* If recursing, finish up current dispatch, before starting over */
if (pending_dispatches)
@@ -331,6 +402,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
if (dispatch)
g_main_dispatch (&current_time);
+ g_unlock (main_loop);
return TRUE;
}
@@ -362,6 +434,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
if (!dispatch)
{
g_hook_unref (&source_list, hook);
+ g_unlock (main_loop);
return TRUE;
}
else
@@ -426,6 +499,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
else
{
g_hook_unref (&source_list, hook);
+ g_unlock (main_loop);
return TRUE;
}
}
@@ -442,10 +516,12 @@ g_main_iterate (gboolean block, gboolean dispatch)
{
pending_dispatches = g_slist_reverse (pending_dispatches);
g_main_dispatch (&current_time);
- return TRUE;
+ retval = TRUE;
}
- else
- return FALSE;
+
+ g_unlock (main_loop);
+
+ return retval;
}
/* See if any events are pending
@@ -494,11 +570,7 @@ g_main_destroy (GMainLoop *loop)
g_free (loop);
}
-static GPollRec *poll_records = NULL;
-static GPollRec *poll_free_list = NULL;
-static GMemChunk *poll_chunk;
-static guint n_poll_records = 0;
-
+/* HOLDS: main_loop_lock */
static void
g_main_poll (gint timeout, gboolean use_priority, gint priority)
{
@@ -508,6 +580,17 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
gint i;
gint npoll;
+ if (wake_up_pipe[0] < 0)
+ {
+ if (pipe (wake_up_pipe) < 0)
+ g_error ("Cannot create pipe main loop wake-up: %s\n",
+ g_strerror(errno));
+
+ wake_up_rec.fd = wake_up_pipe[0];
+ wake_up_rec.events = G_IO_IN;
+ g_main_poll_add_unlocked (0, &wake_up_rec);
+ }
+
pollrec = poll_records;
i = 0;
while (pollrec && (!use_priority || priority >= pollrec->priority))
@@ -520,8 +603,20 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
i++;
}
+ poll_waiting = TRUE;
+
+ g_unlock (main_loop);
npoll = i;
(*poll_func) (fd_array, npoll, timeout);
+ g_lock (main_loop);
+
+ if (!poll_waiting)
+ {
+ gchar c;
+ read (wake_up_pipe[0], &c, 1);
+ }
+ else
+ poll_waiting = FALSE;
pollrec = poll_records;
i = 0;
@@ -539,12 +634,28 @@ void
g_main_poll_add (gint priority,
GPollFD *fd)
{
+ g_lock (main_loop);
+ g_main_poll_add_unlocked (priority, fd);
+ g_unlock (main_loop);
+}
+
+static void
+g_main_poll_add_unlocked (gint priority,
+ GPollFD *fd)
+{
GPollRec *lastrec, *pollrec, *newrec;
if (!poll_chunk)
poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
- newrec = g_chunk_new (GPollRec, poll_chunk);
+ if (poll_free_list)
+ {
+ newrec = poll_free_list;
+ poll_free_list = newrec->next;
+ }
+ else
+ newrec = g_chunk_new (GPollRec, poll_chunk);
+
newrec->fd = fd;
newrec->priority = priority;
@@ -564,6 +675,8 @@ g_main_poll_add (gint priority,
newrec->next = pollrec;
n_poll_records++;
+
+ g_unlock (main_loop);
}
void
@@ -571,6 +684,8 @@ g_main_poll_remove (GPollFD *fd)
{
GPollRec *pollrec, *lastrec;
+ g_lock (main_loop);
+
lastrec = NULL;
pollrec = poll_records;
@@ -585,12 +700,15 @@ g_main_poll_remove (GPollFD *fd)
pollrec->next = poll_free_list;
poll_free_list = pollrec;
+
+ n_poll_records--;
+ break;
}
lastrec = pollrec;
pollrec = pollrec->next;
}
- n_poll_records--;
+ g_unlock (main_loop);
}
void
diff --git a/glib/gmem.c b/glib/gmem.c
index c29ee660f..a4907ffca 100644
--- a/glib/gmem.c
+++ b/glib/gmem.c
@@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -48,8 +52,12 @@
*/
#if defined(ENABLE_MEM_PROFILE) && defined(ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS)
-#define ENTER_MEM_CHUNK_ROUTINE() allocating_for_mem_chunk++
-#define LEAVE_MEM_CHUNK_ROUTINE() allocating_for_mem_chunk--
+#define ENTER_MEM_CHUNK_ROUTINE() \
+ g_static_set (allocating_for_mem_chunk, \
+ g_static_get (allocating_for_mem_chunk) + 1)
+#define ENTER_MEM_CHUNK_ROUTINE() \
+ g_static_set (allocating_for_mem_chunk, \
+ g_static_get (allocating_for_mem_chunk) - 1)
#else
#define ENTER_MEM_CHUNK_ROUTINE()
#define LEAVE_MEM_CHUNK_ROUTINE()
@@ -117,13 +125,19 @@ static gint g_mem_chunk_area_search (GMemArea *a,
gchar *addr);
+/* here we can't use StaticMutexes, as they depend upon a working
+ * g_malloc, the same holds true for StaticPrivate */
+static GMutex* mem_chunks_lock = NULL;
static GRealMemChunk *mem_chunks = NULL;
#ifdef ENABLE_MEM_PROFILE
+static GMutex* mem_profile_lock;
static gulong allocations[MEM_PROFILE_TABLE_SIZE] = { 0 };
static gulong allocated_mem = 0;
static gulong freed_mem = 0;
-static gint allocating_for_mem_chunk = 0;
+static GPrivate* allocating_for_mem_chunk = NULL;
+#define IS_IN_MEM_CHUNK_ROUTINE() \
+ GPOINTER_TO_UINT (g_static_get (allocating_for_mem_chunk))
#endif /* ENABLE_MEM_PROFILE */
@@ -174,8 +188,9 @@ g_malloc (gulong size)
*t = size;
#ifdef ENABLE_MEM_PROFILE
+ g_mutex_lock (mem_profile_lock);
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- if(!allocating_for_mem_chunk) {
+ if(!IS_IN_MEM_CHUNK_ROUTINE()) {
# endif
if (size <= MEM_PROFILE_TABLE_SIZE - 1)
allocations[size-1] += 1;
@@ -185,6 +200,7 @@ g_malloc (gulong size)
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
# endif
+ g_mutex_unlock (mem_profile_lock);
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@@ -237,8 +253,9 @@ g_malloc0 (gulong size)
*t = size;
# ifdef ENABLE_MEM_PROFILE
+ g_mutex_lock (mem_profile_lock);
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- if(!allocating_for_mem_chunk) {
+ if(!IS_IN_MEM_CHUNK_ROUTINE()) {
# endif
if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
allocations[size-1] += 1;
@@ -248,8 +265,9 @@ g_malloc0 (gulong size)
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
# endif
+ g_mutex_unlock (mem_profile_lock);
# endif /* ENABLE_MEM_PROFILE */
-#endif /* ENABLE_MEM_PROFILE */
+#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
return p;
@@ -286,7 +304,9 @@ g_realloc (gpointer mem,
#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
#ifdef ENABLE_MEM_PROFILE
+ g_mutex_lock (mem_profile);
freed_mem += *t;
+ g_mutex_unlock (mem_profile);
#endif /* ENABLE_MEM_PROFILE */
mem = t;
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@@ -321,8 +341,9 @@ g_realloc (gpointer mem,
*t = size;
#ifdef ENABLE_MEM_PROFILE
+ g_mutex_lock (mem_profile_lock);
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
- if(!allocating_for_mem_chunk) {
+ if(!IS_IN_MEM_CHUNK_ROUTINE()) {
#endif
if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
allocations[size-1] += 1;
@@ -332,6 +353,7 @@ g_realloc (gpointer mem,
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
#endif
+ g_mutex_unlock (mem_profile_lock);
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@@ -352,8 +374,10 @@ g_free (gpointer mem)
#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
size = *t;
-#ifdef ENABLE_MEM_PROFILE
+#ifdef ENABLE_MEM_PROFILE
+ g_mutex_lock (mem_profile);
freed_mem += size;
+ g_mutex_unlock (mem_profile);
#endif /* ENABLE_MEM_PROFILE */
mem = t;
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@@ -380,19 +404,29 @@ g_mem_profile (void)
{
#ifdef ENABLE_MEM_PROFILE
gint i;
-
+ gulong local_allocations[MEM_PROFILE_TABLE_SIZE];
+ gulong local_allocated_mem;
+ gulong local_freed_mem;
+
+ g_mutex_lock (mem_profile);
+ for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
+ local_allocations[i] = allocations[i];
+ local_allocated_mem = allocated_mem;
+ local_freed_mem = freed_mem;
+ g_mutex_unlock (mem_profile);
+
for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
- if (allocations[i] > 0)
+ if (local_allocations[i] > 0)
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
- "%lu allocations of %d bytes\n", allocations[i], i + 1);
+ "%lu allocations of %d bytes\n", local_allocations[i], i + 1);
- if (allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
+ if (local_allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
"%lu allocations of greater than %d bytes\n",
- allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
- g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated\n", allocated_mem);
- g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed\n", freed_mem);
- g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use\n", allocated_mem - freed_mem);
+ local_allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated\n", local_allocated_mem);
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed\n", local_freed_mem);
+ g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use\n", local_allocated_mem - local_freed_mem);
#endif /* ENABLE_MEM_PROFILE */
}
@@ -460,11 +494,13 @@ g_mem_chunk_new (gchar *name,
mem_chunk->area_size += mem_chunk->atom_size - (mem_chunk->area_size % mem_chunk->atom_size);
*/
+ g_mutex_lock (mem_chunks_lock);
mem_chunk->next = mem_chunks;
mem_chunk->prev = NULL;
if (mem_chunks)
mem_chunks->prev = mem_chunk;
mem_chunks = mem_chunk;
+ g_mutex_unlock (mem_chunks_lock);
LEAVE_MEM_CHUNK_ROUTINE();
@@ -497,8 +533,10 @@ g_mem_chunk_destroy (GMemChunk *mem_chunk)
if (rmem_chunk->prev)
rmem_chunk->prev->next = rmem_chunk->next;
+ g_mutex_lock (mem_chunks_lock);
if (rmem_chunk == mem_chunks)
mem_chunks = mem_chunks->next;
+ g_mutex_unlock (mem_chunks_lock);
if (rmem_chunk->type == G_ALLOC_AND_FREE)
g_tree_destroy (rmem_chunk->mem_tree);
@@ -826,21 +864,26 @@ g_mem_chunk_info (void)
gint count;
count = 0;
+ g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
while (mem_chunk)
{
count += 1;
mem_chunk = mem_chunk->next;
}
+ g_mutex_unlock (mem_chunks_lock);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%d mem chunks\n", count);
+ g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
+ g_mutex_unlock (mem_chunks_lock);
+
while (mem_chunk)
{
g_mem_chunk_print ((GMemChunk*) mem_chunk);
mem_chunk = mem_chunk->next;
- }
+ }
}
void
@@ -848,7 +891,9 @@ g_blow_chunks (void)
{
GRealMemChunk *mem_chunk;
+ g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
+ g_mutex_unlock (mem_chunks_lock);
while (mem_chunk)
{
g_mem_chunk_clean ((GMemChunk*) mem_chunk);
@@ -940,3 +985,13 @@ g_allocator_free (GAllocator *allocator)
g_free (allocator);
}
+
+void
+g_mem_init (void)
+{
+ mem_chunks_lock = g_mutex_new();
+#ifdef ENABLE_MEM_PROFILE
+ mem_profile_lock = g_mutex_new();
+ allocating_for_mem_chunk = g_private_new(NULL);
+#endif
+}
diff --git a/glib/gmessages.c b/glib/gmessages.c
index e0c6eacb1..eb8aed7a8 100644
--- a/glib/gmessages.c
+++ b/glib/gmessages.c
@@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -31,7 +35,7 @@
#endif
#ifdef NATIVE_WIN32
-/* Just use stdio. If we're out of memroy, we're hosed anyway. */
+/* Just use stdio. If we're out of memory, we're hosed anyway. */
#undef write
static inline int
@@ -67,6 +71,9 @@ struct _GLogHandler
/* --- variables --- */
+
+static GMutex* g_messages_lock = NULL;
+
const gchar *g_log_domain_glib = "GLib";
static GLogDomain *g_log_domains = NULL;
static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
@@ -76,20 +83,27 @@ static GErrorFunc glib_error_func = NULL;
static GWarningFunc glib_warning_func = NULL;
static GPrintFunc glib_message_func = NULL;
+static GPrivate* g_log_depth = NULL;
+
/* --- functions --- */
static inline GLogDomain*
g_log_find_domain (const gchar *log_domain)
{
register GLogDomain *domain;
-
+
+ g_mutex_lock (g_messages_lock);
domain = g_log_domains;
while (domain)
{
if (strcmp (domain->log_domain, log_domain) == 0)
- return domain;
+ {
+ g_mutex_unlock (g_messages_lock);
+ return domain;
+ }
domain = domain->next;
}
+ g_mutex_unlock (g_messages_lock);
return NULL;
}
@@ -102,8 +116,11 @@ g_log_domain_new (const gchar *log_domain)
domain->log_domain = g_strdup (log_domain);
domain->fatal_mask = G_LOG_FATAL_MASK;
domain->handlers = NULL;
+
+ g_mutex_lock (g_messages_lock);
domain->next = g_log_domains;
g_log_domains = domain;
+ g_mutex_unlock (g_messages_lock);
return domain;
}
@@ -116,7 +133,9 @@ g_log_domain_check_free (GLogDomain *domain)
{
register GLogDomain *last, *work;
- last = NULL;
+ last = NULL;
+
+ g_mutex_lock (g_messages_lock);
work = g_log_domains;
while (work)
{
@@ -131,7 +150,8 @@ g_log_domain_check_free (GLogDomain *domain)
break;
}
work = work->next;
- }
+ }
+ g_mutex_unlock (g_messages_lock);
}
}
@@ -170,8 +190,10 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask)
/* remove bogus flag */
fatal_mask &= ~G_LOG_FLAG_FATAL;
+ g_mutex_lock (g_messages_lock);
old_mask = g_log_always_fatal;
g_log_always_fatal = fatal_mask;
+ g_mutex_unlock (g_messages_lock);
return old_mask;
}
@@ -223,7 +245,9 @@ g_log_set_handler (const gchar *log_domain,
domain = g_log_domain_new (log_domain);
handler = g_new (GLogHandler, 1);
+ g_mutex_lock (g_messages_lock);
handler->id = ++handler_id;
+ g_mutex_unlock (g_messages_lock);
handler->log_level = log_levels;
handler->log_func = log_func;
handler->data = user_data;
@@ -311,19 +335,25 @@ g_logv (const gchar *log_domain,
test_level = 1 << i;
if (log_level & test_level)
{
- static guint g_log_depth = 0;
+ guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
GLogDomain *domain;
GLogFunc log_func;
gpointer data = NULL;
domain = g_log_find_domain (log_domain ? log_domain : "");
- if (g_log_depth++)
+ if (depth)
test_level |= G_LOG_FLAG_RECURSION;
- if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | g_log_always_fatal) &
- test_level) != 0)
- test_level |= G_LOG_FLAG_FATAL;
+ depth++;
+ g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
+
+ g_mutex_lock (g_messages_lock);
+ if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) |
+ g_log_always_fatal) & test_level) != 0)
+ test_level |= G_LOG_FLAG_FATAL;
+ g_mutex_unlock (g_messages_lock);
+
log_func = g_log_domain_get_handler (domain, test_level, &data);
log_func (log_domain, test_level, buffer, data);
@@ -332,7 +362,8 @@ g_logv (const gchar *log_domain,
if (test_level & G_LOG_FLAG_FATAL)
abort ();
- g_log_depth--;
+ depth--;
+ g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
}
}
}
@@ -362,8 +393,11 @@ g_log_default_handler (const gchar *log_domain,
gint fd;
#endif
gboolean in_recursion;
- gboolean is_fatal;
-
+ gboolean is_fatal;
+ GErrorFunc local_glib_error_func;
+ GWarningFunc local_glib_warning_func;
+ GPrintFunc local_glib_message_func;
+
in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
log_level &= G_LOG_LEVEL_MASK;
@@ -380,13 +414,19 @@ g_log_default_handler (const gchar *log_domain,
fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
#endif
+ g_mutex_lock (g_messages_lock);
+ local_glib_error_func = glib_error_func;
+ local_glib_warning_func = glib_warning_func;
+ local_glib_message_func = glib_message_func;
+ g_mutex_unlock (g_messages_lock);
+
switch (log_level)
{
case G_LOG_LEVEL_ERROR:
- if (!log_domain && glib_error_func)
+ if (!log_domain && local_glib_error_func)
{
/* compatibility code */
- glib_error_func (message);
+ local_glib_error_func (message);
return;
}
/* use write(2) for output, in case we are out of memeory */
@@ -428,10 +468,10 @@ g_log_default_handler (const gchar *log_domain,
write (fd, "\n", 1);
break;
case G_LOG_LEVEL_WARNING:
- if (!log_domain && glib_warning_func)
+ if (!log_domain && local_glib_warning_func)
{
/* compatibility code */
- glib_warning_func (message);
+ local_glib_warning_func (message);
return;
}
if (log_domain)
@@ -453,10 +493,10 @@ g_log_default_handler (const gchar *log_domain,
write (fd, "\n", 1);
break;
case G_LOG_LEVEL_MESSAGE:
- if (!log_domain && glib_message_func)
+ if (!log_domain && local_glib_message_func)
{
/* compatibility code */
- glib_message_func (message);
+ local_glib_message_func (message);
return;
}
if (log_domain)
@@ -553,8 +593,10 @@ g_set_print_handler (GPrintFunc func)
{
GPrintFunc old_print_func;
+ g_mutex_lock (g_messages_lock);
old_print_func = glib_print_func;
glib_print_func = func;
+ g_mutex_unlock (g_messages_lock);
return old_print_func;
}
@@ -565,6 +607,7 @@ g_print (const gchar *format,
{
va_list args;
gchar *string;
+ GPrintFunc local_glib_print_func;
g_return_if_fail (format != NULL);
@@ -572,8 +615,12 @@ g_print (const gchar *format,
string = g_strdup_vprintf (format, args);
va_end (args);
- if (glib_print_func)
- glib_print_func (string);
+ g_mutex_lock (g_messages_lock);
+ local_glib_print_func = glib_print_func;
+ g_mutex_unlock (g_messages_lock);
+
+ if (local_glib_print_func)
+ local_glib_print_func (string);
else
{
fputs (string, stdout);
@@ -587,8 +634,10 @@ g_set_printerr_handler (GPrintFunc func)
{
GPrintFunc old_printerr_func;
+ g_mutex_lock (g_messages_lock);
old_printerr_func = glib_printerr_func;
glib_printerr_func = func;
+ g_mutex_unlock (g_messages_lock);
return old_printerr_func;
}
@@ -599,6 +648,7 @@ g_printerr (const gchar *format,
{
va_list args;
gchar *string;
+ GPrintFunc local_glib_printerr_func;
g_return_if_fail (format != NULL);
@@ -606,8 +656,12 @@ g_printerr (const gchar *format,
string = g_strdup_vprintf (format, args);
va_end (args);
- if (glib_printerr_func)
- glib_printerr_func (string);
+ g_mutex_lock (g_messages_lock);
+ local_glib_printerr_func = glib_printerr_func;
+ g_mutex_unlock (g_messages_lock);
+
+ if (local_glib_printerr_func)
+ local_glib_printerr_func (string);
else
{
fputs (string, stderr);
@@ -622,9 +676,11 @@ g_set_error_handler (GErrorFunc func)
{
GErrorFunc old_error_func;
+ g_mutex_lock (g_messages_lock);
old_error_func = glib_error_func;
glib_error_func = func;
-
+ g_mutex_unlock (g_messages_lock);
+
return old_error_func;
}
@@ -634,8 +690,10 @@ g_set_warning_handler (GWarningFunc func)
{
GWarningFunc old_warning_func;
+ g_mutex_lock (g_messages_lock);
old_warning_func = glib_warning_func;
glib_warning_func = func;
+ g_mutex_unlock (g_messages_lock);
return old_warning_func;
}
@@ -646,8 +704,17 @@ g_set_message_handler (GPrintFunc func)
{
GPrintFunc old_message_func;
+ g_mutex_lock (g_messages_lock);
old_message_func = glib_message_func;
glib_message_func = func;
+ g_mutex_unlock (g_messages_lock);
return old_message_func;
}
+
+void
+g_messages_init (void)
+{
+ g_messages_lock = g_mutex_new();
+ g_log_depth = g_private_new(NULL);
+}
diff --git a/glib/gnode.c b/glib/gnode.c
index 9f6e544ba..089a4996d 100644
--- a/glib/gnode.c
+++ b/glib/gnode.c
@@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
/* node allocation
@@ -34,10 +39,12 @@ struct _GAllocator /* from gmem.c */
GNode *free_nodes; /* implementation specific */
};
+static G_LOCK_DEFINE(current_allocator);
static GAllocator *current_allocator = NULL;
-void
-g_node_push_allocator (GAllocator *allocator)
+/* HOLDS: current_allocator_lock */
+static void
+g_node_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@@ -62,13 +69,22 @@ g_node_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
+}
+
+void
+g_node_push_allocator (GAllocator *allocator)
+{
+ g_node_validate_allocator ( allocator );
+ g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
+ g_unlock (current_allocator);
}
void
g_node_pop_allocator (void)
{
+ g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@@ -78,6 +94,7 @@ g_node_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
+ g_unlock (current_allocator);
}
@@ -87,9 +104,15 @@ g_node_new (gpointer data)
{
GNode *node;
+ g_lock (current_allocator);
if (!current_allocator)
- g_node_push_allocator (g_allocator_new ("GLib default GNode allocator", 1024));
-
+ {
+ GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
+ 1024);
+ g_node_validate_allocator (allocator);
+ allocator->last = NULL;
+ current_allocator = allocator;
+ }
if (!current_allocator->free_nodes)
node = g_chunk_new (GNode, current_allocator->mem_chunk);
else
@@ -97,6 +120,7 @@ g_node_new (gpointer data)
node = current_allocator->free_nodes;
current_allocator->free_nodes = node->next;
}
+ g_unlock (current_allocator);
node->data = data;
node->next = NULL;
@@ -122,9 +146,11 @@ g_nodes_free (GNode *node)
else
break;
}
-
+
+ g_lock (current_allocator);
parent->next = current_allocator->free_nodes;
current_allocator->free_nodes = node;
+ g_unlock (current_allocator);
}
void
diff --git a/glib/gprimes.c b/glib/gprimes.c
index 3d45c1ef7..404ebd605 100644
--- a/glib/gprimes.c
+++ b/glib/gprimes.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
static const guint g_primes[] =
diff --git a/glib/grel.c b/glib/grel.c
index 5fdf88098..544da6bfc 100644
--- a/glib/grel.c
+++ b/glib/grel.c
@@ -15,6 +15,11 @@
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
#include <stdarg.h>
#include <string.h>
diff --git a/glib/gscanner.c b/glib/gscanner.c
index 02985a7f7..c6fd0dd4e 100644
--- a/glib/gscanner.c
+++ b/glib/gscanner.c
@@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#define __gscanner_c__
#ifdef HAVE_CONFIG_H
diff --git a/glib/gslist.c b/glib/gslist.c
index 4efe2a575..1ed517ff6 100644
--- a/glib/gslist.c
+++ b/glib/gslist.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
@@ -30,10 +35,12 @@ struct _GAllocator /* from gmem.c */
GSList *free_lists; /* implementation specific */
};
+static G_LOCK_DEFINE(current_allocator);
static GAllocator *current_allocator = NULL;
-void
-g_slist_push_allocator (GAllocator *allocator)
+/* HOLDS: current_allocator_lock */
+static void
+g_slist_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@@ -58,13 +65,22 @@ g_slist_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
+}
+
+void
+g_slist_push_allocator (GAllocator *allocator)
+{
+ g_slist_validate_allocator (allocator);
+ g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
+ g_unlock (current_allocator);
}
void
g_slist_pop_allocator (void)
{
+ g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@@ -74,6 +90,7 @@ g_slist_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
+ g_unlock (current_allocator);
}
GSList*
@@ -81,9 +98,15 @@ g_slist_alloc (void)
{
GSList *list;
+ g_lock (current_allocator);
if (!current_allocator)
- g_slist_push_allocator (g_allocator_new ("GLib default GSList allocator", 1024));
-
+ {
+ GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
+ 1024);
+ g_slist_validate_allocator (allocator);
+ allocator->last = NULL;
+ current_allocator = allocator;
+ }
if (!current_allocator->free_lists)
{
list = g_chunk_new (GSList, current_allocator->mem_chunk);
@@ -103,6 +126,8 @@ g_slist_alloc (void)
current_allocator->free_lists = list->next;
}
}
+ g_unlock (current_allocator);
+
list->next = NULL;
return list;
@@ -114,8 +139,10 @@ g_slist_free (GSList *list)
if (list)
{
list->data = list->next;
+ g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
+ g_unlock (current_allocator);
}
}
@@ -125,8 +152,10 @@ g_slist_free_1 (GSList *list)
if (list)
{
list->data = NULL;
+ g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
+ g_unlock (current_allocator);
}
}
diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c
index ad28978ee..e154c56dc 100644
--- a/glib/gstrfuncs.c
+++ b/glib/gstrfuncs.c
@@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -208,7 +212,8 @@ g_strtod (const gchar *nptr,
gchar*
g_strerror (gint errnum)
{
- static char msg[64];
+ static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
+ char *msg;
#ifdef HAVE_STRERROR
return strerror (errnum);
@@ -634,7 +639,14 @@ g_strerror (gint errnum)
if ((errnum > 0) && (errnum <= sys_nerr))
return sys_errlist [errnum];
#endif /* NO_SYS_ERRLIST */
-
+
+ msg = g_static_private_get (&msg_private);
+ if( !msg )
+ {
+ msg = g_new( gchar, 64 );
+ g_static_private_set (&msg_private, msg, g_free);
+ }
+
sprintf (msg, "unknown error (%d)", errnum);
return msg;
}
@@ -642,7 +654,8 @@ g_strerror (gint errnum)
gchar*
g_strsignal (gint signum)
{
- static char msg[64];
+ static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
+ char *msg;
#ifdef HAVE_STRSIGNAL
extern char *strsignal (int sig);
@@ -748,6 +761,13 @@ g_strsignal (gint signum)
extern char *sys_siglist[];
return sys_siglist [signum];
#endif /* NO_SYS_SIGLIST */
+
+ msg = g_static_private_get (&msg_private);
+ if( !msg )
+ {
+ msg = g_new( gchar, 64 );
+ g_static_private_set (&msg_private, msg, g_free);
+ }
sprintf (msg, "unknown signal (%d)", signum);
return msg;
diff --git a/glib/gstring.c b/glib/gstring.c
index fa84fe7a2..312a54060 100644
--- a/glib/gstring.c
+++ b/glib/gstring.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@@ -43,7 +48,7 @@ struct _GRealString
gint alloc;
};
-
+static G_LOCK_DEFINE(string_mem_chunk);
static GMemChunk *string_mem_chunk = NULL;
/* Hash Functions.
@@ -202,12 +207,14 @@ g_string_sized_new (guint dfl_size)
{
GRealString *string;
+ g_lock (string_mem_chunk);
if (!string_mem_chunk)
string_mem_chunk = g_mem_chunk_new ("string mem chunk",
sizeof (GRealString),
1024, G_ALLOC_AND_FREE);
string = g_chunk_new (GRealString, string_mem_chunk);
+ g_unlock (string_mem_chunk);
string->alloc = 0;
string->len = 0;
@@ -241,7 +248,9 @@ g_string_free (GString *string,
if (free_segment)
g_free (string->str);
+ g_lock (string_mem_chunk);
g_mem_chunk_free (string_mem_chunk, string);
+ g_unlock (string_mem_chunk);
}
GString*
diff --git a/glib/gtimer.c b/glib/gtimer.c
index 6e58fa0bd..0b6e86a8a 100644
--- a/glib/gtimer.c
+++ b/glib/gtimer.c
@@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
diff --git a/glib/gtree.c b/glib/gtree.c
index 4d9e98a0b..006f15db7 100644
--- a/glib/gtree.c
+++ b/glib/gtree.c
@@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
+
+/*
+ * MT safe
+ */
+
#include "glib.h"
@@ -78,6 +83,7 @@ static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
static void g_tree_node_check (GTreeNode *node);
+static G_LOCK_DEFINE(g_tree_global);
static GMemChunk *node_mem_chunk = NULL;
static GTreeNode *node_free_list = NULL;
@@ -88,6 +94,7 @@ g_tree_node_new (gpointer key,
{
GTreeNode *node;
+ g_lock (g_tree_global);
if (node_free_list)
{
node = node_free_list;
@@ -102,7 +109,8 @@ g_tree_node_new (gpointer key,
G_ALLOC_ONLY);
node = g_chunk_new (GTreeNode, node_mem_chunk);
- }
+ }
+ g_unlock (g_tree_global);
node->balance = 0;
node->left = NULL;
@@ -120,9 +128,11 @@ g_tree_node_destroy (GTreeNode *node)
{
g_tree_node_destroy (node->right);
g_tree_node_destroy (node->left);
+ g_lock (g_tree_global);
node->right = node_free_list;
node_free_list = node;
- }
+ g_unlock (g_tree_global);
+ }
}
@@ -375,9 +385,11 @@ g_tree_node_remove (GTreeNode *node,
node = g_tree_node_restore_right_balance (new_root, old_balance);
}
+ g_lock (g_tree_global);
garbage->right = node_free_list;
node_free_list = garbage;
- }
+ g_unlock (g_tree_global);
+ }
else if (cmp < 0)
{
if (node->left)
diff --git a/glib/gutils.c b/glib/gutils.c
index cc6594937..9a91199b6 100644
--- a/glib/gutils.c
+++ b/glib/gutils.c
@@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * MT safe for the unix part, FIXME: make the win32 part MT safe as well.
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -367,11 +371,14 @@ g_getenv (const gchar *variable)
#endif
}
+static G_LOCK_DEFINE(g_utils_global);
+
static gchar *g_tmp_dir = NULL;
static gchar *g_user_name = NULL;
static gchar *g_real_name = NULL;
static gchar *g_home_dir = NULL;
+/* HOLDS: g_utils_global_lock */
static void
g_get_any_init (void)
{
@@ -442,14 +449,16 @@ g_get_any_init (void)
g_home_dir = NULL;
# endif /* !NATIVE_WIN32 */
#endif /* !HAVE_PWD_H */
- }
+ }
}
gchar*
g_get_user_name (void)
{
+ g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
+ g_unlock (g_utils_global);
return g_user_name;
}
@@ -457,9 +466,11 @@ g_get_user_name (void)
gchar*
g_get_real_name (void)
{
+ g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
-
+ g_unlock (g_utils_global);
+
return g_real_name;
}
@@ -472,8 +483,10 @@ g_get_real_name (void)
gchar*
g_get_home_dir (void)
{
+ g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
+ g_unlock (g_utils_global);
return g_home_dir;
}
@@ -488,8 +501,10 @@ g_get_home_dir (void)
gchar*
g_get_tmp_dir (void)
{
+ g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
+ g_unlock (g_utils_global);
return g_tmp_dir;
}
@@ -499,16 +514,25 @@ static gchar *g_prgname = NULL;
gchar*
g_get_prgname (void)
{
- return g_prgname;
+ gchar* retval;
+
+ g_lock (g_utils_global);
+ retval = g_prgname;
+ g_unlock (g_utils_global);
+
+ return retval;
}
void
g_set_prgname (const gchar *prgname)
{
- gchar *c = g_prgname;
-
+ gchar *c;
+
+ g_lock (g_utils_global);
+ c = g_prgname;
g_prgname = g_strdup (prgname);
g_free (c);
+ g_unlock (g_utils_global);
}
guint