Le jeudi 14 août 2008 à 11:30 +0200, Yoann Vandoorselaere a écrit :
> Le jeudi 14 août 2008 à 10:58 +0200, Bruno Haible a écrit :
> > Yoann Vandoorselaere wrote:
> > > >     Can you see alternatives? Maybe something like <glthread/lock.h>,
> > > >     <glthread/tls.h>, <glthread/thread.h>, <glthread/cond.h>,
> > > >     <glthread/yield.h> ?
> > > 
> > > Look good to me, can you handle the renaming part so that all the
> > > modules look consistant?
> > 
> > Done as follows:
> 
> Thanks Bruno, attached is an updated diff of the cond/thread module,
> renamed using this new policy. Can you check it in the GnuLib
> repository?
> 
> Additionally, what should be the name for the module exporting the
> sched_yield() function?

Here is an updated patch, that fixes several naming issue and implement
the yield module.

-- 
Yoann Vandoorselaere | Responsable R&D / CTO | PreludeIDS Technologies
Tel: +33 (0)8 70 70 21 58                  Fax: +33(0)4 78 42 21 58
http://www.prelude-ids.com
diff --git a/lib/glthread/cond.h b/lib/glthread/cond.h
new file mode 100644
index 0000000..a23f1ce
--- /dev/null
+++ b/lib/glthread/cond.h
@@ -0,0 +1,325 @@
+/* Condition waiting in multithreaded situations.
+   Copyright (C) 2005-2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Yoann Vandoorselaere <[EMAIL PROTECTED]>, 2008.
+   Based on Bruno Haible <[EMAIL PROTECTED]> lock.h */
+
+/*
+   Condition variables can be used for waiting until a condition
+   becomes true. In this respect, they are similar to wait queues. But
+   contrary to wait queues, condition variables have different
+   semantics that allows events to be lost when there is no thread
+   waiting for them.
+
+   Condition variable:
+     Type:                gl_cond_t
+     Declaration:         gl_cond_define(extern, name)
+     Initializer:         gl_cond_define_initialized(, name)
+     Waiting:             gl_cond_wait(name)
+     Timed wait:          gl_cond_timedwait(name, tv)
+     Signaling:           gl_cond_signal(name)
+     Broadcasting:        gl_cond_broadcast(name)
+*/
+
+
+#ifndef _GLTHREAD_COND_H
+#define _GLTHREAD_COND_H
+
+#include <errno.h>
+#include "glthread/lock.h"
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library.  */
+
+# include <pthread.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The pthread_in_use() detection needs to be done at runtime.  */
+#  define pthread_in_use() \
+     glthread_in_use ()
+extern int glthread_in_use (void);
+
+# endif
+
+# if USE_POSIX_THREADS_WEAK
+
+/* Use weak references to the POSIX threads library.  */
+
+/* Weak references avoid dragging in external libraries if the other parts
+   of the program don't use them.  Here we use them, because we don't want
+   every program that uses libintl to depend on libpthread.  This assumes
+   that libpthread would not be loaded after libintl; i.e. if libintl is
+   loaded first, by an executable that does not depend on libpthread, and
+   then a module is dynamically loaded that depends on libpthread, libintl
+   will not be multithread-safe.  */
+
+/* The way to test at runtime whether libpthread is present is to test
+   whether a function pointer's value, such as &pthread_mutex_init, is
+   non-NULL.  However, some versions of GCC have a bug through which, in
+   PIC mode, &foo != NULL always evaluates to true if there is a direct
+   call to foo(...) in the same function.  To avoid this, we test the
+   address of a function in libpthread that we don't use.  */
+
+#  pragma weak pthread_cond_init
+#  pragma weak pthread_cond_wait
+#  pragma weak pthread_cond_timedwait
+#  pragma weak pthread_cond_signal
+#  pragma weak pthread_cond_broadcast
+#  pragma weak pthread_cond_destroy
+
+#  if !PTHREAD_IN_USE_DETECTION_HARD
+#   pragma weak pthread_cancel
+#   define pthread_in_use() (pthread_cancel != NULL)
+#  endif
+
+# else
+
+#  if !PTHREAD_IN_USE_DETECTION_HARD
+#   define pthread_in_use() 1
+#  endif
+
+# endif
+
+
+/* -------------------------- gl_cond_t datatype -------------------------- */
+
+typedef pthread_cond_t gl_cond_t;
+# define gl_cond_define(STORAGECLASS, NAME) \
+    STORAGECLASS pthread_cond_t NAME;
+# define gl_cond_define_initialized(STORAGECLASS, NAME) \
+    STORAGECLASS pthread_cond_t NAME = gl_cond_initializer;
+# define gl_cond_initializer \
+    PTHREAD_COND_INITIALIZER
+# define glthread_cond_init(COND) \
+    (pthread_in_use () ? pthread_cond_init (COND, NULL) : 0)
+# define glthread_cond_wait(COND, LOCK) \
+    (pthread_in_use () ? pthread_cond_wait (COND, LOCK) : 0)
+# define glthread_cond_timedwait(COND, LOCK, TS) \
+    (pthread_in_use () ? pthread_cond_timedwait (COND, LOCK, TS) : 0)
+# define glthread_cond_signal(COND) \
+    (pthread_in_use () ? pthread_cond_signal (COND) : 0)
+# define glthread_cond_broadcast(COND) \
+    (pthread_in_use () ? pthread_cond_broadcast (COND) : 0)
+# define glthread_cond_destroy(COND) \
+    (pthread_in_use () ? pthread_cond_destroy (COND) : 0)
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library.  */
+
+# include <pth.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_PTH_THREADS_WEAK
+
+/* Use weak references to the GNU Pth threads library.  */
+
+#  pragma weak pth_cond_init
+#  pragma weak pth_cond_await
+#  pragma weak pth_cond_notify
+#  pragma weak pth_event
+#  pragma weak pth_timeout
+#  pragma weak pth_cancel
+#  define pth_in_use() (pth_cancel != NULL)
+
+# else
+
+#  define pth_in_use() 1
+
+# endif
+
+/* -------------------------- gl_cond_t datatype -------------------------- */
+
+typedef pth_cond_t gl_cond_t;
+# define gl_cond_define(STORAGECLASS, NAME) \
+    STORAGECLASS pth_cond_t NAME;
+# define gl_cond_define_initialized(STORAGECLASS, NAME) \
+    STORAGECLASS pth_cond_t NAME = gl_cond_initializer;
+# define gl_cond_initializer \
+    PTH_COND_INIT
+# define glthread_cond_init(COND) \
+    (pth_in_use () && !pth_cond_init (COND) ? errno : 0)
+# define glthread_cond_wait(COND, LOCK) \
+    (pth_in_use () && !pth_cond_await (COND, LOCK, NULL) ? errno : 0)
+
+static inline int
+glthread_cond_timedwait (gl_cond_t * cond,
+                         gl_lock_t * lock,
+                         struct timespec *ts)
+{
+  int ret, status;
+  pth_event_t ev;
+
+  if (!pth_in_use ())
+    return 0;
+
+  ev = pth_event (PTH_EVENT_TIME, pth_time (ts->tv_sec, ts->tv_nsec / 1000));
+  ret = pth_cond_await (cond, lock, ev);
+
+  status = pth_event_status (ev);
+  pth_event_free (ev, PTH_FREE_THIS);
+
+  if (status == PTH_STATUS_OCCURRED)
+    return ETIMEDOUT;
+
+  return ret;
+}
+
+# define glthread_cond_signal(COND) \
+    (pth_in_use () && !pth_cond_notify (COND, FALSE) ? errno : 0)
+# define glthread_cond_broadcast(COND) \
+    (pth_in_use () && !pth_cond_notify (COND, TRUE) ? errno : 0)
+# define glthread_cond_destroy(COND) 0
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library.  */
+
+# include <thread.h>
+# include <synch.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_SOLARIS_THREADS_WEAK
+
+/* Use weak references to the old Solaris threads library.  */
+
+#  pragma weak cond_init
+#  pragma weak cond_wait
+#  pragma weak cond_timedwait
+#  pragma weak cond_signal
+#  pragma weak cond_broadcast
+#  pragma weak cond_destroy
+#  pragma weak thr_suspend
+#  define thread_in_use() (thr_suspend != NULL)
+
+# else
+
+#  define thread_in_use() 1
+
+# endif
+
+/* -------------------------- gl_cond_t datatype -------------------------- */
+
+#define ETIMEDOUT ETIME
+
+typedef pthread_cond_t gl_cond_t;
+# define gl_cond_define(STORAGECLASS, NAME) \
+    STORAGECLASS cond_t NAME;
+# define gl_cond_define_initialized(STORAGECLASS, NAME) \
+    STORAGECLASS cond_t NAME = gl_cond_initializer;
+# define gl_cond_initializer \
+    DEFAULTCV
+# define glthread_cond_init(COND) \
+    (pthread_in_use () ? cond_init (COND, USYNC_THREAD, NULL) : 0)
+# define glthread_cond_wait(COND, LOCK) \
+    (pthread_in_use () ? cond_wait (COND, LOCK) : 0)
+# define glthread_cond_timedwait(COND, LOCK, TS) \
+    (pthread_in_use () ? cond_timedwait (COND, LOCK, TS) : 0)
+# define glthread_cond_signal(COND) \
+    (pthread_in_use () ? cond_signal (COND) : 0)
+# define glthread_cond_broadcast(COND) \
+    (pthread_in_use () ? cond_broadcast (COND) : 0)
+# define glthread_cond_destroy(COND) \
+    (pthread_in_use () ? cond_destroy (COND) : 0)
+
+#endif
+
+/* ========================================================================= */
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported.  */
+
+typedef int gl_cond_t;
+# define gl_cond_define(STORAGECLASS, NAME)
+# define gl_cond_define_initialized(STORAGECLASS, NAME)
+# define glthread_cond_init(COND) 0
+# define glthread_cond_signal(COND) 0
+# define glthread_cond_broadcast(COND) 0
+# define glthread_cond_wait(COND, LOCK) 0
+# define glthread_cond_timedwait(COND, LOCK, TS) 0
+# define glthread_cond_destroy(COND) 0
+
+#endif
+
+
+/* ========================================================================= */
+
+/* Macros with built-in error handling.  */
+
+#define gl_cond_init(COND)                    \
+   do                                         \
+     {                                        \
+       if (glthread_cond_init (&COND))        \
+         abort ();                            \
+     }                                        \
+   while (0)
+#define gl_cond_wait(COND, LOCK)              \
+   do                                         \
+     {                                        \
+       if (glthread_cond_wait (&COND, &LOCK)) \
+         abort ();                            \
+     }                                        \
+   while (0)
+#define gl_cond_signal(COND)                  \
+   do                                         \
+     {                                        \
+       if (glthread_cond_signal (&COND))      \
+         abort ();                            \
+     }                                        \
+   while (0)
+#define gl_cond_broadcast(COND)               \
+   do                                         \
+     {                                        \
+       if (glthread_cond_broadcast (&COND))   \
+         abort ();                            \
+     }                                        \
+   while (0)
+#define gl_cond_destroy(COND)                 \
+   do                                         \
+     {                                        \
+       if (glthread_cond_destroy (&COND))     \
+         abort ();                            \
+     }                                        \
+   while (0)
+
+#endif                          /* _GLTHREAD_COND_H */
diff --git a/lib/glthread/thread.h b/lib/glthread/thread.h
new file mode 100644
index 0000000..3aa04f4
--- /dev/null
+++ b/lib/glthread/thread.h
@@ -0,0 +1,276 @@
+/* Locking in multithreaded situations.
+   Copyright (C) 2005-2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Bruno Haible <[EMAIL PROTECTED]>, 2005.
+   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
+   gthr-win32.h.  */
+
+/* This file contains locking primitives for use with a given thread library.
+   It does not contain primitives for creating threads or for other
+   synchronization primitives.
+*/
+
+
+#ifndef _GLTHREAD_THREAD_H
+#define _GLTHREAD_THREAD_H
+
+#include <errno.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library.  */
+
+# include <pthread.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The pthread_in_use() detection needs to be done at runtime.  */
+#  define pthread_in_use() \
+     glthread_in_use ()
+extern int glthread_in_use (void);
+
+# endif
+
+# if USE_POSIX_THREADS_WEAK
+
+/* Use weak references to the POSIX threads library.  */
+
+/* Weak references avoid dragging in external libraries if the other parts
+   of the program don't use them.  Here we use them, because we don't want
+   every program that uses libintl to depend on libpthread.  This assumes
+   that libpthread would not be loaded after libintl; i.e. if libintl is
+   loaded first, by an executable that does not depend on libpthread, and
+   then a module is dynamically loaded that depends on libpthread, libintl
+   will not be multithread-safe.  */
+
+/* The way to test at runtime whether libpthread is present is to test
+   whether a function pointer's value, such as &pthread_mutex_init, is
+   non-NULL.  However, some versions of GCC have a bug through which, in
+   PIC mode, &foo != NULL always evaluates to true if there is a direct
+   call to foo(...) in the same function.  To avoid this, we test the
+   address of a function in libpthread that we don't use.  */
+
+#  pragma weak pthread_create
+#  pragma weak pthread_join
+#  pragma weak pthread_self
+#  pragma weak pthread_exit
+#  pragma weak pthread_sigmask
+
+#  ifdef HAVE_PTHREAD_ATFORK
+#  pragma weak pthread_atfork
+#  endif
+
+#  if !PTHREAD_IN_USE_DETECTION_HARD
+#   pragma weak pthread_cancel
+#   define pthread_in_use() (pthread_cancel != NULL)
+#  endif
+
+# else
+
+#  if !PTHREAD_IN_USE_DETECTION_HARD
+#   define pthread_in_use() 1
+#  endif
+
+# endif
+
+
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+typedef pthread_t gl_thread_t;
+# define glthread_create(THREAD, FUNC, ARG) \
+    (pthread_in_use () ? pthread_create (THREAD, NULL, FUNC, ARG) : 0)
+# define glthread_sigmask(HOW, SET, OSET) \
+    (pthread_in_use () ? pthread_sigmask (HOW, SET, OSET) : 0)
+# define glthread_join(THREAD, VALPTR) \
+    (pthread_in_use () ? pthread_join (THREAD, VALPTR) : 0)
+# define glthread_self() \
+    (pthread_in_use () ? (void *) pthread_self () : 0)
+# define glthread_exit(VALPTR) \
+    (pthread_in_use () ? pthread_exit (VALPTR) : 0)
+
+# ifdef HAVE_PTHREAD_ATFORK
+#  define glthread_atfork(PREPARE, PARENT, CHILD) \
+     (pthread_in_use () ? pthread_atfork (PREPARE, PARENT, CHILD) : 0)
+# else
+#  define glthread_atfork(PREPARE, PARENT, CHILD) 0
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library.  */
+
+# include <pth.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_PTH_THREADS_WEAK
+
+/* Use weak references to the GNU Pth threads library.  */
+
+#  pragma weak pth_spawn
+#  pragma weak pth_sigmask
+#  pragma weak pth_join
+#  pragma weak pth_self
+#  pragma weak pth_exit
+#  pragma weak pth_cancel
+#  define pth_in_use() (pth_cancel != NULL)
+
+# else
+
+#  define pth_in_use() 1
+
+# endif
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+typedef pth_t gl_thread_t;
+# define glthread_create(THREAD, FUNC, ARG) \
+    (pth_in_use () ? ((*(THREAD) = pth_spawn (NULL, FUNC, ARG)) ? 0 : -1) : 0)
+# define glthread_sigmask(HOW, SET, OSET) \
+    (pth_in_use &&  !pth_sigmask (HOW, SET, OSET) ? errno : 0)
+# define glthread_join(THREAD, VALPTR) \
+    (pth_in_use () && !pth_join (THREAD, VALPTR) ? errno : 0)
+# define glthread_self() \
+    (pth_in_use () ? (void *) pth_self () : 0)
+# define glthread_exit(VALPTR) \
+    (pth_in_use () ? pth_exit (VALPTR) : 0)
+# define glthread_atfork(PREPARE, PARENT, CHILD) 0
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library.  */
+
+# include <thread.h>
+# include <synch.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_SOLARIS_THREADS_WEAK
+
+/* Use weak references to the old Solaris threads library.  */
+
+#  pragma weak thr_create
+#  pragma weak thr_join
+#  pragma weak thr_self
+#  pragma weak thr_exit
+#  pragma weak thr_suspend
+#  define thread_in_use() (thr_suspend != NULL)
+
+# else
+
+#  define thread_in_use() 1
+
+# endif
+
+/* -------------------------- gl_thread_t datatype -------------------------- */
+
+typedef thread_t gl_thread_t;
+# define glthread_create(THREAD, FUNC, ARG) \
+    (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREAD) : 0)
+# define glthread_sigmask(HOW, SET, OSET) \
+    (pthread_in_use () ? sigprocmask (HOW, SET, OSET) : 0)
+# define glthread_join(THREAD, RETVAL) \
+    (pthread_in_use () ? thr_join (THREAD, NULL, RETVAL) : 0)
+# define glthread_self() \
+    (pthread_in_use () ? (void *) thr_self () : 0)
+# define glthread_exit(VALPTR) \
+    (pthread_in_use () ? thr_exit (VALPTR) : 0)
+# define glthread_atfork(PREPARE, PARENT, CHILD) 0
+#endif
+
+
+/* ========================================================================= */
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported.  */
+
+typedef int gl_thread_t;
+# define glthread_create(THREAD, FUNC, ARG) 0
+# define glthread_sigmask(HOW, SET, OSET) 0
+# define glthread_join(THREAD, RETVAL) 0
+# define glthread_self() NULL
+# define glthread_exit(VALPTR) 0
+# define glthread_atfork(PREPARE, PARENT, CHILD) 0
+
+#endif
+
+
+/* ========================================================================= */
+
+/* Macros with built-in error handling.  */
+
+static inline int
+gl_thread_create_func (gl_thread_t * thread,
+                       void *(*func) (void *arg),
+                       void *arg)
+{
+  int ret;
+
+  ret = glthread_create (thread, func, arg);
+  if (ret)
+    abort ();
+
+  return ret;
+}
+
+#define gl_thread_create(THREAD, FUNC, ARG)      \
+        gl_thread_create_func(&THREAD, FUNC, ARG)
+
+#define gl_thread_sigmask(HOW, SET, OSET)          \
+   do                                              \
+     {                                             \
+       if (glthread_sigmask (HOW, SET, OSET))      \
+         abort ();                                 \
+     }                                             \
+   while (0)
+#define gl_thread_join(THREAD, RETVAL)             \
+   do                                              \
+     {                                             \
+       if (glthread_join (THREAD, RETVAL))         \
+         abort ();                                 \
+     }                                             \
+   while (0)
+#define gl_thread_atfork(PREPARE, PARENT, CHILD)     \
+   do                                                \
+     {                                               \
+       if (glthread_atfork (PREPARE, PARENT, CHILD)) \
+         abort ();                                   \
+     }                                               \
+   while (0)
+
+#endif                          /* _GLTHREAD_THREAD_H */
diff --git a/lib/glthread/yield.h b/lib/glthread/yield.h
new file mode 100644
index 0000000..217a099
--- /dev/null
+++ b/lib/glthread/yield.h
@@ -0,0 +1,93 @@
+/* Sched Yield in multithreaded situations.
+   Copyright (C) 2005-2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GLTHREAD_YIELD_H
+#define _GLTHREAD_YIELD_H
+
+#include <errno.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library.  */
+
+# include <sched.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define glthread_yield() sched_yield()
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library.  */
+
+# include <pth.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define glthread_yield() pth_yield(NULL)
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library.  */
+
+# include <thread.h>
+# include <synch.h>
+# include <stdlib.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define glthread_yield() thr_yield()
+#endif
+
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# define glthread_yield() Sleep(0)
+#endif
+
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported.  */
+
+# define glthread_yield() 0
+
+#endif
+
+#endif 
diff --git a/m4/cond.m4 b/m4/cond.m4
new file mode 100644
index 0000000..b98d51e
--- /dev/null
+++ b/m4/cond.m4
@@ -0,0 +1,11 @@
+# glcond.m4 serial 1 (gettext-0.15)
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_COND],
+[
+  AC_C_INLINE()
+  AC_REQUIRE([gl_LOCK])
+])
diff --git a/m4/thread.m4 b/m4/thread.m4
new file mode 100644
index 0000000..43bd94d
--- /dev/null
+++ b/m4/thread.m4
@@ -0,0 +1,15 @@
+# glcond.m4 serial 1 (gettext-0.15)
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_THREAD],
+[
+  AC_C_INLINE()
+  AC_REQUIRE([gl_LOCK])
+
+  if test $gl_threads_api = posix; then
+    AC_CHECK_FUNC(pthread_atfork)
+  fi
+])
diff --git a/m4/yield.m4 b/m4/yield.m4
new file mode 100644
index 0000000..933471e
--- /dev/null
+++ b/m4/yield.m4
@@ -0,0 +1,21 @@
+# glcond.m4 serial 1 (gettext-0.15)
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_YIELD],
+[
+  AC_REQUIRE([gl_LOCK])
+
+  dnl Checks for special libraries for the tests/test-tls test.
+  dnl dnl On some systems, sched_yield is in librt, rather than in libpthread.
+  LIBSCHED=
+  if test $gl_threads_api = posix; then
+    dnl Solaris has sched_yield in librt, not in libpthread or libc.
+    AC_CHECK_LIB(rt, sched_yield, [LIBSCHED=-lrt],
+         [dnl Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt.
+          AC_CHECK_LIB(posix4, sched_yield, [LIBSCHED=-lposix4])])
+  fi
+  AC_SUBST([LIBSCHED])
+])
diff --git a/modules/cond b/modules/cond
new file mode 100644
index 0000000..5cf6bad
--- /dev/null
+++ b/modules/cond
@@ -0,0 +1,25 @@
+Description:
+Condition in multithreaded situations.
+
+Files:
+lib/glthread/cond.h
+m4/cond.m4
+
+Depends-on:
+lock
+
+configure.ac:
+gl_COND
+
+Makefile.am:
+lib_SOURCES += glthread/cond.h
+
+Include:
+"glthread/cond.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Yoann Vandoorselaere
+
diff --git a/modules/cond-tests b/modules/cond-tests
new file mode 100644
index 0000000..9b4465d
--- /dev/null
+++ b/modules/cond-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-cond.c
+
+Depends-on:
+lock
+yield
+
+Makefile.am:
+TESTS += test-cond
+check_PROGRAMS += test-cond
+test_cond_LDADD = $(LDADD) @LIBMULTITHREAD@ @LIBSCHED@
diff --git a/modules/lock-tests b/modules/lock-tests
index 7c72c94..13b5831 100644
--- a/modules/lock-tests
+++ b/modules/lock-tests
@@ -2,18 +2,8 @@ Files:
 tests/test-lock.c
 
 Depends-on:
-
-configure.ac:
-dnl Checks for special libraries for the tests/test-lock test.
-dnl On some systems, sched_yield is in librt, rather than in libpthread.
-LIBSCHED=
-if test $gl_threads_api = posix; then
-  dnl Solaris has sched_yield in librt, not in libpthread or libc.
-  AC_CHECK_LIB(rt, sched_yield, [LIBSCHED=-lrt],
-    [dnl Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt.
-     AC_CHECK_LIB(posix4, sched_yield, [LIBSCHED=-lposix4])])
-fi
-AC_SUBST([LIBSCHED])
+thread
+yield
 
 Makefile.am:
 TESTS += test-lock
diff --git a/modules/thread b/modules/thread
new file mode 100644
index 0000000..af58919
--- /dev/null
+++ b/modules/thread
@@ -0,0 +1,25 @@
+Description:
+Locking in multithreaded situations.
+
+Files:
+lib/glthread/thread.h
+m4/thread.m4
+
+Depends-on:
+lock
+
+configure.ac:
+gl_THREAD
+
+Makefile.am:
+lib_SOURCES += glthread/thread.h 
+
+Include:
+"glthread/thread.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Yoann Vandoorselaere
+
diff --git a/modules/tls-tests b/modules/tls-tests
index b9f5a23..fbae090 100644
--- a/modules/tls-tests
+++ b/modules/tls-tests
@@ -2,18 +2,7 @@ Files:
 tests/test-tls.c
 
 Depends-on:
-
-configure.ac:
-dnl Checks for special libraries for the tests/test-tls test.
-dnl On some systems, sched_yield is in librt, rather than in libpthread.
-LIBSCHED=
-if test $gl_threads_api = posix; then
-  dnl Solaris has sched_yield in librt, not in libpthread or libc.
-  AC_CHECK_LIB(rt, sched_yield, [LIBSCHED=-lrt],
-    [dnl Solaris 2.5.1, 2.6 has sched_yield in libposix4, not librt.
-     AC_CHECK_LIB(posix4, sched_yield, [LIBSCHED=-lposix4])])
-fi
-AC_SUBST([LIBSCHED])
+yield
 
 Makefile.am:
 TESTS += test-tls
diff --git a/modules/yield b/modules/yield
new file mode 100644
index 0000000..479b43b
--- /dev/null
+++ b/modules/yield
@@ -0,0 +1,25 @@
+Description:
+Sched yield in multithreaded situations.
+
+Files:
+lib/glthread/yield.h
+m4/yield.m4
+
+Depends-on:
+lock
+
+configure.ac:
+gl_YIELD
+
+Makefile.am:
+lib_SOURCES += glthread/yield.h 
+
+Include:
+"glthread/yield.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+Yoann Vandoorselaere
+
diff --git a/tests/test-cond.c b/tests/test-cond.c
new file mode 100644
index 0000000..541c8b8
--- /dev/null
+++ b/tests/test-cond.c
@@ -0,0 +1,235 @@
+/* Test of condition in multithreaded situations.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#if USE_POSIX_THREADS || USE_SOLARIS_THREADS || USE_PTH_THREADS || USE_WIN32_THREADS
+
+#if USE_POSIX_THREADS
+# define TEST_POSIX_THREADS 1
+#endif
+#if USE_SOLARIS_THREADS
+# define TEST_SOLARIS_THREADS 1
+#endif
+#if USE_PTH_THREADS
+# define TEST_PTH_THREADS 1
+#endif
+#if USE_WIN32_THREADS
+# define TEST_WIN32_THREADS 1
+#endif
+
+/* Whether to enable locking.
+   Uncomment this to get a test program without locking, to verify that
+   it crashes.  */
+#define ENABLE_LOCKING 1
+
+/* Which tests to perform.
+   Uncomment some of these, to verify that all tests crash if no locking
+   is enabled.  */
+#define DO_TEST_COND 1
+#define DO_TEST_TIMEDCOND 1
+
+
+/* Whether to help the scheduler through explicit yield().
+   Uncomment this to see if the operating system has a fair scheduler.  */
+#define EXPLICIT_YIELD 1
+
+/* Whether to print debugging messages.  */
+#define ENABLE_DEBUGGING 0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if !ENABLE_LOCKING
+# undef USE_POSIX_THREADS
+# undef USE_SOLARIS_THREADS
+# undef USE_PTH_THREADS
+# undef USE_WIN32_THREADS
+#endif
+
+#include "glthread/thread.h"
+#include "glthread/cond.h"
+#include "glthread/lock.h"
+#include "glthread/yield.h"
+
+#if ENABLE_DEBUGGING
+# define dbgprintf printf
+#else
+# define dbgprintf if (0) printf
+#endif
+
+#if EXPLICIT_YIELD
+# define yield() glthread_yield ()
+#else
+# define yield()
+#endif
+
+
+/*
+ * Condition check
+ */
+#include <unistd.h>
+static int cond_value = 0;
+static gl_cond_t condtest = gl_cond_initializer;
+static gl_lock_t lockcond = gl_lock_initializer;
+
+static void *
+cond_routine (void *arg)
+{
+  gl_lock_lock (lockcond);
+  while (!cond_value)
+    {
+      gl_cond_wait (condtest, lockcond);
+    }
+  gl_lock_unlock (lockcond);
+
+  cond_value = 2;
+
+  return NULL;
+}
+
+void
+test_cond ()
+{
+  int remain = 2;
+  gl_thread_t thread;
+
+  cond_value = 0;
+
+  gl_thread_create (thread, cond_routine, NULL);
+  do
+    {
+      yield ();
+      remain = sleep (remain);
+    }
+  while (remain);
+
+  /* signal condition */
+  gl_lock_lock (lockcond);
+  cond_value = 1;
+  gl_cond_signal (condtest);
+  gl_lock_unlock (lockcond);
+
+  gl_thread_join (thread, NULL);
+
+  if (cond_value != 2)
+    abort ();
+}
+
+
+/*
+ * Timed Condition check
+ */
+static int cond_timeout;
+
+static void
+get_ts (struct timespec *ts)
+{
+  struct timeval now;
+
+  gettimeofday (&now, NULL);
+
+  ts->tv_sec = now.tv_sec + 1;
+  ts->tv_nsec = now.tv_usec * 1000;
+}
+
+static void *
+timedcond_routine (void *arg)
+{
+  int ret;
+  struct timespec ts;
+
+  gl_lock_lock (lockcond);
+  while (!cond_value)
+    {
+      get_ts (&ts);
+      ret = glthread_cond_timedwait (&condtest, &lockcond, &ts);
+      if (ret == ETIMEDOUT)
+        cond_timeout = 1;
+    }
+  gl_lock_unlock (lockcond);
+
+  return NULL;
+}
+
+static void
+test_timedcond (void)
+{
+  int remain = 2;
+  gl_thread_t thread;
+
+  cond_value = cond_timeout = 0;
+
+  gl_thread_create (thread, timedcond_routine, NULL);
+
+  remain = 2;
+  do
+    {
+      yield ();
+      remain = sleep (remain);
+    }
+  while (remain);
+
+  /* signal condition */
+  gl_lock_lock (lockcond);
+  cond_value = 1;
+  gl_cond_signal (condtest);
+  gl_lock_unlock (lockcond);
+
+  gl_thread_join (thread, NULL);
+
+  if (!cond_timeout)
+    abort ();
+}
+
+int
+main ()
+{
+#if TEST_PTH_THREADS
+  if (!pth_init ())
+    abort ();
+#endif
+
+#if DO_TEST_COND
+  printf ("Starting test_cond ...");
+  fflush (stdout);
+  test_cond ();
+  printf (" OK\n");
+  fflush (stdout);
+#endif
+#if DO_TEST_TIMEDCOND
+  printf ("Starting test_timedcond ...");
+  fflush (stdout);
+  test_timedcond ();
+  printf (" OK\n");
+  fflush (stdout);
+#endif
+
+  return 0;
+}
+
+#else
+
+/* No multithreading available.  */
+
+int
+main ()
+{
+  return 77;
+}
+
+#endif
diff --git a/tests/test-lock.c b/tests/test-lock.c
index 6d2278e..75455b6 100644
--- a/tests/test-lock.c
+++ b/tests/test-lock.c
@@ -45,6 +45,8 @@
 #define DO_TEST_RWLOCK 1
 #define DO_TEST_RECURSIVE_LOCK 1
 #define DO_TEST_ONCE 1
+#define DO_TEST_COND 1
+
 
 /* Whether to help the scheduler through explicit yield().
    Uncomment this to see if the operating system has a fair scheduler.  */
@@ -71,7 +73,10 @@
 # undef USE_PTH_THREADS
 # undef USE_WIN32_THREADS
 #endif
+
+#include "glthread/thread.h"
 #include "glthread/lock.h"
+#include "glthread/yield.h"
 
 #if ENABLE_DEBUGGING
 # define dbgprintf printf
@@ -79,81 +84,6 @@
 # define dbgprintf if (0) printf
 #endif
 
-#if TEST_POSIX_THREADS
-# include <pthread.h>
-# include <sched.h>
-typedef pthread_t gl_thread_t;
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  pthread_t thread;
-  if (pthread_create (&thread, NULL, func, arg) != 0)
-    abort ();
-  return thread;
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  void *retval;
-  if (pthread_join (thread, &retval) != 0)
-    abort ();
-}
-static inline void gl_thread_yield (void)
-{
-  sched_yield ();
-}
-static inline void * gl_thread_self (void)
-{
-  return (void *) pthread_self ();
-}
-#endif
-#if TEST_PTH_THREADS
-# include <pth.h>
-typedef pth_t gl_thread_t;
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  pth_t thread = pth_spawn (NULL, func, arg);
-  if (thread == NULL)
-    abort ();
-  return thread;
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  if (!pth_join (thread, NULL))
-    abort ();
-}
-static inline void gl_thread_yield (void)
-{
-  pth_yield (NULL);
-}
-static inline void * gl_thread_self (void)
-{
-  return pth_self ();
-}
-#endif
-#if TEST_SOLARIS_THREADS
-# include <thread.h>
-typedef thread_t gl_thread_t;
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  thread_t thread;
-  if (thr_create (NULL, 0, func, arg, 0, &thread) != 0)
-    abort ();
-  return thread;
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  void *retval;
-  if (thr_join (thread, NULL, &retval) != 0)
-    abort ();
-}
-static inline void gl_thread_yield (void)
-{
-  thr_yield ();
-}
-static inline void * gl_thread_self (void)
-{
-  return (void *) thr_self ();
-}
-#endif
 #if TEST_WIN32_THREADS
 # include <windows.h>
 typedef HANDLE gl_thread_t;
@@ -192,17 +122,13 @@ static inline void gl_thread_join (gl_thread_t thread)
   if (!CloseHandle (thread))
     abort ();
 }
-static inline void gl_thread_yield (void)
-{
-  Sleep (0);
-}
 static inline void * gl_thread_self (void)
 {
   return (void *) GetCurrentThreadId ();
 }
 #endif
 #if EXPLICIT_YIELD
-# define yield() gl_thread_yield ()
+# define yield() glthread_yield ()
 #else
 # define yield()
 #endif
@@ -244,9 +170,9 @@ lock_mutator_thread (void *arg)
     {
       int i1, i2, value;
 
-      dbgprintf ("Mutator %p before lock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p before lock\n", glthread_self ());
       gl_lock_lock (my_lock);
-      dbgprintf ("Mutator %p after  lock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p after  lock\n", glthread_self ());
 
       i1 = random_account ();
       i2 = random_account ();
@@ -254,20 +180,20 @@ lock_mutator_thread (void *arg)
       account[i1] += value;
       account[i2] -= value;
 
-      dbgprintf ("Mutator %p before unlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p before unlock\n", glthread_self ());
       gl_lock_unlock (my_lock);
-      dbgprintf ("Mutator %p after  unlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p after  unlock\n", glthread_self ());
 
-      dbgprintf ("Mutator %p before check lock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p before check lock\n", glthread_self ());
       gl_lock_lock (my_lock);
       check_accounts ();
       gl_lock_unlock (my_lock);
-      dbgprintf ("Mutator %p after  check unlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p after  check unlock\n", glthread_self ());
 
       yield ();
     }
 
-  dbgprintf ("Mutator %p dying.\n", gl_thread_self ());
+  dbgprintf ("Mutator %p dying.\n", glthread_self ());
   return NULL;
 }
 
@@ -278,16 +204,16 @@ lock_checker_thread (void *arg)
 {
   while (!lock_checker_done)
     {
-      dbgprintf ("Checker %p before check lock\n", gl_thread_self ());
+      dbgprintf ("Checker %p before check lock\n", glthread_self ());
       gl_lock_lock (my_lock);
       check_accounts ();
       gl_lock_unlock (my_lock);
-      dbgprintf ("Checker %p after  check unlock\n", gl_thread_self ());
+      dbgprintf ("Checker %p after  check unlock\n", glthread_self ());
 
       yield ();
     }
 
-  dbgprintf ("Checker %p dying.\n", gl_thread_self ());
+  dbgprintf ("Checker %p dying.\n", glthread_self ());
   return NULL;
 }
 
@@ -304,15 +230,15 @@ test_lock (void)
   lock_checker_done = 0;
 
   /* Spawn the threads.  */
-  checkerthread = gl_thread_create (lock_checker_thread, NULL);
+  gl_thread_create (checkerthread, lock_checker_thread, NULL);
   for (i = 0; i < THREAD_COUNT; i++)
-    threads[i] = gl_thread_create (lock_mutator_thread, NULL);
+    gl_thread_create (threads[i], lock_mutator_thread, NULL);
 
   /* Wait for the threads to terminate.  */
   for (i = 0; i < THREAD_COUNT; i++)
-    gl_thread_join (threads[i]);
+    gl_thread_join (threads[i], NULL);
   lock_checker_done = 1;
-  gl_thread_join (checkerthread);
+  gl_thread_join (checkerthread, NULL);
   check_accounts ();
 }
 
@@ -331,9 +257,9 @@ rwlock_mutator_thread (void *arg)
     {
       int i1, i2, value;
 
-      dbgprintf ("Mutator %p before wrlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p before wrlock\n", glthread_self ());
       gl_rwlock_wrlock (my_rwlock);
-      dbgprintf ("Mutator %p after  wrlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p after  wrlock\n", glthread_self ());
 
       i1 = random_account ();
       i2 = random_account ();
@@ -341,14 +267,14 @@ rwlock_mutator_thread (void *arg)
       account[i1] += value;
       account[i2] -= value;
 
-      dbgprintf ("Mutator %p before unlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p before unlock\n", glthread_self ());
       gl_rwlock_unlock (my_rwlock);
-      dbgprintf ("Mutator %p after  unlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p after  unlock\n", glthread_self ());
 
       yield ();
     }
 
-  dbgprintf ("Mutator %p dying.\n", gl_thread_self ());
+  dbgprintf ("Mutator %p dying.\n", glthread_self ());
   return NULL;
 }
 
@@ -359,16 +285,16 @@ rwlock_checker_thread (void *arg)
 {
   while (!rwlock_checker_done)
     {
-      dbgprintf ("Checker %p before check rdlock\n", gl_thread_self ());
+      dbgprintf ("Checker %p before check rdlock\n", glthread_self ());
       gl_rwlock_rdlock (my_rwlock);
       check_accounts ();
       gl_rwlock_unlock (my_rwlock);
-      dbgprintf ("Checker %p after  check unlock\n", gl_thread_self ());
+      dbgprintf ("Checker %p after  check unlock\n", glthread_self ());
 
       yield ();
     }
 
-  dbgprintf ("Checker %p dying.\n", gl_thread_self ());
+  dbgprintf ("Checker %p dying.\n", glthread_self ());
   return NULL;
 }
 
@@ -386,16 +312,16 @@ test_rwlock (void)
 
   /* Spawn the threads.  */
   for (i = 0; i < THREAD_COUNT; i++)
-    checkerthreads[i] = gl_thread_create (rwlock_checker_thread, NULL);
+    gl_thread_create (checkerthreads[i], rwlock_checker_thread, NULL);
   for (i = 0; i < THREAD_COUNT; i++)
-    threads[i] = gl_thread_create (rwlock_mutator_thread, NULL);
+    gl_thread_create (threads[i], rwlock_mutator_thread, NULL);
 
   /* Wait for the threads to terminate.  */
   for (i = 0; i < THREAD_COUNT; i++)
-    gl_thread_join (threads[i]);
+    gl_thread_join (threads[i], NULL);
   rwlock_checker_done = 1;
   for (i = 0; i < THREAD_COUNT; i++)
-    gl_thread_join (checkerthreads[i]);
+    gl_thread_join (checkerthreads[i], NULL);
   check_accounts ();
 }
 
@@ -410,9 +336,9 @@ recshuffle (void)
 {
   int i1, i2, value;
 
-  dbgprintf ("Mutator %p before lock\n", gl_thread_self ());
+  dbgprintf ("Mutator %p before lock\n", glthread_self ());
   gl_recursive_lock_lock (my_reclock);
-  dbgprintf ("Mutator %p after  lock\n", gl_thread_self ());
+  dbgprintf ("Mutator %p after  lock\n", glthread_self ());
 
   i1 = random_account ();
   i2 = random_account ();
@@ -424,9 +350,9 @@ recshuffle (void)
   if (((unsigned int) rand() >> 3) % 2)
     recshuffle ();
 
-  dbgprintf ("Mutator %p before unlock\n", gl_thread_self ());
+  dbgprintf ("Mutator %p before unlock\n", glthread_self ());
   gl_recursive_lock_unlock (my_reclock);
-  dbgprintf ("Mutator %p after  unlock\n", gl_thread_self ());
+  dbgprintf ("Mutator %p after  unlock\n", glthread_self ());
 }
 
 static void *
@@ -438,16 +364,16 @@ reclock_mutator_thread (void *arg)
     {
       recshuffle ();
 
-      dbgprintf ("Mutator %p before check lock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p before check lock\n", glthread_self ());
       gl_recursive_lock_lock (my_reclock);
       check_accounts ();
       gl_recursive_lock_unlock (my_reclock);
-      dbgprintf ("Mutator %p after  check unlock\n", gl_thread_self ());
+      dbgprintf ("Mutator %p after  check unlock\n", glthread_self ());
 
       yield ();
     }
 
-  dbgprintf ("Mutator %p dying.\n", gl_thread_self ());
+  dbgprintf ("Mutator %p dying.\n", glthread_self ());
   return NULL;
 }
 
@@ -458,16 +384,16 @@ reclock_checker_thread (void *arg)
 {
   while (!reclock_checker_done)
     {
-      dbgprintf ("Checker %p before check lock\n", gl_thread_self ());
+      dbgprintf ("Checker %p before check lock\n", glthread_self ());
       gl_recursive_lock_lock (my_reclock);
       check_accounts ();
       gl_recursive_lock_unlock (my_reclock);
-      dbgprintf ("Checker %p after  check unlock\n", gl_thread_self ());
+      dbgprintf ("Checker %p after  check unlock\n", glthread_self ());
 
       yield ();
     }
 
-  dbgprintf ("Checker %p dying.\n", gl_thread_self ());
+  dbgprintf ("Checker %p dying.\n", glthread_self ());
   return NULL;
 }
 
@@ -484,15 +410,15 @@ test_recursive_lock (void)
   reclock_checker_done = 0;
 
   /* Spawn the threads.  */
-  checkerthread = gl_thread_create (reclock_checker_thread, NULL);
+  gl_thread_create (checkerthread, reclock_checker_thread, NULL);
   for (i = 0; i < THREAD_COUNT; i++)
-    threads[i] = gl_thread_create (reclock_mutator_thread, NULL);
+    gl_thread_create (threads[i], reclock_mutator_thread, NULL);
 
   /* Wait for the threads to terminate.  */
   for (i = 0; i < THREAD_COUNT; i++)
-    gl_thread_join (threads[i]);
+    gl_thread_join (threads[i], NULL);
   reclock_checker_done = 1;
-  gl_thread_join (checkerthread);
+  gl_thread_join (checkerthread, NULL);
   check_accounts ();
 }
 
@@ -533,10 +459,10 @@ once_contender_thread (void *arg)
       gl_lock_unlock (ready_lock[id]);
 
       if (repeat == REPEAT_COUNT)
-	break;
+        break;
 
       dbgprintf ("Contender %p waiting for signal for round %d\n",
-		 gl_thread_self (), repeat);
+                 glthread_self (), repeat);
 #if ENABLE_LOCKING
       /* Wait for the signal to go.  */
       gl_rwlock_rdlock (fire_signal[repeat]);
@@ -545,10 +471,10 @@ once_contender_thread (void *arg)
 #else
       /* Wait for the signal to go.  */
       while (fire_signal_state <= repeat)
-	yield ();
+        yield ();
 #endif
       dbgprintf ("Contender %p got the     signal for round %d\n",
-		 gl_thread_self (), repeat);
+                 glthread_self (), repeat);
 
       /* Contend for execution.  */
       gl_once (once_control, once_execute);
@@ -582,37 +508,37 @@ test_once (void)
 
   /* Spawn the threads.  */
   for (i = 0; i < THREAD_COUNT; i++)
-    threads[i] = gl_thread_create (once_contender_thread, (void *) (long) i);
+    gl_thread_create (threads[i], once_contender_thread, (void *) (long) i);
 
   for (repeat = 0; repeat <= REPEAT_COUNT; repeat++)
     {
       /* Wait until every thread is ready.  */
       dbgprintf ("Main thread before synchonizing for round %d\n", repeat);
       for (;;)
-	{
-	  int ready_count = 0;
-	  for (i = 0; i < THREAD_COUNT; i++)
-	    {
-	      gl_lock_lock (ready_lock[i]);
-	      ready_count += ready[i];
-	      gl_lock_unlock (ready_lock[i]);
-	    }
-	  if (ready_count == THREAD_COUNT)
-	    break;
-	  yield ();
-	}
+        {
+          int ready_count = 0;
+          for (i = 0; i < THREAD_COUNT; i++)
+            {
+              gl_lock_lock (ready_lock[i]);
+              ready_count += ready[i];
+              gl_lock_unlock (ready_lock[i]);
+            }
+          if (ready_count == THREAD_COUNT)
+            break;
+          yield ();
+        }
       dbgprintf ("Main thread after  synchonizing for round %d\n", repeat);
 
       if (repeat > 0)
-	{
-	  /* Check that exactly one thread executed the once_execute()
-	     function.  */
-	  if (performed != 1)
-	    abort ();
-	}
+        {
+          /* Check that exactly one thread executed the once_execute()
+             function.  */
+          if (performed != 1)
+            abort ();
+        }
 
       if (repeat == REPEAT_COUNT)
-	break;
+        break;
 
       /* Preparation for the next round: Initialize once_control.  */
       memcpy (&once_control, &fresh_once, sizeof (gl_once_t));
@@ -622,11 +548,11 @@ test_once (void)
 
       /* Preparation for the next round: Reset the ready flags.  */
       for (i = 0; i < THREAD_COUNT; i++)
-	{
-	  gl_lock_lock (ready_lock[i]);
-	  ready[i] = 0;
-	  gl_lock_unlock (ready_lock[i]);
-	}
+        {
+          gl_lock_lock (ready_lock[i]);
+          ready[i] = 0;
+          gl_lock_unlock (ready_lock[i]);
+        }
 
       /* Signal all threads simultaneously.  */
       dbgprintf ("Main thread giving signal for round %d\n", repeat);
@@ -639,7 +565,7 @@ test_once (void)
 
   /* Wait for the threads to terminate.  */
   for (i = 0; i < THREAD_COUNT; i++)
-    gl_thread_join (threads[i]);
+    gl_thread_join (threads[i], NULL);
 }
 
 int
diff --git a/tests/test-tls.c b/tests/test-tls.c
index 83c4ffb..e663431 100644
--- a/tests/test-tls.c
+++ b/tests/test-tls.c
@@ -50,7 +50,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "glthread/thread.h"
 #include "glthread/tls.h"
+#include "glthread/yield.h"
 
 #if ENABLE_DEBUGGING
 # define dbgprintf printf
@@ -58,81 +60,6 @@
 # define dbgprintf if (0) printf
 #endif
 
-#if TEST_POSIX_THREADS
-# include <pthread.h>
-# include <sched.h>
-typedef pthread_t gl_thread_t;
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  pthread_t thread;
-  if (pthread_create (&thread, NULL, func, arg) != 0)
-    abort ();
-  return thread;
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  void *retval;
-  if (pthread_join (thread, &retval) != 0)
-    abort ();
-}
-static inline void gl_thread_yield (void)
-{
-  sched_yield ();
-}
-static inline void * gl_thread_self (void)
-{
-  return (void *) pthread_self ();
-}
-#endif
-#if TEST_PTH_THREADS
-# include <pth.h>
-typedef pth_t gl_thread_t;
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  pth_t thread = pth_spawn (NULL, func, arg);
-  if (thread == NULL)
-    abort ();
-  return thread;
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  if (!pth_join (thread, NULL))
-    abort ();
-}
-static inline void gl_thread_yield (void)
-{
-  pth_yield (NULL);
-}
-static inline void * gl_thread_self (void)
-{
-  return pth_self ();
-}
-#endif
-#if TEST_SOLARIS_THREADS
-# include <thread.h>
-typedef thread_t gl_thread_t;
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  thread_t thread;
-  if (thr_create (NULL, 0, func, arg, 0, &thread) != 0)
-    abort ();
-  return thread;
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  void *retval;
-  if (thr_join (thread, NULL, &retval) != 0)
-    abort ();
-}
-static inline void gl_thread_yield (void)
-{
-  thr_yield ();
-}
-static inline void * gl_thread_self (void)
-{
-  return (void *) thr_self ();
-}
-#endif
 #if TEST_WIN32_THREADS
 # include <windows.h>
 typedef HANDLE gl_thread_t;
@@ -171,17 +98,14 @@ static inline void gl_thread_join (gl_thread_t thread)
   if (!CloseHandle (thread))
     abort ();
 }
-static inline void gl_thread_yield (void)
-{
-  Sleep (0);
-}
 static inline void * gl_thread_self (void)
 {
   return (void *) GetCurrentThreadId ();
 }
 #endif
+
 #if EXPLICIT_YIELD
-# define yield() gl_thread_yield ()
+# define yield() glthread_yield ()
 #else
 # define yield()
 #endif
@@ -284,11 +208,11 @@ test_tls (void)
 
       /* Spawn the threads.  */
       for (i = 0; i < THREAD_COUNT; i++)
-	threads[i] = gl_thread_create (worker_thread, NULL);
+	gl_thread_create (threads[i], worker_thread, NULL);
 
       /* Wait for the threads to terminate.  */
       for (i = 0; i < THREAD_COUNT; i++)
-	gl_thread_join (threads[i]);
+	gl_thread_join (threads[i], NULL);
 
       for (i = 0; i < KEYS_COUNT; i++)
 	gl_tls_key_destroy (mykeys[i]);

Reply via email to