mirror of
https://https.git.savannah.gnu.org/git/gnulib.git
synced 2026-09-01 02:34:55 +00:00
cnd: Add tests.
* tests/test-cnd.c: New file, based on tests/test-cond.c. * modules/cnd-tests: New file.
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
2019-06-20 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
cnd: Add tests.
|
||||
* tests/test-cnd.c: New file, based on tests/test-cond.c.
|
||||
* modules/cnd-tests: New file.
|
||||
|
||||
2019-06-20 Bruno Haible <bruno@clisp.org>
|
||||
|
||||
mtx: Add tests.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
Files:
|
||||
tests/test-cnd.c
|
||||
tests/macros.h
|
||||
|
||||
Depends-on:
|
||||
mtx
|
||||
thrd
|
||||
gettimeofday
|
||||
|
||||
configure.ac:
|
||||
AC_CHECK_DECLS_ONCE([alarm])
|
||||
|
||||
Makefile.am:
|
||||
TESTS += test-cnd
|
||||
check_PROGRAMS += test-cnd
|
||||
test_cnd_LDADD = $(LDADD) @LIBSTDTHREAD@
|
||||
@@ -0,0 +1,209 @@
|
||||
/* Test of condition variables in multithreaded situations.
|
||||
Copyright (C) 2008-2019 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 <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* 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 <threads.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#if HAVE_DECL_ALARM
|
||||
# include <signal.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
#if ENABLE_DEBUGGING
|
||||
# define dbgprintf printf
|
||||
#else
|
||||
# define dbgprintf if (0) printf
|
||||
#endif
|
||||
|
||||
#if EXPLICIT_YIELD
|
||||
# define yield() thrd_yield ()
|
||||
#else
|
||||
# define yield()
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Condition check
|
||||
*/
|
||||
static int cond_value = 0;
|
||||
static cnd_t condtest;
|
||||
static mtx_t lockcond;
|
||||
|
||||
static int
|
||||
cnd_wait_routine (void *arg)
|
||||
{
|
||||
ASSERT (mtx_lock (&lockcond) == thrd_success);
|
||||
while (!cond_value)
|
||||
{
|
||||
ASSERT (cnd_wait (&condtest, &lockcond) == thrd_success);
|
||||
}
|
||||
ASSERT (mtx_unlock (&lockcond) == thrd_success);
|
||||
|
||||
cond_value = 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
test_cnd_wait ()
|
||||
{
|
||||
struct timespec remain;
|
||||
thrd_t thread;
|
||||
int ret;
|
||||
|
||||
remain.tv_sec = 2;
|
||||
remain.tv_nsec = 0;
|
||||
|
||||
cond_value = 0;
|
||||
|
||||
ASSERT (thrd_create (&thread, cnd_wait_routine, NULL) == thrd_success);
|
||||
do
|
||||
{
|
||||
yield ();
|
||||
ret = thrd_sleep (&remain, &remain);
|
||||
ASSERT (ret >= -1);
|
||||
}
|
||||
while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
|
||||
|
||||
/* signal condition */
|
||||
ASSERT (mtx_lock (&lockcond) == thrd_success);
|
||||
cond_value = 1;
|
||||
ASSERT (cnd_signal (&condtest) == thrd_success);
|
||||
ASSERT (mtx_unlock (&lockcond) == thrd_success);
|
||||
|
||||
ASSERT (thrd_join (thread, NULL) == thrd_success);
|
||||
|
||||
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 int
|
||||
cnd_timedwait_routine (void *arg)
|
||||
{
|
||||
int ret;
|
||||
struct timespec ts;
|
||||
|
||||
ASSERT (mtx_lock (&lockcond) == thrd_success);
|
||||
while (!cond_value)
|
||||
{
|
||||
get_ts (&ts);
|
||||
ret = cnd_timedwait (&condtest, &lockcond, &ts);
|
||||
if (ret == thrd_timedout)
|
||||
cond_timeout = 1;
|
||||
}
|
||||
ASSERT (mtx_unlock (&lockcond) == thrd_success);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_cnd_timedwait (void)
|
||||
{
|
||||
struct timespec remain;
|
||||
thrd_t thread;
|
||||
int ret;
|
||||
|
||||
remain.tv_sec = 2;
|
||||
remain.tv_nsec = 0;
|
||||
|
||||
cond_value = cond_timeout = 0;
|
||||
|
||||
ASSERT (thrd_create (&thread, cnd_timedwait_routine, NULL) == thrd_success);
|
||||
do
|
||||
{
|
||||
yield ();
|
||||
ret = thrd_sleep (&remain, &remain);
|
||||
ASSERT (ret >= -1);
|
||||
}
|
||||
while (ret == -1 && (remain.tv_sec != 0 || remain.tv_nsec != 0));
|
||||
|
||||
/* signal condition */
|
||||
ASSERT (mtx_lock (&lockcond) == thrd_success);
|
||||
cond_value = 1;
|
||||
ASSERT (cnd_signal (&condtest) == thrd_success);
|
||||
ASSERT (mtx_unlock (&lockcond) == thrd_success);
|
||||
|
||||
ASSERT (thrd_join (thread, NULL) == thrd_success);
|
||||
|
||||
if (!cond_timeout)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
#if HAVE_DECL_ALARM
|
||||
/* Declare failure if test takes too long, by using default abort
|
||||
caused by SIGALRM. */
|
||||
int alarm_value = 600;
|
||||
signal (SIGALRM, SIG_DFL);
|
||||
alarm (alarm_value);
|
||||
#endif
|
||||
|
||||
ASSERT (cnd_init (&condtest) == thrd_success);
|
||||
ASSERT (mtx_init (&lockcond, mtx_plain) == thrd_success);
|
||||
|
||||
#if DO_TEST_COND
|
||||
printf ("Starting test_cnd_wait ..."); fflush (stdout);
|
||||
test_cnd_wait ();
|
||||
printf (" OK\n"); fflush (stdout);
|
||||
#endif
|
||||
#if DO_TEST_TIMEDCOND
|
||||
printf ("Starting test_cnd_timedwait ..."); fflush (stdout);
|
||||
test_cnd_timedwait ();
|
||||
printf (" OK\n"); fflush (stdout);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user