diff options
| author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-02-09 19:17:51 +0000 |
|---|---|---|
| committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-02-09 19:24:44 +0000 |
| commit | d8f1f2d9ab2144b589fdac3e381cd86e71871e43 (patch) | |
| tree | 586832da5c77a4635006cfecb4515e23956ddaa6 /sysdeps/pthread | |
| parent | faae4b2bdd692d929037c80c3315f716f02f3b00 (diff) | |
| download | glibc-d8f1f2d9ab2144b589fdac3e381cd86e71871e43.tar.xz glibc-d8f1f2d9ab2144b589fdac3e381cd86e71871e43.zip | |
pthread: Move most cond tests from nptl to sysdeps/pthread
So they can be checked with htl too.
Diffstat (limited to 'sysdeps/pthread')
29 files changed, 3778 insertions, 0 deletions
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index 5117110210..2c33c5c904 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -45,7 +45,17 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ tst-attr1 \ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ tst-basic7 \ + tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \ + tst-cond8 tst-cond9 tst-cond10 tst-cond12 tst-cond13 \ + tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ + tst-cond23 tst-cond24 tst-cond25 \ + tst-cond-except \ tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex6 tst-mutex10 \ tst-spin1 tst-spin2 tst-spin3 tst-spin4 +ifeq ($(build-shared),yes) +tests-static += tst-cond8-static +tests += tst-cond8-static +endif + endif diff --git a/sysdeps/pthread/tst-cond-except.c b/sysdeps/pthread/tst-cond-except.c new file mode 100644 index 0000000000..8526e241e6 --- /dev/null +++ b/sysdeps/pthread/tst-cond-except.c @@ -0,0 +1,109 @@ +/* Verify that exception table for pthread_cond_wait is correct. + Copyright (C) 2012-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <pthread.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +pthread_mutex_t mutex; +pthread_cond_t cond; + +#define CHECK_RETURN_VAL_OR_FAIL(ret,str) \ + ({ if ((ret) != 0) \ + { \ + printf ("%s failed: %s\n", (str), strerror (ret)); \ + ret = 1; \ + goto out; \ + } \ + }) + + +void +clean (void *arg) +{ + puts ("clean: Unlocking mutex..."); + pthread_mutex_unlock ((pthread_mutex_t *) arg); + puts ("clean: Mutex unlocked..."); +} + +void * +thr (void *arg) +{ + int ret = 0; + pthread_mutexattr_t mutexAttr; + ret = pthread_mutexattr_init (&mutexAttr); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_init"); + + ret = pthread_mutexattr_setprotocol (&mutexAttr, PTHREAD_PRIO_INHERIT); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutexattr_setprotocol"); + + ret = pthread_mutex_init (&mutex, &mutexAttr); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_init"); + + ret = pthread_cond_init (&cond, 0); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_init"); + + puts ("th: Init done, entering wait..."); + + pthread_cleanup_push (clean, (void *) &mutex); + ret = pthread_mutex_lock (&mutex); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_mutex_lock"); + while (1) + { + ret = pthread_cond_wait (&cond, &mutex); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cond_wait"); + } + pthread_cleanup_pop (1); + +out: + return (void *) (uintptr_t) ret; +} + +int +do_test (void) +{ + pthread_t thread; + int ret = 0; + void *thr_ret = 0; + ret = pthread_create (&thread, 0, thr, &thr_ret); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_create"); + + puts ("main: Thread created, waiting a bit..."); + sleep (2); + + puts ("main: Cancelling thread..."); + ret = pthread_cancel (thread); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_cancel"); + + puts ("main: Joining th..."); + ret = pthread_join (thread, NULL); + CHECK_RETURN_VAL_OR_FAIL (ret, "pthread_join"); + + if (thr_ret != NULL) + return 1; + + puts ("main: Joined thread, done!"); + +out: + return ret; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-cond1.c b/sysdeps/pthread/tst-cond1.c new file mode 100644 index 0000000000..47c68d443b --- /dev/null +++ b/sysdeps/pthread/tst-cond1.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <error.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + + +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; + + +static void * +tf (void *p) +{ + int err; + + err = pthread_mutex_lock (&mut); + if (err != 0) + error (EXIT_FAILURE, err, "child: cannot get mutex"); + + puts ("child: got mutex; signalling"); + + pthread_cond_signal (&cond); + + puts ("child: unlock"); + + err = pthread_mutex_unlock (&mut); + if (err != 0) + error (EXIT_FAILURE, err, "child: cannot unlock"); + + puts ("child: done"); + + return NULL; +} + + +static int +do_test (void) +{ + pthread_t th; + int err; + + printf ("&cond = %p\n&mut = %p\n", &cond, &mut); + + puts ("parent: get mutex"); + + err = pthread_mutex_lock (&mut); + if (err != 0) + error (EXIT_FAILURE, err, "parent: cannot get mutex"); + + puts ("parent: create child"); + + err = pthread_create (&th, NULL, tf, NULL); + if (err != 0) + error (EXIT_FAILURE, err, "parent: cannot create thread"); + + puts ("parent: wait for condition"); + + /* This test will fail on spurious wake-ups, which are allowed; however, + the current implementation shouldn't produce spurious wake-ups in the + scenario we are testing here. */ + err = pthread_cond_wait (&cond, &mut); + if (err != 0) + error (EXIT_FAILURE, err, "parent: cannot wait fir signal"); + + puts ("parent: got signal"); + + err = pthread_join (th, NULL); + if (err != 0) + error (EXIT_FAILURE, err, "parent: failed to join"); + + puts ("done"); + + return 0; +} + + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-cond10.c b/sysdeps/pthread/tst-cond10.c new file mode 100644 index 0000000000..b89c452467 --- /dev/null +++ b/sysdeps/pthread/tst-cond10.c @@ -0,0 +1,172 @@ +/* Copyright (C) 2003-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <error.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + + +#define N 10 +#define ROUNDS 100 + +static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +static pthread_barrier_t bN1; +static pthread_barrier_t b2; + + +static void * +tf (void *p) +{ + if (pthread_mutex_lock (&mut) != 0) + { + puts ("child: 1st mutex_lock failed"); + exit (1); + } + + int e = pthread_barrier_wait (&b2); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child: 1st barrier_wait failed"); + exit (1); + } + + if (pthread_cond_wait (&cond, &mut) != 0) + { + puts ("child: cond_wait failed"); + exit (1); + } + + if (pthread_mutex_unlock (&mut) != 0) + { + puts ("child: mutex_unlock failed"); + exit (1); + } + + e = pthread_barrier_wait (&bN1); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child: 2nd barrier_wait failed"); + exit (1); + } + + return NULL; +} + + +static int +do_test (void) +{ + if (pthread_barrier_init (&bN1, NULL, N + 1) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + if (pthread_barrier_init (&b2, NULL, 2) != 0) + { + puts ("barrier_init failed"); + exit (1); + } + + pthread_attr_t at; + + if (pthread_attr_init (&at) != 0) + { + puts ("attr_init failed"); + return 1; + } + + if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0) + { + puts ("attr_setstacksize failed"); + return 1; + } + + int r; + for (r = 0; r < ROUNDS; ++r) + { + printf ("round %d\n", r + 1); + + int i; + pthread_t th[N]; + for (i = 0; i < N; ++i) + { + if (pthread_create (&th[i], &at, tf, NULL) != 0) + { + puts ("create failed"); + exit (1); + } + + int e = pthread_barrier_wait (&b2); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("parent: 1st barrier_wait failed"); + exit (1); + } + } + + if (pthread_mutex_lock (&mut) != 0) + { + puts ("parent: mutex_lock failed"); + exit (1); + } + if (pthread_mutex_unlock (&mut) != 0) + { + puts ("parent: mutex_unlock failed"); + exit (1); + } + + /* N single signal calls. Without locking. This tests that no + signal gets lost. */ + for (i = 0; i < N; ++i) + if (pthread_cond_signal (&cond) != 0) + { + puts ("cond_signal failed"); + exit (1); + } + + int e = pthread_barrier_wait (&bN1); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("parent: 2nd barrier_wait failed"); + exit (1); + } + + for (i = 0; i < N; ++i) + if (pthread_join (th[i], NULL) != 0) + { + puts ("join failed"); + exit (1); + } + } + + if (pthread_attr_destroy (&at) != 0) + { + puts ("attr_destroy failed"); + return 1; + } + + return 0; +} + + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-cond11-static.c b/sysdeps/pthread/tst-cond11-static.c new file mode 100644 index 0000000000..9bccb8ec8b --- /dev/null +++ b/sysdeps/pthread/tst-cond11-static.c @@ -0,0 +1 @@ +#include "tst-cond11.c" diff --git a/sysdeps/pthread/tst-cond11.c b/sysdeps/pthread/tst-cond11.c new file mode 100644 index 0000000000..209e2f0c8d --- /dev/null +++ b/sysdeps/pthread/tst-cond11.c @@ -0,0 +1,122 @@ +/* Copyright (C) 2003-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <time.h> +#include <unistd.h> +#include <support/check.h> +#include <support/test-driver.h> +#include <support/timespec.h> +#include <support/xthread.h> +#include <support/xtime.h> + +/* A bogus clock value that tells run_test to use pthread_cond_timedwait + rather than pthread_condclockwait. */ +#define CLOCK_USE_ATTR_CLOCK (-1) + +#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0 +static int +run_test (clockid_t attr_clock, clockid_t wait_clock) +{ + pthread_condattr_t condattr; + pthread_cond_t cond; + pthread_mutexattr_t mutattr; + pthread_mutex_t mut; + + verbose_printf ("attr_clock = %d\n", (int) attr_clock); + + TEST_COMPARE (pthread_condattr_init (&condattr), 0); + TEST_COMPARE (pthread_condattr_setclock (&condattr, attr_clock), 0); + + clockid_t attr_clock_read; + TEST_COMPARE (pthread_condattr_getclock (&condattr, &attr_clock_read), 0); + TEST_COMPARE (attr_clock, attr_clock_read); + + TEST_COMPARE (pthread_cond_init (&cond, &condattr), 0); + TEST_COMPARE (pthread_condattr_destroy (&condattr), 0); + + xpthread_mutexattr_init (&mutattr); + xpthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK); + xpthread_mutex_init (&mut, &mutattr); + xpthread_mutexattr_destroy (&mutattr); + + xpthread_mutex_lock (&mut); + TEST_COMPARE (pthread_mutex_lock (&mut), EDEADLK); + + struct timespec ts_timeout; + xclock_gettime (wait_clock == CLOCK_USE_ATTR_CLOCK ? attr_clock : wait_clock, + &ts_timeout); + + /* Wait one second. */ + ++ts_timeout.tv_sec; + + if (wait_clock == CLOCK_USE_ATTR_CLOCK) { + TEST_COMPARE (pthread_cond_timedwait (&cond, &mut, &ts_timeout), ETIMEDOUT); + TEST_TIMESPEC_BEFORE_NOW (ts_timeout, attr_clock); + } else { + TEST_COMPARE (pthread_cond_clockwait (&cond, &mut, wait_clock, &ts_timeout), + ETIMEDOUT); + TEST_TIMESPEC_BEFORE_NOW (ts_timeout, wait_clock); + } + + xpthread_mutex_unlock (&mut); + xpthread_mutex_destroy (&mut); + TEST_COMPARE (pthread_cond_destroy (&cond), 0); + + return 0; +} +#endif + + +static int +do_test (void) +{ +#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1 + + FAIL_UNSUPPORTED ("_POSIX_CLOCK_SELECTION not supported, test skipped"); + +#else + + run_test (CLOCK_REALTIME, CLOCK_USE_ATTR_CLOCK); + +# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0 +# if _POSIX_MONOTONIC_CLOCK == |
