diff options
| author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-02-09 17:15:47 +0000 |
|---|---|---|
| committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-02-09 17:17:06 +0000 |
| commit | 74159dc58af2ce8a32b62daecd587f29ff7931f2 (patch) | |
| tree | 089ea56ba675c3aed5c9a8f66ec8cc2e3469338f /sysdeps/pthread | |
| parent | 71d52ac4d65435791d8fa9f52abab7107ef7f7e8 (diff) | |
| download | glibc-74159dc58af2ce8a32b62daecd587f29ff7931f2.tar.xz glibc-74159dc58af2ce8a32b62daecd587f29ff7931f2.zip | |
pthread: Move most mutex tests from nptl to sysdeps/pthread
So they can be checked with htl too.
XFAIL tst-mutex4, for which support is still missing in htl.
Diffstat (limited to 'sysdeps/pthread')
| -rw-r--r-- | sysdeps/pthread/Makefile | 3 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex1.c | 83 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex10.c | 109 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex2.c | 241 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex3.c | 241 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex4.c | 276 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex6.c | 76 | ||||
| -rw-r--r-- | sysdeps/pthread/tst-mutex8.c | 435 |
8 files changed, 1463 insertions, 1 deletions
diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index 6b66031706..fb467d8e79 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -44,6 +44,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ tst-basic7 \ - tst-spin1 tst-spin2 tst-spin3 tst-spin4 \ + tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex6 tst-mutex10 \ + tst-spin1 tst-spin2 tst-spin3 tst-spin4 endif diff --git a/sysdeps/pthread/tst-mutex1.c b/sysdeps/pthread/tst-mutex1.c new file mode 100644 index 0000000000..dba1f5fad6 --- /dev/null +++ b/sysdeps/pthread/tst-mutex1.c @@ -0,0 +1,83 @@ +/* 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 <pthread.h> +#include <stdio.h> +#include <errno.h> +#include <stdbool.h> +#include <libc-diag.h> + +#ifndef ATTR +# define ATTR NULL +# define ATTR_NULL true +#endif + + +static int +do_test (void) +{ + pthread_mutex_t m; + + int e = pthread_mutex_init (&m, ATTR); + if (!ATTR_NULL && e == ENOTSUP) + { + puts ("cannot support selected type of mutexes"); + return 0; + } + else if (e != 0) + { + puts ("mutex_init failed"); + return 1; + } + + /* This deliberately tests supplying a null pointer to a function whose + argument is marked __attribute__ ((nonnull)). */ + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (5, "-Wnonnull"); + if (!ATTR_NULL && pthread_mutexattr_destroy (ATTR) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + DIAG_POP_NEEDS_COMMENT; + + if (pthread_mutex_lock (&m) != 0) + { + puts ("mutex_lock failed"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("mutex_unlock failed"); + return 1; + } + + if (pthread_mutex_destroy (&m) != 0) + { + puts ("mutex_destroy failed"); + return 1; + } + + return 0; +} + +#ifndef TEST_FUNCTION +# define TEST_FUNCTION do_test () +#endif +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-mutex10.c b/sysdeps/pthread/tst-mutex10.c new file mode 100644 index 0000000000..646ef13bb3 --- /dev/null +++ b/sysdeps/pthread/tst-mutex10.c @@ -0,0 +1,109 @@ +/* Testing race while enabling lock elision. + Copyright (C) 2018-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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <pthread.h> +#include <unistd.h> +#include <getopt.h> +#include <support/support.h> +#include <support/xthread.h> + +static pthread_barrier_t barrier; +static pthread_mutex_t mutex; +static long long int iteration_count = 1000000; +static unsigned int thread_count = 3; + +static void * +thr_func (void *arg) +{ + long long int i; + for (i = 0; i < iteration_count; i++) + { + if ((uintptr_t) arg == 0) + { + xpthread_mutex_destroy (&mutex); + xpthread_mutex_init (&mutex, NULL); + } + + xpthread_barrier_wait (&barrier); + + /* Test if enabling lock elision works if it is enabled concurrently. + There was a race in FORCE_ELISION macro which leads to either + pthread_mutex_destroy returning EBUSY as the owner was recorded + by pthread_mutex_lock - in "normal mutex" code path - but was not + resetted in pthread_mutex_unlock - in "elision" code path. + Or it leads to the assertion in nptl/pthread_mutex_lock.c: + assert (mutex->__data.__owner == 0); + Please ensure that the test is run with lock elision: + export GLIBC_TUNABLES=glibc.elision.enable=1 */ + xpthread_mutex_lock (&mutex); + xpthread_mutex_unlock (&mutex); + + xpthread_barrier_wait (&barrier); + } + return NULL; +} + +static int +do_test (void) +{ + unsigned int i; + printf ("Starting %d threads to run %lld iterations.\n", + thread_count, iteration_count); + + pthread_t *threads = xmalloc (thread_count * sizeof (pthread_t)); + xpthread_barrier_init (&barrier, NULL, thread_count); + xpthread_mutex_init (&mutex, NULL); + + for (i = 0; i < thread_count; i++) + threads[i] = xpthread_create (NULL, thr_func, (void *) (uintptr_t) i); + + for (i = 0; i < thread_count; i++) + xpthread_join (threads[i]); + + xpthread_barrier_destroy (&barrier); + free (threads); + + return EXIT_SUCCESS; +} + +#define OPT_ITERATIONS 10000 +#define OPT_THREADS 10001 +#define CMDLINE_OPTIONS \ + { "iterations", required_argument, NULL, OPT_ITERATIONS }, \ + { "threads", required_argument, NULL, OPT_THREADS }, +static void +cmdline_process (int c) +{ + long long int arg = strtoll (optarg, NULL, 0); + switch (c) + { + case OPT_ITERATIONS: + if (arg > 0) + iteration_count = arg; + break; + case OPT_THREADS: + if (arg > 0 && arg < 100) + thread_count = arg; + break; + } +} +#define CMDLINE_PROCESS cmdline_process +#define TIMEOUT 50 +#include <support/test-driver.c> diff --git a/sysdeps/pthread/tst-mutex2.c b/sysdeps/pthread/tst-mutex2.c new file mode 100644 index 0000000000..10a586f8ee --- /dev/null +++ b/sysdeps/pthread/tst-mutex2.c @@ -0,0 +1,241 @@ +/* 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 <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + + +static pthread_mutex_t m; +static pthread_barrier_t b; + + +static void * +tf (void *arg) +{ + int e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("child: 1st mutex_unlock succeeded"); + exit (1); + } + else if (e != EPERM) + { + puts ("child: 1st mutex_unlock error != EPERM"); + exit (1); + } + + e = pthread_mutex_trylock (&m); + if (e == 0) + { + puts ("child: 1st trylock suceeded"); + exit (1); + } + if (e != EBUSY) + { + puts ("child: 1st trylock didn't return EBUSY"); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child: 1st barrier_wait failed"); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("child: 2nd barrier_wait failed"); + exit (1); + } + + e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("child: 2nd mutex_unlock succeeded"); + exit (1); + } + else if (e != EPERM) + { + puts ("child: 2nd mutex_unlock error != EPERM"); + exit (1); + } + + if (pthread_mutex_trylock (&m) != 0) + { + puts ("child: 2nd trylock failed"); + exit (1); + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("child: 3rd mutex_unlock failed"); + exit (1); + } + + return NULL; +} + + +static int +do_test (void) +{ + pthread_mutexattr_t a; + int e; + + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + return 1; + } + + if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_ERRORCHECK) != 0) + { + puts ("mutexattr_settype failed"); + return 1; + } + +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + e = pthread_mutex_init (&m, &a); + if (e != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif + puts ("mutex_init failed"); + return 1; + } + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } + + e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("1st mutex_unlock succeeded"); + return 1; + } + else if (e != EPERM) + { + puts ("1st mutex_unlock error != EPERM"); + return 1; + } + + if (pthread_mutex_lock (&m) != 0) + { + puts ("mutex_lock failed"); + return 1; + } + + e = pthread_mutex_lock (&m); + if (e == 0) + { + puts ("2nd mutex_lock succeeded"); + return 1; + } + else if (e != EDEADLK) + { + puts ("2nd mutex_lock error != EDEADLK"); + return 1; + } + + pthread_t th; + if (pthread_create (&th, NULL, tf, NULL) != 0) + { + puts ("create failed"); + return 1; + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("1st barrier_wait failed"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("2nd mutex_unlock failed"); + return 1; + } + + e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("3rd mutex_unlock succeeded"); + return 1; + } + else if (e != EPERM) + { + puts ("3rd mutex_unlock error != EPERM"); + return 1; + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("2nd barrier_wait failed"); + return 1; + } + + if (pthread_join (th, NULL) != 0) + { + puts ("join failed"); + return 1; + } + + if (pthread_mutex_destroy (&m) != 0) + { + puts ("mutex_destroy failed"); + return 1; + } + + if (pthread_barrier_destroy (&b) != 0) + { + puts ("barrier_destroy failed"); + return 1; + } + + if (pthread_mutexattr_destroy (&a) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-mutex3.c b/sysdeps/pthread/tst-mutex3.c new file mode 100644 index 0000000000..d18ebb2f10 --- /dev/null +++ b/sysdeps/pthread/tst-mutex3.c @@ -0,0 +1,241 @@ +/* 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 <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> + + +static pthread_mutex_t m; +static pthread_barrier_t b; + + +static void * +tf (void *arg) +{ + int e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("1st mutex_unlock in child succeeded"); + exit (1); + } + if (e != EPERM) + { + puts ("1st mutex_unlock in child didn't return EPERM"); + exit (1); + } + + e = pthread_mutex_trylock (&m); + if (e == 0) + { + puts ("mutex_trylock in second thread succeeded"); + exit (1); + } + if (e != EBUSY) + { + puts ("mutex_trylock returned wrong value"); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + exit (1); + } + + e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("2nd mutex_unlock in child succeeded"); + exit (1); + } + if (e != EPERM) + { + puts ("2nd mutex_unlock in child didn't return EPERM"); + exit (1); + } + + if (pthread_mutex_trylock (&m) != 0) + { + puts ("2nd mutex_trylock in second thread failed"); + exit (1); + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("3rd mutex_unlock in second thread failed"); + exit (1); + } + + return NULL; +} + + +static int +do_test (void) +{ + pthread_mutexattr_t a; + + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + return 1; + } + + if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0) + { + puts ("mutexattr_settype failed"); + return 1; + } + +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + int e; + e = pthread_mutex_init (&m, &a); + if (e != 0) + { +#ifdef ENABLE_PI + if (e == ENOTSUP) + { + puts ("PI mutexes unsupported"); + return 0; + } +#endif + puts ("mutex_init failed"); + return 1; + } + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } + + if (pthread_mutex_lock (&m) != 0) + { + puts ("mutex_lock failed"); + return 1; + } + + if (pthread_mutex_lock (&m) != 0) + { + puts ("2nd mutex_lock failed"); + return 1; + } + + if (pthread_mutex_trylock (&m) != 0) + { + puts ("1st trylock failed"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("mutex_unlock failed"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("2nd mutex_unlock failed"); + return 1; + } + + pthread_t th; + if (pthread_create (&th, NULL, tf, NULL) != 0) + { + puts ("create failed"); + return 1; + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("3rd mutex_unlock failed"); + return 1; + } + + e = pthread_mutex_unlock (&m); + if (e == 0) + { + puts ("4th mutex_unlock succeeded"); + return 1; + } + if (e != EPERM) + { + puts ("4th mutex_unlock didn't return EPERM"); + return 1; + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + puts ("barrier_wait failed"); + return 1; + } + + if (pthread_join (th, NULL) != 0) + { + puts ("join failed"); + return 1; + } + + if (pthread_barrier_destroy (&b) != 0) + { + puts ("barrier_destroy failed"); + return 1; + } + + if (pthread_mutex_destroy (&m) != 0) + { + puts ("mutex_destroy failed"); + return 1; + } + + if (pthread_mutexattr_destroy (&a) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-mutex4.c b/sysdeps/pthread/tst-mutex4.c new file mode 100644 index 0000000000..8ac6666fa0 --- /dev/null +++ b/sysdeps/pthread/tst-mutex4.c @@ -0,0 +1,276 @@ +/* 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 <errno.h> +#include <pthread.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/wait.h> + + +static int +do_test (void) +{ + size_t ps = sysconf (_SC_PAGESIZE); + char tmpfname[] = "/tmp/tst-mutex4.XXXXXX"; + c |
