? gmutex.c
? gthread
? libgthread.la
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/glib/Makefile.am,v
retrieving revision 1.18
diff -u -r1.18 Makefile.am
--- Makefile.am	1998/12/02 23:45:17	1.18
+++ Makefile.am	1998/12/03 15:02:33
@@ -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 @@
 		gstring.c	\
 		gstrfuncs.c	\
 		gscanner.c	\
-		gutils.c
+		gutils.c	\
+		gmutex.c
 
 include_HEADERS = \
 		glib.h
Index: acconfig.h
===================================================================
RCS file: /cvs/gnome/glib/acconfig.h,v
retrieving revision 1.6
diff -u -r1.6 acconfig.h
--- acconfig.h	1998/12/02 14:55:20	1.6
+++ acconfig.h	1998/12/03 15:02:33
@@ -84,6 +84,8 @@
 #undef WIN32
 #undef NATIVE_WIN32
 
+#undef G_THREAD_SOURCE
+
 /* #undef PACKAGE */
 /* #undef VERSION */
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/glib/configure.in,v
retrieving revision 1.31
diff -u -r1.31 configure.in
--- configure.in	1998/12/02 14:55:21	1.31
+++ configure.in	1998/12/03 15:02:38
@@ -508,6 +508,150 @@
 AC_SUBST(G_MODULE_NEED_USCORE)
 AC_SUBST(GLIB_DEBUG_FLAGS)
 
+
+dnl ***********************
+dnl *** g_thread checks ***
+dnl ***********************
+
+AC_ARG_ENABLE(thread, [  --enable-thread=[none/posix/solaris] specify a thread implementation to use.],,)
+
+dnl error and warning message
+dnl *************************
+
+THREAD_NO_IMPLEMENTATION="You do not have any known thread system on your
+                computer. glib will not be thread safe on your computer."
+
+THREAD_UNKNOWN_COMPILER="Your compiler is not known, so I cannot
+                determine the necessary compiler options to compile programs 
+                which are using threads. Please provide such information."
+
+FLAG_DOES_NOT_WORK="I can't find the MACRO, that enables thread safety on your
+                platform (normaly it's "_REENTRANT"). I'll not use any flag on
+                compilation now, but then your programs might not work. 
+                Please provide information on how it is done on your system."
+
+LIBS_NOT_FOUND_1="I can't find the libraries for the thread implementation
+		"
+
+LIBS_NOT_FOUND_2=". Please choose another thread implementation or 
+		provide informationon your thread implementation."
+
+dnl determination of thread implementation
+dnl ***************************************
+
+if test x"$enable_thread" = x; then
+        case $host in
+                *-*-solaris*)
+                        AC_CHECK_LIB(thread,cond_init,enable_thread=solaris)
+                        ;;
+        esac
+        if test x"$enable_thread" = x; then
+                AC_CHECK_LIB(pthread,pthread_cond_init,enable_thread=posix)
+     	        AC_CHECK_LIB(pthreads,pthread_attr_init,enable_thread=posix)
+	fi
+fi
+
+AC_MSG_CHECKING(for thread implementation)
+
+if test x"$enable_thread" = x; then
+        enable_thread=none
+        AC_MSG_WARN($THREAD_NO_IMPLEMENTATION)
+fi
+
+AC_MSG_RESULT($enable_thread)
+
+dnl determination of G_THREAD_LIBS
+dnl ******************************
+
+G_THREAD_LIBS=
+
+case $enable_thread in
+        posix)
+		G_THREAD_LIBS=error
+		AC_CHECK_LIB(pthreads,pthread_cond_init,
+			     G_THREAD_LIBS="-lpthreads") 
+                AC_CHECK_LIB(pthread,pthread_cond_init,
+			     G_THREAD_LIBS="-lpthread")     	       	
+                ;;
+        solaris)
+		G_THREAD_LIBS=error
+                AC_CHECK_LIB(thread,cond_init,G_THREAD_LIBS="-lthread")
+		# solaris has a broken initializer for mutexes, if we find it,
+		# we will replace it.
+		AC_MSG_CHECKING(for broken solaris mutex initialization)
+		AC_EGREP_CPP([ *begin *{ *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *} *end *],
+		             [#include <thread.h>
+			     begin DEFAULTMUTEX end],
+			     [solaris_mutex_init_broken=yes],
+			     [solaris_mutex_init_broken=no])
+		AC_MSG_RESULT($solaris_mutex_init_broken)
+                ;;
+        none)
+                ;;
+        *)
+		G_THREAD_LIBS=error
+                ;;
+esac
+
+if test "x$G_THREAD_LIBS" = xerror; then
+        AC_MSG_ERROR($LIBS_NOT_FOUND_1$enable_thread$LIBS_NOT_FOUND_2)
+fi
+
+AC_MSG_CHECKING(necessary linker options)
+AC_MSG_RESULT($G_THREAD_LIBS)
+
+dnl determination of G_THREAD_CFLAGS
+dnl ********************************
+
+if test x"$enable_thread" != xnone; then
+	G_THREAD_CFLAGS="-D_REENTRANT" # good default
+
+	case $host in
+ 	       -aix*)
+			# FIXME: can somebody confirm this -D_THREAD_SAFE ???
+			G_THREAD_CFLAGS="$G_THREAD_CFLAGS -D_THREAD_SAFE"
+			if test x"$GCC" = xyes; then 
+                	        G_THREAD_CFLAGS="$G_THREAD_CFLAGS -mthreads"
+			fi
+			;;
+	esac
+
+	# if we are not finding the ctime_r function, then we probably are 
+	# not using the proper multithread flag
+	old_CPPFLAGS=$CPPFLAGS
+	CPPFLAGS="$CPPFLAGS $G_THREAD_CFLAGS"
+	AC_EGREP_HEADER([[^a-zA-Z_]ctime_r[^a-zA-Z_]], time.h, , 
+        	G_THREAD_CFLAGS=
+        	AC_MSG_WARN($FLAG_DOES_NOT_WORK))
+	CPPFLAGS=$old_CPPFLAGS
+                
+	if test x"$GCC" = xyes; then 	
+		# older gcc's do not know the -fstack-check option and will
+		# stop compiling, so just check this here 
+		old_CPPFLAGS="$CPPFLAGS"
+		CPPFLAGS="$CPPFLAGS -fstack-check"
+		AC_TRY_COMPILE(,,
+			G_THREAD_CFLAGS="$G_THREAD_CFLAGS -fstack-check")
+		CPPFLAGS=$old_CPPFLAGS
+	else
+        	AC_MSG_WARN($THREAD_UNKNOWN_COMPILER)
+	fi
+
+	AC_MSG_CHECKING(necessary compiler options)
+
+	AC_MSG_RESULT($G_THREAD_CFLAGS)
+else
+        G_THREAD_CFLAGS=
+fi
+
+AC_DEFINE_UNQUOTED(G_THREAD_SOURCE,"gthread-$enable_thread.c")
+AC_SUBST(G_THREAD_CFLAGS)
+AC_SUBST(G_THREAD_LIBS)
+
+dnl ******************************
+dnl *** output the whole stuff ***
+dnl ******************************
+
 AC_OUTPUT_COMMANDS([
 
 ## Generate `glibconfig.h' in two cases
@@ -550,6 +694,9 @@
   if test x$glib_values_h = xyes; then
     echo '#include <values.h>' >> $outfile
   fi
+  if test x$g_mutex_header_file != x; then
+    echo '#include <'"$g_mutex_header_file"'>' >> $outfile
+  fi
   if test x$glib_sys_poll_h = xyes; then
     echo '#include <sys/poll.h>' >> $outfile
   fi
@@ -623,6 +770,34 @@
 #define G_BYTE_ORDER $g_byte_order
 outfile_EOF
 
+cat >>$outfile <<outfile_EOF                                               
+
+/* definitions for the default mutex implementation */
+outfile_EOF
+
+  if test x$g_mutex_has_default = xyes; then
+cat >>$outfile <<outfile_EOF                                               
+
+typedef struct _GStaticMutex GStaticMutex;
+struct _GStaticMutex 
+{
+  $g_mutex_default_type default_mutex;
+  struct _GMutex* runtime_mutex;
+};
+#define G_STATIC_MUTEX_INIT { $g_mutex_default_init, NULL }
+#define g_static_mutex_get_mutex(mutex) \
+  ( g_mutex_use_default_impl ? (GMutex*)&mutex.default_mutex : \
+    g_static_mutex_get_mutex_impl(&mutex.runtime_mutex) )
+outfile_EOF
+  else
+cat >>$outfile <<outfile_EOF                                               
+
+typedef GMutex* GStaticMutex;
+#define G_STATIC_MUTEX_INIT NULL
+#define g_static_mutex_get_mutex(mutex) g_static_mutex_get_mutex_impl(&mutex)
+outfile_EOF
+  fi
+
   g_bit_sizes="16 32"
   if test -n "$gint64"; then
     g_bit_sizes="$g_bit_sizes 64"
@@ -837,6 +1012,28 @@
   glib_wc="\$glib_wc
 #define G_HAVE_BROKEN_WCTYPE 1"
 fi
+
+case $enable_thread in
+	posix)
+		g_mutex_has_default=yes
+		g_mutex_default_type='pthread_mutex_t'
+		g_mutex_default_init='PTHREAD_MUTEX_INITIALIZER'
+		g_mutex_header_file='pthread.h'
+		;;
+	solaris)
+		g_mutex_has_default=yes
+		g_mutex_default_type='mutex_t'
+		if test x$solaris_mutex_init_broken = xyes; then
+		  g_mutex_default_init="{ { { 0, 0, 0, 0 }, USYNC_THREAD }, { { { 0, 0, 0, 0, 0, 0, 0, 0 } } }, 0}"
+		else
+		  g_mutex_default_init="DEFAULTMUTEX"
+		fi
+		g_mutex_header_file='thread.h'
+		;;
+	*)		
+		g_mutex_has_default=no
+		;;
+esac
 ])
 
 AC_OUTPUT([
@@ -844,6 +1041,7 @@
 glib-config
 gmodule/gmoduleconf.h
 gmodule/Makefile
+gthread/Makefile
 docs/Makefile
 ],[case "$CONFIG_FILES" in
 *glib-config*)chmod +x glib-config;;
Index: garray.c
===================================================================
RCS file: /cvs/gnome/glib/garray.c,v
retrieving revision 1.9
diff -u -r1.9 garray.c
--- garray.c	1998/11/23 15:02:43	1.9
+++ garray.c	1998/12/03 15:02:38
@@ -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,10 +45,9 @@
 static void g_array_maybe_expand (GRealArray *array,
 				  gint        len);
 
-
 static GMemChunk *array_mem_chunk = NULL;
+static G_LOCK(array_mem_chunk);
 
-
 GArray*
 g_array_new (gboolean zero_terminated,
 	     gboolean clear,
@@ -51,12 +55,14 @@
 {
   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 @@
   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 @@
 static void g_ptr_array_maybe_expand (GRealPtrArray *array,
 				      gint           len);
 
-
 static GMemChunk *ptr_array_mem_chunk = NULL;
-
+static G_LOCK(ptr_array_mem_chunk);
 
 
 GPtrArray*
@@ -251,12 +258,14 @@
 {
   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 @@
   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
Index: gcache.c
===================================================================
RCS file: /cvs/gnome/glib/gcache.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 gcache.c
--- gcache.c	1998/06/10 23:21:13	1.1.1.1
+++ gcache.c	1998/12/03 15:02:38
@@ -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 GMemChunk *node_mem_chunk = NULL;
-
+static G_LOCK(node_mem_chunk);
 
 GCache*
 g_cache_new (GCacheNewFunc      value_new_func,
@@ -193,11 +198,13 @@
 {
   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 @@
 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);
 }
Index: gcompletion.c
===================================================================
RCS file: /cvs/gnome/glib/gcompletion.c,v
retrieving revision 1.2
diff -u -r1.2 gcompletion.c
--- gcompletion.c	1998/07/25 03:02:57	1.2
+++ gcompletion.c	1998/12/03 15:02:38
@@ -17,6 +17,10 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/* 
+ * MT safe
+ */
+
 #include "glib.h"
 #include <string.h>
 
Index: gdataset.c
===================================================================
RCS file: /cvs/gnome/glib/gdataset.c,v
retrieving revision 1.9
diff -u -r1.9 gdataset.c
--- gdataset.c	1998/11/24 12:18:15	1.9
+++ gdataset.c	1998/12/03 15:02:38
@@ -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"
 
@@ -48,6 +54,8 @@
 
 
 /* --- prototypes --- */
+/* all of the following static functions must be called, while holding
+   the g_dataset_global lock */
 static inline GDataset*	g_dataset_lookup		(gconstpointer	  dataset_location);
 static inline void	g_datalist_clear_i		(GData		**datalist);
 static void		g_dataset_destroy_internal	(GDataset	 *dataset);
@@ -57,16 +65,22 @@
 							 GDestroyNotify   destroy_func,
 							 GDataset	 *dataset);
 static void		g_data_initialize		(void);
+/* the following static function must be called, while holding the
+   g_quark_global lock */
 static inline GQuark	g_quark_new			(gchar  	*string);
 
 
 /* --- variables --- */
+static G_LOCK(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(g_quark_global);
 static GHashTable   *g_quark_ht = NULL;
 static gchar       **g_quarks = NULL;
 static GQuark        g_quark_seq_id = 0;
@@ -109,11 +123,13 @@
 {
   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);
 }
 
 static inline GDataset*
@@ -158,6 +174,7 @@
 {
   g_return_if_fail (dataset_location != NULL);
   
+  g_lock(g_dataset_global);
   if (g_dataset_location_ht)
     {
       register GDataset *dataset;
@@ -166,6 +183,7 @@
       if (dataset)
 	g_dataset_destroy_internal (dataset);
     }
+  g_unlock(g_dataset_global);
 }
 
 static inline void
@@ -293,9 +311,10 @@
 	return;
     }
   
+  g_lock(g_dataset_global);
   if (!g_dataset_location_ht)
     g_data_initialize ();
-  
+ 
   dataset = g_dataset_lookup (dataset_location);
   if (!dataset)
     {
@@ -308,6 +327,7 @@
     }
   
   g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
+  g_unlock(g_dataset_global);
 }
 
 void
@@ -327,10 +347,12 @@
 	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 +361,7 @@
 {
   g_return_if_fail (dataset_location != NULL);
   
+  g_lock(g_dataset_global);
   if (key_id && g_dataset_location_ht)
     {
       GDataset *dataset;
@@ -346,7 +369,8 @@
       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 +379,10 @@
 {
   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 +391,7 @@
 {
   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 +403,14 @@
 	  
 	  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 +442,23 @@
   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
@@ -468,12 +505,15 @@
 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 = g_hash_table_lookup (g_quark_ht, string);
+  g_unlock(g_quark_global);
+  
+  return quark;
 }
 
 GQuark
@@ -483,6 +523,7 @@
   
   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 +534,7 @@
   
   if (!quark)
     quark = g_quark_new (g_strdup (string));
+  g_unlock(g_quark_global);
   
   return quark;
 }
@@ -504,6 +546,7 @@
   
   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,17 +557,21 @@
 
   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;
 }
 
 static inline GQuark
Index: gdate.c
===================================================================
RCS file: /cvs/gnome/glib/gdate.c,v
retrieving revision 1.5
diff -u -r1.5 gdate.c
--- gdate.c	1998/12/02 23:47:01	1.5
+++ gdate.c	1998/12/03 15:02:44
@@ -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 @@
   memset (d, 0x0, ndates*sizeof (GDate)); 
 }
 
+static G_LOCK(gdate_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 @@
 
 #define NUM_LEN 10
 
+/* must be called, while holding the gdate_global lock */
 static void
 g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
 {
@@ -488,7 +496,7 @@
               if (found != NULL)
                 {
                   pt->month = i;
-                  return;
+		  return;
                 }
             }
 	  
@@ -502,12 +510,13 @@
                   return;
                 }
             }
-	  
+
           ++i;
-        }
+        }      
     }
 }
 
+/* must be called, while holding the gdate_global lock */
 static void
 g_date_prepare_to_parse (const gchar *str, GDateParseTokens *pt)
 {
@@ -641,6 +650,8 @@
   /* set invalid */
   g_date_clear (d, 1);
   
+  g_lock(gdate_global);
+
   g_date_prepare_to_parse (str, &pt);
   
 #ifdef G_ENABLE_DEBUG
@@ -649,7 +660,11 @@
 #endif
   
   
-  if (pt.num_ints == 4) return; /* presumably a typo; bail out. */
+  if (pt.num_ints == 4) 
+    {
+      g_unlock(gdate_global);
+      return; /* presumably a typo; bail out. */
+    }
   
   if (pt.num_ints > 1)
     {
@@ -765,6 +780,7 @@
   else 
     g_message ("Rejected DMY %u %u %u", day, m, y);
 #endif
+  g_unlock(gdate_global);
 }
 
 void         
Index: gerror.c
===================================================================
RCS file: /cvs/gnome/glib/gerror.c,v
retrieving revision 1.5
diff -u -r1.5 gerror.c
--- gerror.c	1998/11/01 01:32:55	1.5
+++ gerror.c	1998/12/03 15:02:44
@@ -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
Index: ghash.c
===================================================================
RCS file: /cvs/gnome/glib/ghash.c,v
retrieving revision 1.10
diff -u -r1.10 ghash.c
--- ghash.c	1998/11/28 01:54:54	1.10
+++ ghash.c	1998/12/03 15:02:44
@@ -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_nodes_destroy	 (GHashNode	*hash_node);
 
 
+static G_LOCK(ghash_global);
+
 static GMemChunk *node_mem_chunk = NULL;
 static GHashNode *node_free_list = NULL;
 
@@ -338,6 +345,7 @@
 {
   GHashNode *hash_node;
   
+  g_lock(ghash_global);
   if (node_free_list)
     {
       hash_node = node_free_list;
@@ -352,6 +360,7 @@
       
       hash_node = g_chunk_new (GHashNode, node_mem_chunk);
     }
+  g_unlock(ghash_global);
   
   hash_node->key = key;
   hash_node->value = value;
@@ -363,8 +372,10 @@
 static void
 g_hash_node_destroy (GHashNode *hash_node)
 {
+  g_lock(ghash_global);
   hash_node->next = node_free_list;
   node_free_list = hash_node;
+  g_unlock(ghash_global);
 }
 
 static void
@@ -380,6 +391,8 @@
   while (node->next)
     node = node->next;
   
+  g_lock(ghash_global);
   node->next = node_free_list;
   node_free_list = hash_node;
+  g_unlock(ghash_global);
 }
Index: ghook.c
===================================================================
RCS file: /cvs/gnome/glib/ghook.c,v
retrieving revision 1.6
diff -u -r1.6 ghook.c
--- ghook.c	1998/11/30 07:08:53	1.6
+++ ghook.c	1998/12/03 15:02:45
@@ -19,6 +19,11 @@
  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+
+/* 
+ * MT safe
+ */
+
 #include	"glib.h"
 
 
Index: giochannel.c
===================================================================
RCS file: /cvs/gnome/glib/giochannel.c,v
retrieving revision 1.2
diff -u -r1.2 giochannel.c
--- giochannel.c	1998/12/02 14:55:22	1.2
+++ giochannel.c	1998/12/03 15:02:45
@@ -20,6 +20,10 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/* 
+ * MT safe
+ */
+
 #include "glib.h"
 #include <unistd.h>
 
Index: giounix.c
===================================================================
RCS file: /cvs/gnome/glib/giounix.c,v
retrieving revision 1.2
diff -u -r1.2 giounix.c
--- giounix.c	1998/12/02 14:55:23	1.2
+++ giounix.c	1998/12/03 15:02:46
@@ -20,6 +20,10 @@
  * Boston, MA 02111-1307, USA.
  */
 
+/* 
+ * MT safe
+ */
+
 #include "glib.h"
 #include <sys/types.h>
 #include <unistd.h>
Index: glib-config.in
===================================================================
RCS file: /cvs/gnome/glib/glib-config.in,v
retrieving revision 1.3
diff -u -r1.3 glib-config.in
--- glib-config.in	1998/09/15 19:08:07	1.3
+++ glib-config.in	1998/12/03 15:02:46
@@ -17,6 +17,7 @@
 Libraries:
 	glib
 	gmodule
+	gthread
 EOF
 	exit $1
 }
@@ -69,6 +70,9 @@
     gmodule)
       lib_gmodule=yes
       ;;
+    gthread)
+      lib_gthread=yes
+      ;;
     *)
       usage 1 1>&2
       ;;
@@ -83,7 +87,11 @@
 	echo $exec_prefix
 fi
 if test "$echo_cflags" = "yes"; then
-	echo -I@libdir@/glib/include $includes
+	cflags=""
+	if test "$lib_gthread" = "yes"; then
+		cflags="$cflags @G_THREAD_CFLAGS@"
+	fi
+	echo -I@libdir@/glib/include $includes $cflags
 fi
 if test "$echo_libs" = "yes"; then
 	libs=""
@@ -92,6 +100,9 @@
 	fi
 	if test "$lib_gmodule" = "yes"; then
 		libs="@G_MODULE_LDFLAGS@ -lgmodule $libs @G_MODULE_LIBS@"
+	fi
+	if test "$lib_gthread" = "yes"; then
+		libs="-lgthread $libs @G_THREAD_LIBS@"
 	fi
-	echo "-L@libdir@ $libs"
+	echo -L@libdir@ $libs
 fi
Index: glib.h
===================================================================
RCS file: /cvs/gnome/glib/glib.h,v
retrieving revision 1.86
diff -u -r1.86 glib.h
--- glib.h	1998/12/02 18:47:08	1.86
+++ glib.h	1998/12/03 15:02:52
@@ -2597,6 +2597,91 @@
 
 #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 */
+
+typedef struct _GMutex GMutex;
+typedef struct _GCond GCond;
+
+typedef struct _GMutexFunctions GMutexFunctions;
+struct _GMutexFunctions
+{
+  GMutex*  (*mutex_new)       ();
+  void     (*mutex_lock)      (GMutex* mutex);
+  gboolean (*mutex_try_lock)  (GMutex* mutex);
+  void     (*mutex_unlock)    (GMutex* mutex);
+  void     (*mutex_free)      (GMutex* mutex);
+  GCond*   (*cond_new)        ();
+  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);
+};
+
+GUTILS_C_VAR GMutexFunctions g_mutex_functions_for_glib_use;
+GUTILS_C_VAR gboolean g_mutex_use_default_impl;
+GUTILS_C_VAR gboolean g_mutex_supported;
+GUTILS_C_VAR gboolean g_cond_supported;
+GUTILS_C_VAR GMutex *g_mutex_protect_static_mutex_allocation;
+
+/* 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. */
+void g_thread_init(GMutexFunctions* 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 vetcor is ignored */
+gboolean g_thread_try_init(GMutexFunctions* 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_MUTEX_FUNC(name,fail,arg) \
+  (g_mutex_supported ? (*g_mutex_functions_for_glib_use.name)arg : (fail))
+#define G_USE_COND_FUNC(name,fail,arg) \
+  (g_cond_supported ? (*g_mutex_functions_for_glib_use.name)arg : (fail))
+
+/* keep in mind, all those mutexes ans static mutexes are not
+   recursive in general, don't rely on that */
+#define g_mutex_new() G_USE_MUTEX_FUNC(mutex_new,NULL,())
+#define g_mutex_lock(mutex) G_USE_MUTEX_FUNC(mutex_lock,(void)0,(mutex))
+#define g_mutex_try_lock(mutex) G_USE_MUTEX_FUNC(mutex_try_lock,TRUE,(mutex))
+#define g_mutex_unlock(mutex) G_USE_MUTEX_FUNC(mutex_unlock,(void)0,(mutex))
+#define g_mutex_free(mutex) G_USE_MUTEX_FUNC(mutex_free,(void)0,(mutex))
+#define g_cond_new() G_USE_COND_FUNC(cond_new,NULL,())
+#define g_cond_signal(cond) G_USE_COND_FUNC(cond_signal,(void)0,(cond))
+#define g_cond_broadcast(cond) G_USE_COND_FUNC(cond_broadcast,(void)0,(cond))
+#define g_cond_wait(cond,mutex) G_USE_COND_FUNC(cond_wait,(void)0,(cond,mutex))
+#define g_cond_timed_wait(cond,mutex,abs_time) \
+  G_USE_COND_FUNC(cond_timed_wait,TRUE,(cond,mutex,abs_time))
+#define g_cond_free(cond) G_USE_COND_FUNC(cond_free,(void)0,(cond))
+
+/* 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_try_lock(mutex) \
+  g_mutex_try_lock( g_static_mutex_get_mutex(mutex) )
+#define g_static_mutex_unlock(mutex) \
+  g_mutex_unlock( g_static_mutex_get_mutex(mutex) ) 
+
+/* these are some convenience macros, for using StaticMutex'es, you
+   define them by G_LOCK(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(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT 
+#define g_lock(name) g_static_mutex_lock(g_lock_name(name)) 
+#define g_trylock(name) g_static_mutex_try_lock(g_lock_name(name))
+#define g_unlock(name) g_static_mutex_unlock(g_lock_name(name))
 
 #ifdef __cplusplus
 }
Index: glist.c
===================================================================
RCS file: /cvs/gnome/glib/glist.c,v
retrieving revision 1.5
diff -u -r1.5 glist.c
--- glist.c	1998/12/02 14:55:25	1.5
+++ glist.c	1998/12/03 15:02:53
@@ -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,10 @@
 };
 
 static GAllocator	*current_allocator = NULL;
+static G_LOCK(current_allocator);
 
-void
-g_list_push_allocator (GAllocator *allocator)
+static void
+g_list_validate_allocator (GAllocator *allocator)
 {
   g_return_if_fail (allocator != NULL);
   g_return_if_fail (allocator->is_unused == TRUE);
@@ -58,13 +64,22 @@
     }
 
   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 +89,7 @@
       allocator->last = NULL;
       allocator->is_unused = TRUE;
     }
+  g_unlock(current_allocator);
 }
 
 GList*
@@ -81,9 +97,15 @@
 {
   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 +125,7 @@
 	  current_allocator->free_lists = list->next;
 	}
     }
+  g_unlock(current_allocator);
   list->next = NULL;
   list->prev = NULL;
   
@@ -114,9 +137,11 @@
 {
   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);
     }
 }
 
@@ -125,9 +150,11 @@
 {
   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);
     }
 }
 
