Renamed to glib/gthreadprivate.h and moved system thread identifier
[platform/upstream/glib.git] / glib / gthread.c
index 71b5627..72ffcb0 100644 (file)
@@ -1,7 +1,7 @@
 /* GLIB - Library of useful routines for C programming
  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
  *
- * gmutex.c: MT safety related functions
+ * gthread.c: MT safety related functions
  * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe
  *                Owen Taylor
  *
  */
 
 #include "config.h"
-#include "glib.h"
 
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
-#if GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P
-# define g_system_thread_equal(thread1, thread2)                       \
-   (thread1.dummy_pointer == thread2.dummy_pointer)
-# define g_system_thread_assign(dest, src)                             \
-   (dest.dummy_pointer = src.dummy_pointer)
-#else /* GLIB_SIZEOF_SYSTEM_THREAD != SIZEOF_VOID_P */
-# define g_system_thread_equal(thread1, thread2)                       \
-   (memcmp (&thread1, &thread2, GLIB_SIZEOF_SYSTEM_THREAD) == 0)
-# define g_system_thread_assign(dest, src)                             \
-   (memcpy (&dest, &src, GLIB_SIZEOF_SYSTEM_THREAD))
-#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */
+#include <string.h>
+
+#include "glib.h"
+#include "gthreadprivate.h"
+#include "galias.h"
 
 GQuark 
-g_thread_error_quark()
+g_thread_error_quark (void)
 {
-  static GQuark quark;
-  if (!quark)
-    quark = g_quark_from_static_string ("g_thread_error");
-  return quark;
+  return g_quark_from_static_string ("g_thread_error");
 }
 
+/* Keep this in sync with GRealThread in gmain.c! */
 typedef struct _GRealThread GRealThread;
 struct  _GRealThread
 {
   GThread thread;
-  GThreadFunc func;
-  gpointer arg;
   gpointer private_data;
+  GRealThread *next;
+  gpointer retval;
   GSystemThread system_thread;
 };
 
@@ -86,9 +77,6 @@ static GSystemThread zero_thread; /* This is initialized to all zero */
 gboolean g_thread_use_default_impl = TRUE;
 gboolean g_threads_got_initialized = FALSE;
 
-#if defined(G_OS_WIN32) && defined(__GNUC__)
-__declspec(dllexport)
-#endif
 GThreadFunctions g_thread_functions_for_glib_use = {
   (GMutex*(*)())g_thread_fail,                 /* mutex_new */
   NULL,                                        /* mutex_lock */
@@ -116,57 +104,119 @@ GThreadFunctions g_thread_functions_for_glib_use = {
 
 /* Local data */
 
-static GMutex   *g_mutex_protect_static_mutex_allocation = NULL;
-static GMutex   *g_thread_specific_mutex = NULL;
+static GMutex   *g_once_mutex = NULL;
+static GCond    *g_once_cond = NULL;
 static GPrivate *g_thread_specific_private = NULL;
+static GRealThread *g_thread_all_threads = NULL;
+static GSList   *g_thread_free_indeces = NULL;
+
+G_LOCK_DEFINE_STATIC (g_thread);
 
+#ifdef G_THREADS_ENABLED
 /* This must be called only once, before any threads are created.
  * It will only be called from g_thread_init() in -lgthread.
  */
-void
-g_mutex_init (void)
+void 
+g_thread_init_glib (void)
 {
-  GRealThread* main_thread;
   /* We let the main thread (the one that calls g_thread_init) inherit
-   * the data, that it set before calling g_thread_init
+   * the static_private data set before calling g_thread_init
    */
-  main_thread = (GRealThread*) g_thread_self ();
+  GRealThread* main_thread = (GRealThread*) g_thread_self ();
+
+  /* mutex and cond creation works without g_threads_got_initialized */
+  g_once_mutex = g_mutex_new ();
+  g_once_cond = g_cond_new ();
+
+  /* we may only create mutex and cond in here */
+  _g_mem_thread_init_noprivate_nomessage ();
 
+  /* setup the basic threading system */
+  g_threads_got_initialized = TRUE;
   g_thread_specific_private = g_private_new (g_thread_cleanup);
-  G_THREAD_UF (private_set, (g_thread_specific_private, main_thread));
+  g_private_set (g_thread_specific_private, main_thread);
   G_THREAD_UF (thread_self, (&main_thread->system_thread));
 
-  g_mutex_protect_static_mutex_allocation = g_mutex_new();
-  g_thread_specific_mutex = g_mutex_new();
-}
+  /* complete memory system initialization, g_private_*() works now */
+  _g_slice_thread_init_nomessage ();
 
-GMutex *
-g_static_mutex_get_mutex_impl (GMutex** mutex)
-{
-  if (!g_thread_supported ())
-    return NULL;
+  /* accomplish log system initialization to enable messaging */
+  _g_messages_thread_init_nomessage ();
 
-  g_assert (g_mutex_protect_static_mutex_allocation);
+  /* we may run full-fledged initializers from here */
+  _g_convert_thread_init ();
+  _g_rand_thread_init ();
+  _g_main_thread_init ();
+  _g_atomic_thread_init ();
+  _g_utils_thread_init ();
+#ifdef G_OS_WIN32
+  _g_win32_thread_init ();
+#endif
+}
+#endif /* G_THREADS_ENABLED */
 
-  g_mutex_lock (g_mutex_protect_static_mutex_allocation);
+gpointer 
+g_once_impl (GOnce       *once, 
+            GThreadFunc  func, 
+            gpointer     arg)
+{
+  g_mutex_lock (g_once_mutex);
 
-  if (!(*mutex)) 
-    *mutex = g_mutex_new(); 
+  while (once->status == G_ONCE_STATUS_PROGRESS)
+    g_cond_wait (g_once_cond, g_once_mutex);
+  
+  if (once->status != G_ONCE_STATUS_READY)
+    {
+      once->status = G_ONCE_STATUS_PROGRESS;
+      g_mutex_unlock (g_once_mutex);
+  
+      once->retval = func (arg);
 
-  g_mutex_unlock (g_mutex_protect_static_mutex_allocation);
+      g_mutex_lock (g_once_mutex);
+      once->status = G_ONCE_STATUS_READY;
+      g_cond_broadcast (g_once_cond);
+    }
   
-  return *mutex;
+  g_mutex_unlock (g_once_mutex);
+  
+  return once->retval;
 }
 
 void 
 g_static_mutex_init (GStaticMutex *mutex)
 {
-  static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
+  static const GStaticMutex init_mutex = G_STATIC_MUTEX_INIT;
 
   g_return_if_fail (mutex);
 
-  memcpy (mutex, &init_mutex, sizeof (GStaticMutex));
+  *mutex = init_mutex;
+}
+
+GMutex *
+g_static_mutex_get_mutex_impl (GMutex** mutex)
+{
+  if (!g_thread_supported ())
+    return NULL;
+
+  g_assert (g_once_mutex);
+
+  g_mutex_lock (g_once_mutex);
+
+  if (!(*mutex)) 
+    {
+      GMutex *new_mutex = g_mutex_new (); 
+      
+      /* The following is a memory barrier to avoid the write 
+       * to *new_mutex being reordered to after writing *mutex */
+      g_mutex_lock (new_mutex);
+      g_mutex_unlock (new_mutex);
+      
+      *mutex = new_mutex;
+    }
+
+  g_mutex_unlock (g_once_mutex);
+  
+  return *mutex;
 }
 
 void
@@ -186,6 +236,16 @@ g_static_mutex_free (GStaticMutex* mutex)
   *runtime_mutex = NULL;
 }
 
+void     
+g_static_rec_mutex_init (GStaticRecMutex *mutex)
+{
+  static const GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT;
+  
+  g_return_if_fail (mutex);
+
+  *mutex = init_mutex;
+}
+
 void
 g_static_rec_mutex_lock (GStaticRecMutex* mutex)
 {
@@ -255,20 +315,31 @@ void
 g_static_rec_mutex_lock_full   (GStaticRecMutex *mutex,
                                guint            depth)
 {
+  GSystemThread self;
   g_return_if_fail (mutex);
 
   if (!g_thread_supported ())
     return;
 
+  if (depth == 0)
+    return;
+
+  G_THREAD_UF (thread_self, (&self));
+
+  if (g_system_thread_equal (self, mutex->owner))
+    {
+      mutex->depth += depth;
+      return;
+    }
   g_static_mutex_lock (&mutex->mutex);
-  G_THREAD_UF (thread_self, (&mutex->owner));
+  g_system_thread_assign (mutex->owner, self);
   mutex->depth = depth;
 }
 
 guint    
 g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
 {
-  gint depth;
+  guint depth;
 
   g_return_val_if_fail (mutex, 0);
 
@@ -284,21 +355,25 @@ g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex)
   return depth;
 }
 
+void
+g_static_rec_mutex_free (GStaticRecMutex *mutex)
+{
+  g_return_if_fail (mutex);
 
-gpointer
-g_static_private_get (GStaticPrivate *private_key)
+  g_static_mutex_free (&mutex->mutex);
+}
+
+void     
+g_static_private_init (GStaticPrivate *private_key)
 {
-  return g_static_private_get_for_thread (private_key, g_thread_self ());
+  private_key->index = 0;
 }
 
 gpointer
-g_static_private_get_for_thread (GStaticPrivate *private_key,
-                                GThread        *thread)
+g_static_private_get (GStaticPrivate *private_key)
 {
+  GRealThread *self = (GRealThread*) g_thread_self ();
   GArray *array;
-  GRealThread *self = (GRealThread*) thread;
-
-  g_return_val_if_fail (thread, NULL);
 
   array = self->private_data;
   if (!array)
@@ -307,7 +382,8 @@ g_static_private_get_for_thread (GStaticPrivate *private_key,
   if (!private_key->index)
     return NULL;
   else if (private_key->index <= array->len)
-    return g_array_index (array, GStaticPrivateNode, private_key->index - 1).data;
+    return g_array_index (array, GStaticPrivateNode, 
+                         private_key->index - 1).data;
   else
     return NULL;
 }
@@ -317,23 +393,11 @@ g_static_private_set (GStaticPrivate *private_key,
                      gpointer        data,
                      GDestroyNotify  notify)
 {
-  g_static_private_set_for_thread (private_key, g_thread_self (), 
-                                  data, notify);
-}
-
-void
-g_static_private_set_for_thread (GStaticPrivate *private_key, 
-                                GThread        *thread,
-                                gpointer        data,
-                                GDestroyNotify  notify)
-{
+  GRealThread *self = (GRealThread*) g_thread_self ();
   GArray *array;
-  GRealThread *self =(GRealThread*) thread;
   static guint next_index = 0;
   GStaticPrivateNode *node;
 
-  g_return_if_fail (thread);
-  
   array = self->private_data;
   if (!array)
     {
@@ -343,12 +407,23 @@ g_static_private_set_for_thread (GStaticPrivate *private_key,
 
   if (!private_key->index)
     {
-      g_mutex_lock (g_thread_specific_mutex);
+      G_LOCK (g_thread);
 
       if (!private_key->index)
-       private_key->index = ++next_index;
+       {
+         if (g_thread_free_indeces)
+           {
+             private_key->index = 
+               GPOINTER_TO_UINT (g_thread_free_indeces->data);
+             g_thread_free_indeces = 
+               g_slist_delete_link (g_thread_free_indeces,
+                                    g_thread_free_indeces);
+           }
+         else
+           private_key->index = ++next_index;
+       }
 
-      g_mutex_unlock (g_thread_specific_mutex);
+      G_UNLOCK (g_thread);
     }
 
   if (private_key->index > array->len)
@@ -372,6 +447,49 @@ g_static_private_set_for_thread (GStaticPrivate *private_key,
     }
 }
 
+void     
+g_static_private_free (GStaticPrivate *private_key)
+{
+  guint index = private_key->index;
+  GRealThread *thread;
+
+  if (!index)
+    return;
+  
+  private_key->index = 0;
+
+  G_LOCK (g_thread);
+  
+  thread = g_thread_all_threads;
+  while (thread)
+    {
+      GArray *array = thread->private_data;
+      thread = thread->next;
+
+      if (array && index <= array->len)
+       {
+         GStaticPrivateNode *node = &g_array_index (array, 
+                                                    GStaticPrivateNode, 
+                                                    index - 1);
+         gpointer ddata = node->data;
+         GDestroyNotify ddestroy = node->destroy;
+
+         node->data = NULL;
+         node->destroy = NULL;
+
+         if (ddestroy) 
+           {
+             G_UNLOCK (g_thread);
+             ddestroy (ddata);
+             G_LOCK (g_thread);
+             }
+       }
+    }
+  g_thread_free_indeces = g_slist_prepend (g_thread_free_indeces, 
+                                          GUINT_TO_POINTER (index));
+  G_UNLOCK (g_thread);
+}
+
 static void
 g_thread_cleanup (gpointer data)
 {
@@ -392,10 +510,27 @@ g_thread_cleanup (gpointer data)
            }
          g_array_free (array, TRUE);
        }
+
       /* We only free the thread structure, if it isn't joinable. If
          it is, the structure is freed in g_thread_join */
       if (!thread->thread.joinable)
        {
+         GRealThread *t, *p;
+
+         G_LOCK (g_thread);
+         for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
+           {
+             if (t == thread)
+               {
+                 if (p)
+                   p->next = t->next;
+                 else
+                   g_thread_all_threads = t->next;
+                 break;
+               }
+           }
+         G_UNLOCK (g_thread);
+         
          /* Just to make sure, this isn't used any more */
          g_system_thread_assign (thread->system_thread, zero_thread);
          g_free (thread);
@@ -409,9 +544,7 @@ g_thread_fail (void)
   g_error ("The thread system is not yet initialized.");
 }
 
-G_LOCK_DEFINE_STATIC (g_thread_create);
-
-static void 
+static gpointer
 g_thread_create_proxy (gpointer data)
 {
   GRealThread* thread = data;
@@ -422,39 +555,44 @@ g_thread_create_proxy (gpointer data)
   g_private_set (g_thread_specific_private, data);
 
   /* the lock makes sure, that thread->system_thread is written,
-     before thread->func is called. See g_thread_create. */
-  G_LOCK (g_thread_create);
-  G_UNLOCK (g_thread_create);
+     before thread->thread.func is called. See g_thread_create. */
+  G_LOCK (g_thread);
+  G_UNLOCK (g_thread);
+  thread->retval = thread->thread.func (thread->thread.data);
 
-  thread->func (thread->arg);
+  return NULL;
 }
 
 GThread* 
-g_thread_create (GThreadFunc            thread_func,
-                gpointer                arg,
-                gulong                  stack_size,
-                gboolean                joinable,
-                gboolean                bound,
-                GThreadPriority         priority,
-                GError                **error)
-{
-  GRealThread* result = g_new (GRealThread, 1);
+g_thread_create_full (GThreadFunc               func,
+                     gpointer           data,
+                     gulong             stack_size,
+                     gboolean           joinable,
+                     gboolean           bound,
+                     GThreadPriority    priority,
+                     GError                **error)
+{
+  GRealThread* result;
   GError *local_error = NULL;
-  g_return_val_if_fail (thread_func, NULL);
+  g_return_val_if_fail (func, NULL);
   g_return_val_if_fail (priority >= G_THREAD_PRIORITY_LOW, NULL);
   g_return_val_if_fail (priority <= G_THREAD_PRIORITY_URGENT, NULL);
   
+  result = g_new0 (GRealThread, 1);
+
   result->thread.joinable = joinable;
-  result->thread.bound = bound;
   result->thread.priority = priority;
-  result->func = thread_func;
-  result->arg = arg;
+  result->thread.func = func;
+  result->thread.data = data;
   result->private_data = NULL; 
-  G_LOCK (g_thread_create);
+  G_LOCK (g_thread);
   G_THREAD_UF (thread_create, (g_thread_create_proxy, result, 
                               stack_size, joinable, bound, priority,
                               &result->system_thread, &local_error));
-  G_UNLOCK (g_thread_create);
+  result->next = g_thread_all_threads;
+  g_thread_all_threads = result;
+  G_UNLOCK (g_thread);
 
   if (local_error)
     {
@@ -466,27 +604,55 @@ g_thread_create (GThreadFunc               thread_func,
   return (GThread*) result;
 }
 
-void 
+void
+g_thread_exit (gpointer retval)
+{
+  GRealThread* real = (GRealThread*) g_thread_self ();
+  real->retval = retval;
+  G_THREAD_CF (thread_exit, (void)0, ());
+}
+
+gpointer
 g_thread_join (GThread* thread)
 {
   GRealThread* real = (GRealThread*) thread;
-  
+  GRealThread *p, *t;
+  gpointer retval;
 
-  g_return_if_fail (thread);
-  g_return_if_fail (thread->joinable);
-  g_return_if_fail (!g_system_thread_equal (real->system_thread, zero_thread));
+  g_return_val_if_fail (thread, NULL);
+  g_return_val_if_fail (thread->joinable, NULL);
+  g_return_val_if_fail (!g_system_thread_equal (real->system_thread, 
+                                               zero_thread), NULL);
 
   G_THREAD_UF (thread_join, (&real->system_thread));
 
+  retval = real->retval;
+
+  G_LOCK (g_thread);
+  for (t = g_thread_all_threads, p = NULL; t; p = t, t = t->next)
+    {
+      if (t == (GRealThread*) thread)
+       {
+         if (p)
+           p->next = t->next;
+         else
+           g_thread_all_threads = t->next;
+         break;
+       }
+    }
+  G_UNLOCK (g_thread);
+
   /* Just to make sure, this isn't used any more */
   thread->joinable = 0;
   g_system_thread_assign (real->system_thread, zero_thread);
 
   /* the thread structure for non-joinable threads is freed upon
-     thread end. We free the memory here. This will leave loose end,
+     thread end. We free the memory here. This will leave loose end,
      if a joinable thread is not joined. */
 
   g_free (thread);
+
+  return retval;
 }
 
 void
@@ -501,11 +667,13 @@ g_thread_set_priority (GThread* thread,
   g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
 
   thread->priority = priority;
-  G_THREAD_CF (thread_set_priority, (void)0, (&real->system_thread, priority));
+
+  G_THREAD_CF (thread_set_priority, (void)0, 
+              (&real->system_thread, priority));
 }
 
 GThread*
-g_thread_self()
+g_thread_self (void)
 {
   GRealThread* thread = g_private_get (g_thread_specific_private);
 
@@ -514,40 +682,57 @@ g_thread_self()
       /* If no thread data is available, provide and set one.  This
          can happen for the main thread and for threads, that are not
          created by GLib. */
-      thread = g_new (GRealThread, 1);
+      thread = g_new0 (GRealThread, 1);
       thread->thread.joinable = FALSE; /* This is a save guess */
-      thread->thread.bound = TRUE; /* This isn't important at all */
       thread->thread.priority = G_THREAD_PRIORITY_NORMAL; /* This is
                                                             just a guess */
-      thread->func = NULL;
-      thread->arg = NULL;
+      thread->thread.func = NULL;
+      thread->thread.data = NULL;
       thread->private_data = NULL;
 
       if (g_thread_supported ())
        G_THREAD_UF (thread_self, (&thread->system_thread));
 
-      g_private_set (g_thread_specific_private, thread);
+      g_private_set (g_thread_specific_private, thread); 
+      
+      G_LOCK (g_thread);
+      thread->next = g_thread_all_threads;
+      g_thread_all_threads = thread;
+      G_UNLOCK (g_thread);
     }
   
   return (GThread*)thread;
 }
 
-static void inline g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
+void
+g_static_rw_lock_init (GStaticRWLock* lock)
+{
+  static const GStaticRWLock init_lock = G_STATIC_RW_LOCK_INIT;
+
+  g_return_if_fail (lock);
+
+  *lock = init_lock;
+}
+
+inline static void 
+g_static_rw_lock_wait (GCond** cond, GStaticMutex* mutex)
 {
   if (!*cond)
       *cond = g_cond_new ();
   g_cond_wait (*cond, g_static_mutex_get_mutex (mutex));
 }
 
-static void inline g_static_rw_lock_signal (GStaticRWLock* lock)
+inline static void 
+g_static_rw_lock_signal (GStaticRWLock* lock)
 {
   if (lock->want_to_write && lock->write_cond)
     g_cond_signal (lock->write_cond);
-  else if (lock->read_cond)
+  else if (lock->want_to_read && lock->read_cond)
     g_cond_broadcast (lock->read_cond);
 }
 
-void g_static_rw_lock_reader_lock (GStaticRWLock* lock)
+void 
+g_static_rw_lock_reader_lock (GStaticRWLock* lock)
 {
   g_return_if_fail (lock);
 
@@ -555,13 +740,16 @@ void g_static_rw_lock_reader_lock (GStaticRWLock* lock)
     return;
 
   g_static_mutex_lock (&lock->mutex);
-  while (lock->write || lock->want_to_write) 
+  lock->want_to_read++;
+  while (lock->have_writer || lock->want_to_write) 
     g_static_rw_lock_wait (&lock->read_cond, &lock->mutex);
+  lock->want_to_read--;
   lock->read_counter++;
   g_static_mutex_unlock (&lock->mutex);
 }
 
-gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
+gboolean 
+g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
 {
   gboolean ret_val = FALSE;
 
@@ -571,7 +759,7 @@ gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
     return TRUE;
 
   g_static_mutex_lock (&lock->mutex);
-  if (!lock->write && !lock->want_to_write)
+  if (!lock->have_writer && !lock->want_to_write)
     {
       lock->read_counter++;
       ret_val = TRUE;
@@ -580,7 +768,8 @@ gboolean g_static_rw_lock_reader_trylock (GStaticRWLock* lock)
   return ret_val;
 }
 
-void g_static_rw_lock_reader_unlock  (GStaticRWLock* lock)
+void 
+g_static_rw_lock_reader_unlock  (GStaticRWLock* lock)
 {
   g_return_if_fail (lock);
 
@@ -594,7 +783,8 @@ void g_static_rw_lock_reader_unlock  (GStaticRWLock* lock)
   g_static_mutex_unlock (&lock->mutex);
 }
 
-void g_static_rw_lock_writer_lock (GStaticRWLock* lock)
+void 
+g_static_rw_lock_writer_lock (GStaticRWLock* lock)
 {
   g_return_if_fail (lock);
 
@@ -603,14 +793,15 @@ void g_static_rw_lock_writer_lock (GStaticRWLock* lock)
 
   g_static_mutex_lock (&lock->mutex);
   lock->want_to_write++;
-  while (lock->write || lock->read_counter)
+  while (lock->have_writer || lock->read_counter)
     g_static_rw_lock_wait (&lock->write_cond, &lock->mutex);
   lock->want_to_write--;
-  lock->write = TRUE;
+  lock->have_writer = TRUE;
   g_static_mutex_unlock (&lock->mutex);
 }
 
-gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
+gboolean 
+g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
 {
   gboolean ret_val = FALSE;
 
@@ -620,16 +811,17 @@ gboolean g_static_rw_lock_writer_trylock (GStaticRWLock* lock)
     return TRUE;
 
   g_static_mutex_lock (&lock->mutex);
-  if (!lock->write && !lock->read_counter)
+  if (!lock->have_writer && !lock->read_counter)
     {
-      lock->write = TRUE;
+      lock->have_writer = TRUE;
       ret_val = TRUE;
     }
   g_static_mutex_unlock (&lock->mutex);
   return ret_val;
 }
 
-void g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
+void 
+g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
 {
   g_return_if_fail (lock);
   
@@ -637,19 +829,74 @@ void g_static_rw_lock_writer_unlock (GStaticRWLock* lock)
     return;
 
   g_static_mutex_lock (&lock->mutex);
-  lock->write = FALSE; 
+  lock->have_writer = FALSE; 
   g_static_rw_lock_signal (lock);
   g_static_mutex_unlock (&lock->mutex);
 }
 
-void g_static_rw_lock_free (GStaticRWLock* lock)
+void 
+g_static_rw_lock_free (GStaticRWLock* lock)
 {
   g_return_if_fail (lock);
   
   if (lock->read_cond)
-    g_cond_free (lock->read_cond);
+    {
+      g_cond_free (lock->read_cond);
+      lock->read_cond = NULL;
+    }
   if (lock->write_cond)
-    g_cond_free (lock->write_cond);
-  
+    {
+      g_cond_free (lock->write_cond);
+      lock->write_cond = NULL;
+    }
+  g_static_mutex_free (&lock->mutex);
+}
+
+/**
+ * g_thread_foreach
+ * @thread_func: function to call for all GThread structures
+ * @user_data:   second argument to @thread_func
+ *
+ * Call @thread_func on all existing #GThread structures. Note that
+ * threads may decide to exit while @thread_func is running, so
+ * without intimate knowledge about the lifetime of foreign threads,
+ * @thread_func shouldn't access the GThread* pointer passed in as
+ * first argument. However, @thread_func will not be called for threads
+ * which are known to have exited already.
+ *
+ * Due to thread lifetime checks, this function has an execution complexity
+ * which is quadratic in the number of existing threads.
+ *
+ * Since: 2.10
+ */
+void
+g_thread_foreach (GFunc    thread_func,
+                  gpointer user_data)
+{
+  GSList *slist = NULL;
+  GRealThread *thread;
+  g_return_if_fail (thread_func != NULL);
+  /* snapshot the list of threads for iteration */
+  G_LOCK (g_thread);
+  for (thread = g_thread_all_threads; thread; thread = thread->next)
+    slist = g_slist_prepend (slist, thread);
+  G_UNLOCK (g_thread);
+  /* walk the list, skipping non-existant threads */
+  while (slist)
+    {
+      GSList *node = slist;
+      slist = node->next;
+      /* check whether the current thread still exists */
+      G_LOCK (g_thread);
+      for (thread = g_thread_all_threads; thread; thread = thread->next)
+        if (thread == node->data)
+          break;
+      G_UNLOCK (g_thread);
+      if (thread)
+        thread_func (thread, user_data);
+      g_slist_free_1 (node);
+    }
 }
 
+#define __G_THREAD_C__
+#include "galiasdef.c"