Merge g_thread_functions_for_glib_use
[platform/upstream/glib.git] / glib / gthread-posix.c
index 96abcf8..01bd092 100644 (file)
  * GLib at ftp://ftp.gtk.org/pub/gtk/.
  */
 
-/*
- * MT safe
+/* The GMutex, GCond and GPrivate implementations in this file are some
+ * of the lowest-level code in GLib.  All other parts of GLib (messages,
+ * memory, slices, etc) assume that they can freely use these facilities
+ * without risking recursion.
+ *
+ * As such, these functions are NOT permitted to call any other part of
+ * GLib.
+ *
+ * The thread manipulation functions (create, exit, join, etc.) have
+ * more freedom -- they can do as they please.
  */
 
 #include "config.h"
 
-#include "glib.h"
+#include "gthread.h"
 #include "gthreadprivate.h"
 
 #include <pthread.h>
-#include <errno.h>
 #include <stdlib.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_SCHED_H
-#include <sched.h>
-#endif
-
-#define posix_check_err(err, name) G_STMT_START{                       \
-  int error = (err);                                                   \
-  if (error)                                                           \
-    g_error ("file %s: line %d (%s): error '%s' during '%s'",          \
-           __FILE__, __LINE__, G_STRFUNC,                              \
-           g_strerror (error), name);                                  \
-  }G_STMT_END
-
-#define posix_check_cmd(cmd) posix_check_err (cmd, #cmd)
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
 
-#ifdef G_ENABLE_DEBUG
-static gboolean posix_check_cmd_prio_warned = FALSE;
-# define posix_check_cmd_prio(cmd) G_STMT_START{                       \
-    int err = (cmd);                                                   \
-    if (err == EPERM)                                                  \
-      {                                                                \
-        if (!posix_check_cmd_prio_warned)                              \
-          {                                                            \
-            posix_check_cmd_prio_warned = TRUE;                                \
-            g_warning ("Priorities can only be changed "               \
-                        "(resp. increased) by root.");                         \
-          }                                                            \
-      }                                                                        \
-    else                                                               \
-      posix_check_err (err, #cmd);                                     \
-     }G_STMT_END
-#else /* G_ENABLE_DEBUG */
-# define posix_check_cmd_prio(cmd) G_STMT_START{                       \
-    int err = (cmd);                                                   \
-    if (err != EPERM)                                                  \
-      posix_check_err (err, #cmd);                                     \
-     }G_STMT_END
-#endif /* G_ENABLE_DEBUG */
-
-#if defined (POSIX_MIN_PRIORITY) && defined (POSIX_MAX_PRIORITY)
-# define HAVE_PRIORITIES 1
-static gint priority_normal_value;
-# ifdef __FreeBSD__
-   /* FreeBSD threads use different priority values from the POSIX_
-    * defines so we just set them here. The corresponding macros
-    * PTHREAD_MIN_PRIORITY and PTHREAD_MAX_PRIORITY are implied to be
-    * exported by the docs, but they aren't.
-    */
-#  define PRIORITY_LOW_VALUE      0
-#  define PRIORITY_URGENT_VALUE   31
-# else /* !__FreeBSD__ */
-#  define PRIORITY_LOW_VALUE      POSIX_MIN_PRIORITY
-#  define PRIORITY_URGENT_VALUE   POSIX_MAX_PRIORITY
-# endif /* !__FreeBSD__ */
-# define PRIORITY_NORMAL_VALUE    priority_normal_value
-
-# define PRIORITY_HIGH_VALUE \
-    ((PRIORITY_NORMAL_VALUE + PRIORITY_URGENT_VALUE * 2) / 3)
-
-static gint
-g_thread_priority_map (GThreadPriority priority)
+static void
+g_thread_abort (gint         status,
+                const gchar *function)
 {
-  switch (priority)
-    {
-    case G_THREAD_PRIORITY_LOW:
-      return PRIORITY_LOW_VALUE;
-
-    case G_THREAD_PRIORITY_NORMAL:
-      return PRIORITY_NORMAL_VALUE;
+  fprintf (stderr, "GLib (gthread-posix.c): Unexpected error from C library during '%s': %s.  Aborting.\n",
+           strerror (status), function);
+  abort ();
+}
 
-    case G_THREAD_PRIORITY_HIGH:
-      return PRIORITY_HIGH_VALUE;
+/* {{{1 GMutex */
 
-    case G_THREAD_PRIORITY_URGENT:
-      return PRIORITY_URGENT_VALUE;
+/**
+ * g_mutex_init:
+ * @mutex: an uninitialized #GMutex
+ *
+ * Initializes a #GMutex so that it can be used.
+ *
+ * This function is useful to initialize a mutex that has been
+ * allocated on the stack, or as part of a larger structure.
+ * It is not necessary to initialize a mutex that has been
+ * created with g_mutex_new(). Also see #G_MUTEX_INITIALIZER
+ * for an alternative way to initialize statically allocated mutexes.
+ *
+ * |[
+ *   typedef struct {
+ *     GMutex m;
+ *     /&ast; ... &ast;/
+ *   } Blob;
+ *
+ * Blob *b;
+ *
+ * b = g_new (Blob, 1);
+ * g_mutex_init (&b->m);
+ * /&ast; ... &ast;/
+ * ]|
+ *
+ * To undo the effect of g_mutex_init() when a mutex is no longer
+ * needed, use g_mutex_clear().
+ *
+ * Since: 2.32
+ */
+void
+g_mutex_init (GMutex *mutex)
+{
+  gint status;
 
-    default:
-      g_assert_not_reached ();
-    }
+  if G_UNLIKELY ((status = pthread_mutex_init (&mutex->impl, NULL)) != 0)
+    g_thread_abort (status, "pthread_mutex_init");
 }
 
-#endif /* POSIX_MIN_PRIORITY && POSIX_MAX_PRIORITY */
-
-static gulong g_thread_min_stack_size = 0;
+/**
+ * g_mutex_clear:
+ * @mutex: an initialized #GMutex
+ *
+ * Frees the resources allocated to a mutex with g_mutex_init().
+ *
+ * #GMutexes that have have been created with g_mutex_new() should
+ * be freed with g_mutex_free() instead.
+ *
+ * Sine: 2.32
+ */
+void
+g_mutex_clear (GMutex *mutex)
+{
+  gint status;
 
-#define G_MUTEX_SIZE (sizeof (pthread_mutex_t))
+  if G_UNLIKELY ((status = pthread_mutex_destroy (&mutex->impl)) != 0)
+    g_thread_abort (status, "pthread_mutex_destroy");
+}
 
+/**
+ * g_mutex_lock:
+ * @mutex: a #GMutex
+ *
+ * Locks @mutex. If @mutex is already locked by another thread, the
+ * current thread will block until @mutex is unlocked by the other
+ * thread.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ *
+ * <note>#GMutex is neither guaranteed to be recursive nor to be
+ * non-recursive, i.e. a thread could deadlock while calling
+ * g_mutex_lock(), if it already has locked @mutex. Use
+ * #GStaticRecMutex, if you need recursive mutexes.</note>
+ */
 void
-_g_thread_impl_init(void)
+g_mutex_lock (GMutex *mutex)
 {
-#ifdef _SC_THREAD_STACK_MIN
-  g_thread_min_stack_size = MAX (sysconf (_SC_THREAD_STACK_MIN), 0);
-#endif /* _SC_THREAD_STACK_MIN */
-#ifdef HAVE_PRIORITIES
-  {
-    struct sched_param sched;
-    int policy;
-    posix_check_cmd (pthread_getschedparam (pthread_self(), &policy, &sched));
-    priority_normal_value = sched.sched_priority;
-  }
-#endif /* HAVE_PRIORITIES */
+  gint status;
+
+  if G_UNLIKELY ((status = pthread_mutex_lock (&mutex->impl)) != 0)
+    g_thread_abort (status, "pthread_mutex_lock");
 }
 
-static GMutex *
-g_mutex_new_posix_impl (void)
+/**
+ * g_mutex_unlock:
+ * @mutex: a #GMutex
+ *
+ * Unlocks @mutex. If another thread is blocked in a g_mutex_lock()
+ * call for @mutex, it will be woken and can lock @mutex itself.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ */
+void
+g_mutex_unlock (GMutex *mutex)
 {
-  GMutex *result = (GMutex *) g_new (pthread_mutex_t, 1);
-  posix_check_cmd (pthread_mutex_init ((pthread_mutex_t *) result, NULL));
-  return result;
+  gint status;
+
+  if G_UNLIKELY ((status = pthread_mutex_unlock (&mutex->impl)) != 0)
+    g_thread_abort (status, "pthread_mutex_lock");
 }
 
-static void
-g_mutex_free_posix_impl (GMutex * mutex)
+/**
+ * g_mutex_trylock:
+ * @mutex: a #GMutex
+ *
+ * Tries to lock @mutex. If @mutex is already locked by another thread,
+ * it immediately returns %FALSE. Otherwise it locks @mutex and returns
+ * %TRUE.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will immediately return %TRUE.
+ *
+ * <note>#GMutex is neither guaranteed to be recursive nor to be
+ * non-recursive, i.e. the return value of g_mutex_trylock() could be
+ * both %FALSE or %TRUE, if the current thread already has locked
+ * @mutex. Use #GStaticRecMutex, if you need recursive
+ * mutexes.</note>
+
+ * Returns: %TRUE, if @mutex could be locked
+ */
+gboolean
+g_mutex_trylock (GMutex *mutex)
 {
-  posix_check_cmd (pthread_mutex_destroy ((pthread_mutex_t *) mutex));
-  g_free (mutex);
+  gint status;
+
+  if G_LIKELY ((status = pthread_mutex_trylock (&mutex->impl)) == 0)
+    return TRUE;
+
+  if G_UNLIKELY (status != EBUSY)
+    g_thread_abort (status, "pthread_mutex_trylock");
+
+  return FALSE;
 }
 
-/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use
-   functions from gmem.c and gmessages.c; */
+/* {{{1 GCond */
 
-/* pthread_mutex_lock, pthread_mutex_unlock can be taken directly, as
-   signature and semantic are right, but without error check then!!!!,
-   we might want to change this therefore. */
+/**
+ * g_cond_init:
+ * @cond: an uninitialized #GCond
+ *
+ * Initialized a #GCond so that it can be used.
+ *
+ * This function is useful to initialize a #GCond that has been
+ * allocated on the stack, or as part of a larger structure.
+ * It is not necessary to initialize a #GCond that has been
+ * created with g_cond_new(). Also see #G_COND_INITIALIZER
+ * for an alternative way to initialize statically allocated
+ * #GConds.
+ *
+ * Since: 2.32
+ */
+void
+g_cond_init (GCond *cond)
+{
+  gint status;
+
+  if G_UNLIKELY ((status = pthread_cond_init (&cond->impl, NULL)) != 0)
+    g_thread_abort (status, "pthread_cond_init");
+}
 
-static gboolean
-g_mutex_trylock_posix_impl (GMutex * mutex)
+/**
+ * g_cond_clear:
+ * @cond: an initialized #GCond
+ *
+ * Frees the resources allocated ot a #GCond with g_cond_init().
+ *
+ * #GConds that have been created with g_cond_new() should
+ * be freed with g_cond_free() instead.
+ *
+ * Since: 2.32
+ */
+void
+g_cond_clear (GCond *cond)
 {
-  int result;
+  gint status;
 
-  result = pthread_mutex_trylock ((pthread_mutex_t *) mutex);
+  if G_UNLIKELY ((status = pthread_cond_destroy (&cond->impl)) != 0)
+    g_thread_abort (status, "pthread_cond_destroy");
+}
 
-  if (result == EBUSY)
-    return FALSE;
+/**
+ * g_cond_wait:
+ * @cond: a #GCond
+ * @mutex: a #GMutex that is currently locked
+ *
+ * Waits until this thread is woken up on @cond.
+ * The @mutex is unlocked before falling asleep
+ * and locked again before resuming.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will immediately return.
+ */
+void
+g_cond_wait (GCond  *cond,
+             GMutex *mutex)
+{
+  gint status;
 
-  posix_check_err (result, "pthread_mutex_trylock");
-  return TRUE;
+  if G_UNLIKELY ((status = pthread_cond_wait (&cond->impl, &mutex->impl)) != 0)
+    g_thread_abort (status, "pthread_cond_wait");
 }
 
-static GCond *
-g_cond_new_posix_impl (void)
+/**
+ * g_cond_signal:
+ * @cond: a #GCond
+ *
+ * If threads are waiting for @cond, exactly one of them is woken up.
+ * It is good practice to hold the same lock as the waiting thread
+ * while calling this function, though not required.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ */
+void
+g_cond_signal (GCond *cond)
 {
-  GCond *result = (GCond *) g_new (pthread_cond_t, 1);
-  posix_check_cmd (pthread_cond_init ((pthread_cond_t *) result, NULL));
-  return result;
+  gint status;
+
+  if G_UNLIKELY ((status = pthread_cond_signal (&cond->impl)) != 0)
+    g_thread_abort (status, "pthread_cond_signal");
 }
 
-/* pthread_cond_signal, pthread_cond_broadcast and pthread_cond_wait
-   can be taken directly, as signature and semantic are right, but
-   without error check then!!!!, we might want to change this
-   therefore. */
+/**
+ * g_cond_broadcast:
+ * @cond: a #GCond
+ *
+ * If threads are waiting for @cond, all of them are woken up.
+ * It is good practice to lock the same mutex as the waiting threads
+ * while calling this function, though not required.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will do nothing.
+ */
+void
+g_cond_broadcast (GCond *cond)
+{
+  gint status;
 
-#define G_NSEC_PER_SEC 1000000000
+  if G_UNLIKELY ((status = pthread_cond_broadcast (&cond->impl)) != 0)
+    g_thread_abort (status, "pthread_cond_broadcast");
+}
 
-static gboolean
-g_cond_timed_wait_posix_impl (GCond * cond,
-                             GMutex * entered_mutex,
-                             GTimeVal * abs_time)
+/**
+ * g_cond_timed_wait:
+ * @cond: a #GCond
+ * @mutex: a #GMutex that is currently locked
+ * @abs_time: a #GTimeVal, determining the final time
+ *
+ * Waits until this thread is woken up on @cond, but not longer than
+ * until the time specified by @abs_time. The @mutex is unlocked before
+ * falling asleep and locked again before resuming.
+ *
+ * If @abs_time is %NULL, g_cond_timed_wait() acts like g_cond_wait().
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will immediately return %TRUE.
+ *
+ * To easily calculate @abs_time a combination of g_get_current_time()
+ * and g_time_val_add() can be used.
+ *
+ * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
+ */
+gboolean
+g_cond_timed_wait (GCond    *cond,
+                   GMutex   *mutex,
+                   GTimeVal *abs_time)
 {
-  int result;
   struct timespec end_time;
-  gboolean timed_out;
-
-  g_return_val_if_fail (cond != NULL, FALSE);
-  g_return_val_if_fail (entered_mutex != NULL, FALSE);
+  gint status;
 
-  if (!abs_time)
+  if (abs_time == NULL)
     {
-      result = pthread_cond_wait ((pthread_cond_t *)cond,
-                                  (pthread_mutex_t *) entered_mutex);
-      timed_out = FALSE;
+      g_cond_wait (cond, mutex);
+      return TRUE;
     }
-  else
-    {
-      end_time.tv_sec = abs_time->tv_sec;
-      end_time.tv_nsec = abs_time->tv_usec * (G_NSEC_PER_SEC / G_USEC_PER_SEC);
 
-      g_return_val_if_fail (end_time.tv_nsec < G_NSEC_PER_SEC, TRUE);
+  end_time.tv_sec = abs_time->tv_sec;
+  end_time.tv_nsec = abs_time->tv_usec * 1000;
 
-      result = pthread_cond_timedwait ((pthread_cond_t *) cond,
-                                       (pthread_mutex_t *) entered_mutex,
-                                       &end_time);
-      timed_out = (result == ETIMEDOUT);
-    }
+  if ((status = pthread_cond_timedwait (&cond->impl, &mutex->impl, &end_time)) == 0)
+    return TRUE;
 
-  if (!timed_out)
-    posix_check_err (result, "pthread_cond_timedwait");
+  if G_UNLIKELY (status != ETIMEDOUT)
+    g_thread_abort (status, "pthread_cond_timedwait");
 
-  return !timed_out;
+  return FALSE;
 }
 
-static void
-g_cond_free_posix_impl (GCond * cond)
+/**
+ * g_cond_timedwait:
+ * @cond: a #GCond
+ * @mutex: a #GMutex that is currently locked
+ * @abs_time: the final time, in microseconds
+ *
+ * A variant of g_cond_timed_wait() that takes @abs_time
+ * as a #gint64 instead of a #GTimeVal.
+ * See g_cond_timed_wait() for details.
+ *
+ * Returns: %TRUE if @cond was signalled, or %FALSE on timeout
+ *
+ * Since: 2.32
+ */
+gboolean
+g_cond_timedwait (GCond  *cond,
+                  GMutex *mutex,
+                  gint64  abs_time)
 {
-  posix_check_cmd (pthread_cond_destroy ((pthread_cond_t *) cond));
-  g_free (cond);
+  struct timespec end_time;
+  gint status;
+
+  end_time.tv_sec = abs_time / 1000000;
+  end_time.tv_nsec = (abs_time % 1000000) * 1000;
+
+  if ((status = pthread_cond_timedwait (&cond->impl, &mutex->impl, &end_time)) == 0)
+    return TRUE;
+
+  if G_UNLIKELY (status != ETIMEDOUT)
+    g_thread_abort (status, "pthread_cond_timedwait");
+
+  return FALSE;
 }
 
-static GPrivate *
-g_private_new_posix_impl (GDestroyNotify destructor)
+/* {{{1 GPrivate */
+
+void
+g_private_init (GPrivate       *key,
+                GDestroyNotify  notify)
 {
-  GPrivate *result = (GPrivate *) g_new (pthread_key_t, 1);
-  posix_check_cmd (pthread_key_create ((pthread_key_t *) result, destructor));
-  return result;
+  pthread_key_create (&key->key, notify);
+  key->ready = TRUE;
 }
 
-/* NOTE: the functions g_private_get and g_private_set may not use
-   functions from gmem.c and gmessages.c */
-
-static void
-g_private_set_posix_impl (GPrivate * private_key, gpointer value)
+/**
+ * g_private_get:
+ * @private_key: a #GPrivate
+ *
+ * Returns the pointer keyed to @private_key for the current thread. If
+ * g_private_set() hasn't been called for the current @private_key and
+ * thread yet, this pointer will be %NULL.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will return the value of @private_key
+ * casted to #gpointer. Note however, that private data set
+ * <emphasis>before</emphasis> g_thread_init() will
+ * <emphasis>not</emphasis> be retained <emphasis>after</emphasis> the
+ * call. Instead, %NULL will be returned in all threads directly after
+ * g_thread_init(), regardless of any g_private_set() calls issued
+ * before threading system initialization.
+ *
+ * Returns: the corresponding pointer
+ */
+gpointer
+g_private_get (GPrivate *key)
 {
-  if (!private_key)
-    return;
-  pthread_setspecific (*(pthread_key_t *) private_key, value);
+  if (!key->ready)
+    return key->single_value;
+
+  /* quote POSIX: No errors are returned from pthread_getspecific(). */
+  return pthread_getspecific (key->key);
 }
 
-static gpointer
-g_private_get_posix_impl (GPrivate * private_key)
+/**
+ * g_private_set:
+ * @private_key: a #GPrivate
+ * @data: the new pointer
+ *
+ * Sets the pointer keyed to @private_key for the current thread.
+ *
+ * This function can be used even if g_thread_init() has not yet been
+ * called, and, in that case, will set @private_key to @data casted to
+ * #GPrivate*. See g_private_get() for resulting caveats.
+ */
+void
+g_private_set (GPrivate *key,
+               gpointer  value)
 {
-  if (!private_key)
-    return NULL;
+  gint status;
 
-  return pthread_getspecific (*(pthread_key_t *) private_key);
+  if (!key->ready)
+    {
+      key->single_value = value;
+      return;
+    }
+
+  if G_UNLIKELY ((status = pthread_setspecific (key->key, value)) != 0)
+    g_thread_abort (status, "pthread_setspecific");
 }
 
-static void
-g_thread_create_posix_impl (GThreadFunc thread_func,
-                           gpointer arg,
-                           gulong stack_size,
-                           gboolean joinable,
-                           gboolean bound,
-                           GThreadPriority priority,
-                           gpointer thread,
-                           GError **error)
+/* {{{1 GThread */
+
+#include "glib.h"
+#include "gthreadprivate.h"
+
+#include <pthread.h>
+#include <errno.h>
+#include <stdlib.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif
+
+#define posix_check_err(err, name) G_STMT_START{                       \
+  int error = (err);                                                   \
+  if (error)                                                           \
+    g_error ("file %s: line %d (%s): error '%s' during '%s'",          \
+           __FILE__, __LINE__, G_STRFUNC,                              \
+           g_strerror (error), name);                                  \
+  }G_STMT_END
+
+#define posix_check_cmd(cmd) posix_check_err (cmd, #cmd)
+
+static gulong g_thread_min_stack_size = 0;
+
+#define G_MUTEX_SIZE (sizeof (pthread_mutex_t))
+
+void
+_g_thread_impl_init(void)
+{
+#ifdef _SC_THREAD_STACK_MIN
+  g_thread_min_stack_size = MAX (sysconf (_SC_THREAD_STACK_MIN), 0);
+#endif /* _SC_THREAD_STACK_MIN */
+}
+
+void
+g_system_thread_create (GThreadFunc       thread_func,
+                        gpointer          arg,
+                        gulong            stack_size,
+                        gboolean          joinable,
+                        gboolean          bound,
+                        GThreadPriority   priority,
+                        gpointer          thread,
+                        GError          **error)
 {
   pthread_attr_t attr;
   gint ret;
 
   g_return_if_fail (thread_func);
-  g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
-  g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
 
   posix_check_cmd (pthread_attr_init (&attr));
 
@@ -310,14 +529,6 @@ g_thread_create_posix_impl (GThreadFunc thread_func,
   posix_check_cmd (pthread_attr_setdetachstate (&attr,
           joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
 
-#ifdef HAVE_PRIORITIES
-  {
-    struct sched_param sched;
-    posix_check_cmd (pthread_attr_getschedparam (&attr, &sched));
-    sched.sched_priority = g_thread_priority_map (priority);
-    posix_check_cmd_prio (pthread_attr_setschedparam (&attr, &sched));
-  }
-#endif /* HAVE_PRIORITIES */
   ret = pthread_create (thread, &attr, (void* (*)(void*))thread_func, arg);
 
   posix_check_cmd (pthread_attr_destroy (&attr));
@@ -332,76 +543,46 @@ g_thread_create_posix_impl (GThreadFunc thread_func,
   posix_check_err (ret, "pthread_create");
 }
 
-static void
-g_thread_yield_posix_impl (void)
+/**
+ * g_thread_yield:
+ *
+ * Gives way to other threads waiting to be scheduled.
+ *
+ * This function is often used as a method to make busy wait less evil.
+ * But in most cases you will encounter, there are better methods to do
+ * that. So in general you shouldn't use this function.
+ */
+void
+g_thread_yield (void)
 {
-  POSIX_YIELD_FUNC;
+  sched_yield ();
 }
 
-static void
-g_thread_join_posix_impl (gpointer thread)
+void
+g_system_thread_join (gpointer thread)
 {
   gpointer ignore;
   posix_check_cmd (pthread_join (*(pthread_t*)thread, &ignore));
 }
 
-static void
-g_thread_exit_posix_impl (void)
+void
+g_system_thread_exit (void)
 {
   pthread_exit (NULL);
 }
 
-static void
-g_thread_set_priority_posix_impl (gpointer thread, GThreadPriority priority)
-{
-  g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW);
-  g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT);
-#ifdef HAVE_PRIORITIES
-  {
-    struct sched_param sched;
-    int policy;
-    posix_check_cmd (pthread_getschedparam (*(pthread_t*)thread, &policy,
-                                           &sched));
-    sched.sched_priority = g_thread_priority_map (priority);
-    posix_check_cmd_prio (pthread_setschedparam (*(pthread_t*)thread, policy,
-                                                &sched));
-  }
-#endif /* HAVE_PRIORITIES */
-}
-
-static void
-g_thread_self_posix_impl (gpointer thread)
+void
+g_system_thread_self (gpointer thread)
 {
   *(pthread_t*)thread = pthread_self();
 }
 
-static gboolean
-g_thread_equal_posix_impl (gpointer thread1, gpointer thread2)
+gboolean
+g_system_thread_equal (gpointer thread1,
+                       gpointer thread2)
 {
   return (pthread_equal (*(pthread_t*)thread1, *(pthread_t*)thread2) != 0);
 }
 
-GThreadFunctions g_thread_functions_for_glib_use =
-{
-  g_mutex_new_posix_impl,
-  (void (*)(GMutex *)) pthread_mutex_lock,
-  g_mutex_trylock_posix_impl,
-  (void (*)(GMutex *)) pthread_mutex_unlock,
-  g_mutex_free_posix_impl,
-  g_cond_new_posix_impl,
-  (void (*)(GCond *)) pthread_cond_signal,
-  (void (*)(GCond *)) pthread_cond_broadcast,
-  (void (*)(GCond *, GMutex *)) pthread_cond_wait,
-  g_cond_timed_wait_posix_impl,
-  g_cond_free_posix_impl,
-  g_private_new_posix_impl,
-  g_private_get_posix_impl,
-  g_private_set_posix_impl,
-  g_thread_create_posix_impl,
-  g_thread_yield_posix_impl,
-  g_thread_join_posix_impl,
-  g_thread_exit_posix_impl,
-  g_thread_set_priority_posix_impl,
-  g_thread_self_posix_impl,
-  g_thread_equal_posix_impl
-};
+/* {{{1 Epilogue */
+/* vim:set foldmethod=marker: */