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-tests b/modules/cond-tests
new file mode 100644
index 0000000..d262d9e
--- /dev/null
+++ b/modules/cond-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-cond.c
+
+Depends-on:
+thread
+yield
+
+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..ac77158
--- /dev/null
+++ b/tests/test-cond.c
@@ -0,0 +1,211 @@
+/* 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 . */
+
+#include
+
+#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
+#include
+#include
+
+#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
+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
-# include
-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
-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
-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
-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
#include
+#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
-# include
-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
-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
-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
-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]);