Le lundi 15 septembre 2008 à 14:12 +0200, Yoann Vandoorselaere a écrit :
> Le dimanche 14 septembre 2008 à 20:46 +0200, Yoann Vandoorselaere a
> écrit :
> > Hi,
> > 
> > Attached is a patch implementing the following glthread fixes:
> > 
> > - Correct pthread_atfork() detection.
> > 
> > - Add the missing cond-tests module.
> > 
> > - Make 'lock-tests' and 'tls-tests' depend on the thread and yield
> > module, use YIELD_LIBS in place of the deprecated LIBSCHED variable, and
> > update 'lock-tests.c' and 'tls-tests.c' to use newer glthread API.
> 
> The patch contained modification to threadlib.m4 that you didn't
> approved earlier (implementation of THREADCPPFLAGS), here is an updated
> diff without this part.

Hi Bruno,

Here is a new version of the patches, contain more dependencies fixes,
and provide a working implementation of gl_cond_t for WIN32 platform
(based on http://www.cs.wustl.edu/~schmidt/win32-cv-1.html).

Regards,

-- 
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.c b/lib/glthread/cond.c
index e3073d5..d7a3626 100644
--- a/lib/glthread/cond.c
+++ b/lib/glthread/cond.c
@@ -18,11 +18,200 @@
 /* Written by Yoann Vandoorselaere <[EMAIL PROTECTED]>, 2008.  */
 
 #include <config.h>
+#include <sys/time.h>
 
 #include "glthread/cond.h"
 
 /* ========================================================================= */
 
+#if USE_WIN32_THREADS
+
+/*
+ * WIN32 implementation based on http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
+ */
+
+int glthread_cond_init_func(gl_cond_t *cv)
+{
+  cv->waiters_count = 0;
+  cv->wait_generation_count = 0;
+  cv->release_count = 0;
+  
+  InitializeCriticalSection(&cv->lock);
+
+  /* Create a manual-reset event. */
+  cv->event = CreateEvent (NULL, TRUE, FALSE, NULL);
+  cv->guard.done = 1;
+
+  return 0;
+}
+
+
+static void 
+init_once(gl_cond_t *cv)
+{
+  if (!cv->guard.done)
+    {
+      if (InterlockedIncrement (&cv->guard.started) == 0)
+        /* This thread is the first one to need this lock.  Initialize it.  */
+        glthread_cond_init (cv);
+      else
+        /* Yield the CPU while waiting for another thread to finish
+           initializing this lock.  */
+        while (!cv->guard.done)
+          Sleep (0);
+    }
+}
+
+
+int glthread_cond_destroy_func(gl_cond_t *cv)
+{
+  CloseHandle(cv->event);
+  return 0;
+}
+
+
+static int cond_wait(gl_cond_t *cv, gl_lock_t *external_mutex, DWORD msec)
+{
+  int ret, my_generation, wait_done; 
+
+  init_once(cv);
+
+  EnterCriticalSection(&cv->lock);
+
+  /* Increment count of waiters, 
+    and store current generation in our activation record. */
+  cv->waiters_count++;
+  my_generation = cv->wait_generation_count;
+
+  LeaveCriticalSection(&cv->lock);
+  glthread_lock_unlock(external_mutex);
+
+  do 
+   {
+    /* Wait until the event is signaled. */
+    ret = WaitForSingleObject (cv->event, msec);
+    if ( ret != WAIT_OBJECT_0 )
+      break;
+
+    EnterCriticalSection (&cv->lock);
+    /* Exit the loop when the event is signaled and there are still
+       waiting threads from this <wait_generation> that haven't been released from this wait yet.
+     */
+    wait_done = cv->release_count > 0 && cv->wait_generation_count != my_generation;
+    LeaveCriticalSection (&cv->lock);
+  } while (!wait_done);
+
+  glthread_lock_lock(external_mutex);
+  EnterCriticalSection(&cv->lock);
+  cv->waiters_count--;
+
+  if ( ret == WAIT_OBJECT_0 ) 
+    {
+      if ( --cv->release_count == 0 )
+        /* We're the last waiter to be notified, so reset the manual event. */
+        ResetEvent (cv->event);
+    }
+
+  LeaveCriticalSection (&cv->lock);
+
+  return (ret == WAIT_TIMEOUT) ? ETIMEDOUT : (ret == WAIT_OBJECT_0) ? 0 : -1;
+}
+
+
+int glthread_cond_wait_func(gl_cond_t *cv, gl_lock_t *external_mutex)
+{
+  return cond_wait(cv, external_mutex, INFINITE);
+}
+
+
+/* Subtract the `struct timeval' values X and Y,
+        storing the result in RESULT.
+        Return 1 if the difference is negative, otherwise 0.  */
+     
+static int 
+timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y)
+{
+  /* Perform the carry for the later subtraction by updating y. */
+  if (x->tv_usec < y->tv_usec) 
+    {
+      int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
+      y->tv_usec -= 1000000 * nsec;
+      y->tv_sec += nsec;
+    }
+  if (x->tv_usec - y->tv_usec > 1000000) 
+    {
+      int nsec = (x->tv_usec - y->tv_usec) / 1000000;
+      y->tv_usec += 1000000 * nsec;
+      y->tv_sec -= nsec;
+    }
+     
+  /* Compute the time remaining to wait.
+     tv_usec is certainly positive. */
+  result->tv_sec = x->tv_sec - y->tv_sec;
+  result->tv_usec = x->tv_usec - y->tv_usec;
+     
+  /* Return 1 if result is negative. */
+  return x->tv_sec < y->tv_sec;
+}
+
+
+int glthread_cond_timedwait_func(gl_cond_t *cv, gl_lock_t *external_mutex, struct timespec *ts)
+{
+  struct timeval res, now, end;
+
+  end.tv_sec = ts->tv_sec;
+  end.tv_usec = ts->tv_nsec / 1000;
+  gettimeofday(&now, NULL);
+
+  timeval_subtract(&res, &end, &now);
+
+  return cond_wait(cv, external_mutex, (res.tv_sec * 1000) + (res.tv_usec / 1000));
+}
+
+
+int glthread_cond_broadcast_func(gl_cond_t *cv)
+{
+  init_once(cv);
+
+  EnterCriticalSection(&cv->lock);
+  /* The pthread_cond_broadcast() and pthread_cond_signal() functions  shall
+     have no effect if there are no threads currently blocked on cond.
+   */
+  if (cv->waiters_count > 0) 
+    {  
+      SetEvent(cv->event);
+      /* Release all the threads in this generation. */
+      cv->release_count = cv->waiters_count;
+      cv->wait_generation_count++;
+    }
+  LeaveCriticalSection(&cv->lock);
+
+  return 0;
+}
+
+	
+int glthread_cond_signal_func(gl_cond_t *cv)
+{
+  init_once(cv);
+
+  EnterCriticalSection(&cv->lock);
+  /* The pthread_cond_broadcast() and pthread_cond_signal() functions  shall
+     have no effect if there are no threads currently blocked on cond.
+   */
+  if (cv->waiters_count > cv->release_count)
+    {
+      SetEvent(cv->event); /* Signal the manual-reset event.*/
+      cv->release_count++;
+      cv->wait_generation_count++;
+    }
+  LeaveCriticalSection(&cv->lock);
+
+  return 0;
+}
+
+
+#endif
+
 #if USE_PTH_THREADS
 
 /* -------------------------- gl_cond_t datatype -------------------------- */
diff --git a/lib/glthread/cond.h b/lib/glthread/cond.h
index 5939004..54c150a 100644
--- a/lib/glthread/cond.h
+++ b/lib/glthread/cond.h
@@ -52,6 +52,7 @@
 #include <errno.h>
 #include <stdbool.h>
 #include <stdlib.h>
+#include <time.h>
 
 #include "glthread/lock.h"
 
@@ -266,13 +267,67 @@ extern int glthread_cond_timedwait_multithreaded (gl_cond_t *cond, gl_lock_t *lo
 
 #endif
 
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* -------------------------- gl_cond_t datatype -------------------------- */
+
+typedef struct {
+  gl_spinlock_t guard;
+  CRITICAL_SECTION lock;
+
+  int waiters_count;
+  int release_count;
+  int wait_generation_count;
+  HANDLE event;
+} gl_cond_t;
+
+# define gl_cond_define(STORAGECLASS, NAME) \
+    STORAGECLASS gl_cond_t NAME;
+# define gl_cond_define_initialized(STORAGECLASS, NAME) \
+    STORAGECLASS gl_cond_t NAME = gl_cond_initializer;
+# define gl_cond_initializer \
+    { { 0, -1 } }
+# define glthread_cond_init(COND) \
+    glthread_cond_init_func (COND)
+# define glthread_cond_wait(COND, LOCK) \
+    glthread_cond_wait_func (COND, LOCK)
+# define glthread_cond_timedwait(COND, LOCK, ABSTIME) \
+    glthread_cond_timedwait_func (COND, LOCK, ABSTIME)
+# define glthread_cond_signal(COND) \
+    glthread_cond_signal_func (COND)
+# define glthread_cond_broadcast(COND) \
+    glthread_cond_broadcast_func (COND)
+# define glthread_cond_destroy(COND) \
+    glthread_cond_destroy_func (COND)
+
+int glthread_cond_init_func(gl_cond_t *cv);
+int glthread_cond_signal_func(gl_cond_t *cv);
+int glthread_cond_broadcast_func(gl_cond_t *cv);
+int glthread_cond_wait_func(gl_cond_t *cv, gl_lock_t *external_mutex);
+int glthread_cond_timedwait_func(gl_cond_t *cv, gl_lock_t *external_mutex, struct timespec *ts);
+int glthread_cond_destroy_func(gl_cond_t *cv);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
 /* ========================================================================= */
 
-#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS)
+#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_initializer 0
 # define gl_cond_define(STORAGECLASS, NAME)
 # define gl_cond_define_initialized(STORAGECLASS, NAME)
 # define glthread_cond_init(COND) 0
diff --git a/m4/thread.m4 b/m4/thread.m4
index df7ffd0..80bcf27 100644
--- a/m4/thread.m4
+++ b/m4/thread.m4
@@ -10,6 +10,9 @@ AC_DEFUN([gl_THREAD],
   AC_REQUIRE([AC_C_INLINE])
 
   if test $gl_threads_api = posix; then
+    LIBS_bkp=$LIBS
+    LIBS="$LIBS $LIBMULTITHREAD"
     AC_CHECK_FUNCS([pthread_atfork])
+    LIBS=$LIBS_bkp
   fi
 ])
diff --git a/modules/cond b/modules/cond
index c1a62a3..846a4b7 100644
--- a/modules/cond
+++ b/modules/cond
@@ -7,9 +7,12 @@ lib/glthread/cond.c
 m4/cond.m4
 
 Depends-on:
+errno
+time
 threadlib
 lock
 stdbool
+gettimeofday
 
 configure.ac:
 gl_COND
diff --git a/modules/cond-tests b/modules/cond-tests
new file mode 100644
index 0000000..98e0654
--- /dev/null
+++ b/modules/cond-tests
@@ -0,0 +1,13 @@
+Files:
+tests/test-cond.c
+
+Depends-on:
+thread
+yield
+sleep
+gettimeofday
+
+Makefile.am:
+TESTS += test-cond
+check_PROGRAMS += test-cond
+test_cond_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
diff --git a/modules/lock-tests b/modules/lock-tests
index 7c72c94..21e2c98 100644
--- a/modules/lock-tests
+++ b/modules/lock-tests
@@ -2,20 +2,10 @@ 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
 check_PROGRAMS += test-lock
-test_lock_LDADD = $(LDADD) @LIBMULTITHREAD@ @LIBSCHED@
+test_lock_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
diff --git a/modules/tls-tests b/modules/tls-tests
index b9f5a23..dcaad4c 100644
--- a/modules/tls-tests
+++ b/modules/tls-tests
@@ -2,21 +2,11 @@ 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])
+thread
+yield
 
 Makefile.am:
 TESTS += test-tls
 check_PROGRAMS += test-tls
-test_tls_LDADD = $(LDADD) @LIBMULTITHREAD@ @LIBSCHED@
+test_tls_LDADD = $(LDADD) @LIBMULTITHREAD@ @YIELD_LIB@
 
diff --git a/tests/test-cond.c b/tests/test-cond.c
new file mode 100644
index 0000000..b47ac53
--- /dev/null
+++ b/tests/test-cond.c
@@ -0,0 +1,212 @@
+/* Test of locking 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
+
+/* 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>
+#include <sys/time.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() gl_thread_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;
+
+  thread = gl_thread_create(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;
+}
+
+void
+test_timedcond()
+{
+  int remain = 2;
+  gl_thread_t thread;
+
+  cond_value = cond_timeout = 0;
+
+  thread = gl_thread_create(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 5faa8d8..e86bbae 100644
--- a/tests/test-lock.c
+++ b/tests/test-lock.c
@@ -20,19 +20,6 @@
 
 #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.  */
@@ -71,7 +58,9 @@
 # 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,128 +68,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;
-/* Use a wrapper function, instead of adding WINAPI through a cast.  */
-struct wrapper_args { void * (*func) (void *); void *arg; };
-static DWORD WINAPI wrapper_func (void *varg)
-{
-  struct wrapper_args *warg = (struct wrapper_args *)varg;
-  void * (*func) (void *) = warg->func;
-  void *arg = warg->arg;
-  free (warg);
-  func (arg);
-  return 0;
-}
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  struct wrapper_args *warg =
-    (struct wrapper_args *) malloc (sizeof (struct wrapper_args));
-  if (warg == NULL)
-    abort ();
-  warg->func = func;
-  warg->arg = arg;
-  {
-    DWORD thread_id;
-    HANDLE thread =
-      CreateThread (NULL, 100000, wrapper_func, warg, 0, &thread_id);
-    if (thread == NULL)
-      abort ();
-    return thread;
-  }
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  if (WaitForSingleObject (thread, INFINITE) == WAIT_FAILED)
-    abort ();
-  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 ()
 #else
@@ -310,9 +177,9 @@ test_lock (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);
   lock_checker_done = 1;
-  gl_thread_join (checkerthread);
+  gl_thread_join (checkerthread, NULL);
   check_accounts ();
 }
 
@@ -392,10 +259,10 @@ test_rwlock (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);
   rwlock_checker_done = 1;
   for (i = 0; i < THREAD_COUNT; i++)
-    gl_thread_join (checkerthreads[i]);
+    gl_thread_join (checkerthreads[i], NULL);
   check_accounts ();
 }
 
@@ -490,9 +357,9 @@ test_recursive_lock (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);
   reclock_checker_done = 1;
-  gl_thread_join (checkerthread);
+  gl_thread_join (checkerthread, NULL);
   check_accounts ();
 }
 
@@ -639,7 +506,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 b9806bb..715a3e6 100644
--- a/tests/test-tls.c
+++ b/tests/test-tls.c
@@ -50,6 +50,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "glthread/thread.h"
+#include "glthread/yield.h"
 #include "glthread/tls.h"
 
 #if ENABLE_DEBUGGING
@@ -58,128 +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;
-/* Use a wrapper function, instead of adding WINAPI through a cast.  */
-struct wrapper_args { void * (*func) (void *); void *arg; };
-static DWORD WINAPI wrapper_func (void *varg)
-{
-  struct wrapper_args *warg = (struct wrapper_args *)varg;
-  void * (*func) (void *) = warg->func;
-  void *arg = warg->arg;
-  free (warg);
-  func (arg);
-  return 0;
-}
-static inline gl_thread_t gl_thread_create (void * (*func) (void *), void *arg)
-{
-  struct wrapper_args *warg =
-    (struct wrapper_args *) malloc (sizeof (struct wrapper_args));
-  if (warg == NULL)
-    abort ();
-  warg->func = func;
-  warg->arg = arg;
-  {
-    DWORD thread_id;
-    HANDLE thread =
-      CreateThread (NULL, 100000, wrapper_func, warg, 0, &thread_id);
-    if (thread == NULL)
-      abort ();
-    return thread;
-  }
-}
-static inline void gl_thread_join (gl_thread_t thread)
-{
-  if (WaitForSingleObject (thread, INFINITE) == WAIT_FAILED)
-    abort ();
-  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 ()
 #else
@@ -288,7 +168,7 @@ test_tls (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);
 
       for (i = 0; i < KEYS_COUNT; i++)
 	gl_tls_key_destroy (mykeys[i]);

Reply via email to