From a25077a431758b30aa60103945fe70811e8207ef Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sun, 16 Feb 2020 14:30:17 +0000 Subject: pthread: Move robust mutex tests from nptl to sysdeps/pthread tst-robust8.c prints some mutex internals for nptl debugging, this needed to be made conditioned by getting built with nptl. --- nptl/Makefile | 4 +- nptl/pthreadP.h | 2 + nptl/tst-robust1.c | 338 ---------------------------------------- nptl/tst-robust10.c | 110 ------------- nptl/tst-robust2.c | 3 - nptl/tst-robust3.c | 20 --- nptl/tst-robust4.c | 2 - nptl/tst-robust5.c | 2 - nptl/tst-robust6.c | 2 - nptl/tst-robust7.c | 212 ------------------------- nptl/tst-robust8.c | 274 -------------------------------- nptl/tst-robust9.c | 93 ----------- sysdeps/htl/pthreadP.h | 2 + sysdeps/mach/hurd/i386/Makefile | 16 +- sysdeps/pthread/Makefile | 2 + sysdeps/pthread/tst-robust1.c | 338 ++++++++++++++++++++++++++++++++++++++++ sysdeps/pthread/tst-robust10.c | 110 +++++++++++++ sysdeps/pthread/tst-robust2.c | 3 + sysdeps/pthread/tst-robust3.c | 20 +++ sysdeps/pthread/tst-robust4.c | 2 + sysdeps/pthread/tst-robust5.c | 2 + sysdeps/pthread/tst-robust6.c | 2 + sysdeps/pthread/tst-robust7.c | 212 +++++++++++++++++++++++++ sysdeps/pthread/tst-robust8.c | 277 ++++++++++++++++++++++++++++++++ sysdeps/pthread/tst-robust9.c | 93 +++++++++++ 25 files changed, 1077 insertions(+), 1064 deletions(-) delete mode 100644 nptl/tst-robust1.c delete mode 100644 nptl/tst-robust10.c delete mode 100644 nptl/tst-robust2.c delete mode 100644 nptl/tst-robust3.c delete mode 100644 nptl/tst-robust4.c delete mode 100644 nptl/tst-robust5.c delete mode 100644 nptl/tst-robust6.c delete mode 100644 nptl/tst-robust7.c delete mode 100644 nptl/tst-robust8.c delete mode 100644 nptl/tst-robust9.c create mode 100644 sysdeps/pthread/tst-robust1.c create mode 100644 sysdeps/pthread/tst-robust10.c create mode 100644 sysdeps/pthread/tst-robust2.c create mode 100644 sysdeps/pthread/tst-robust3.c create mode 100644 sysdeps/pthread/tst-robust4.c create mode 100644 sysdeps/pthread/tst-robust5.c create mode 100644 sysdeps/pthread/tst-robust6.c create mode 100644 sysdeps/pthread/tst-robust7.c create mode 100644 sysdeps/pthread/tst-robust8.c create mode 100644 sysdeps/pthread/tst-robust9.c diff --git a/nptl/Makefile b/nptl/Makefile index fcdc72adfe..b25d34bd71 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -240,8 +240,6 @@ tests = tst-attr2 tst-attr3 tst-default-attr \ tst-mutexpi5 tst-mutexpi5a tst-mutexpi6 tst-mutexpi7 tst-mutexpi7a \ tst-mutexpi9 \ tst-cond11 tst-cond20 tst-cond21 tst-cond22 tst-cond26 tst-cond27 \ - tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ - tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ tst-robustpi6 tst-robustpi7 tst-robustpi8 tst-robustpi9 \ tst-rwlock2 tst-rwlock2a tst-rwlock2b tst-rwlock3 \ @@ -297,7 +295,7 @@ tests = tst-attr2 tst-attr3 tst-default-attr \ tst-initializers1 $(addprefix tst-initializers1-,\ c89 gnu89 c99 gnu99 c11 gnu11) \ tst-bad-schedattr \ - tst-thread_local1 tst-mutex-errorcheck tst-robust10 \ + tst-thread_local1 tst-mutex-errorcheck \ tst-robust-fork tst-create-detached tst-memstream \ tst-thread-exit-clobber tst-minstack-cancel tst-minstack-exit \ tst-minstack-throw \ diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index 7e0ab8ef42..df4b1a0cda 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -19,6 +19,8 @@ #ifndef _PTHREADP_H #define _PTHREADP_H 1 +#define __PTHREAD_NPTL + #include #include #include diff --git a/nptl/tst-robust1.c b/nptl/tst-robust1.c deleted file mode 100644 index fc21b4f52c..0000000000 --- a/nptl/tst-robust1.c +++ /dev/null @@ -1,338 +0,0 @@ -/* Copyright (C) 2005-2020 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2005. - - 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 - . */ - -#include -#include -#include -#include - - -static pthread_mutex_t m1; -static pthread_mutex_t m2; -static pthread_barrier_t b; - - -#ifndef LOCK -# define LOCK(m) pthread_mutex_lock (m) -#endif - - -static void * -tf (void *arg) -{ - long int round = (long int) arg; - - if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0) - { - printf ("%ld: setcancelstate failed\n", round); - exit (1); - } - - int e = LOCK (&m1); - if (e != 0) - { - printf ("%ld: child: mutex_lock m1 failed with error %d\n", round, e); - exit (1); - } - - e = LOCK (&m2); - if (e != 0) - { - printf ("%ld: child: mutex_lock m2 failed with error %d\n", round, e); - exit (1); - } - - e = pthread_barrier_wait (&b); - if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf ("%ld: child: 1st barrier_wait failed\n", round); - exit (1); - } - - e = pthread_barrier_wait (&b); - if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf ("%ld: child: 2nd barrier_wait failed\n", round); - exit (1); - } - - pthread_testcancel (); - - printf ("%ld: testcancel returned\n", round); - exit (1); -} - - -static int -do_test (void) -{ -#ifdef PREPARE_TMO - PREPARE_TMO; -#endif - - pthread_mutexattr_t a; - if (pthread_mutexattr_init (&a) != 0) - { - puts ("mutexattr_init failed"); - return 1; - } - if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0) - { - puts ("mutexattr_setrobust failed"); - return 1; - } - -#ifdef ENABLE_PI - if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) - { - puts ("pthread_mutexattr_setprotocol failed"); - return 1; - } - else - { - int e = pthread_mutex_init (&m1, &a); - if (e == ENOTSUP) - { - puts ("PI robust mutexes not supported"); - return 0; - } - else if (e != 0) - { - puts ("mutex_init m1 failed"); - return 1; - } - pthread_mutex_destroy (&m1); - } -#endif - -#ifndef NOT_CONSISTENT - if (pthread_mutex_init (&m1, &a) != 0) - { - puts ("mutex_init m1 failed"); - return 1; - } - - if (pthread_mutex_init (&m2, &a) != 0) - { - puts ("mutex_init m2 failed"); - return 1; - } -#endif - - if (pthread_barrier_init (&b, NULL, 2) != 0) - { - puts ("barrier_init failed"); - return 1; - } - - for (long int round = 1; round < 5; ++round) - { -#ifdef NOT_CONSISTENT - if (pthread_mutex_init (&m1 , &a) != 0) - { - puts ("mutex_init m1 failed"); - return 1; - } - if (pthread_mutex_init (&m2 , &a) != 0) - { - puts ("mutex_init m2 failed"); - return 1; - } -#endif - - pthread_t th; - if (pthread_create (&th, NULL, tf, (void *) round) != 0) - { - printf ("%ld: create failed\n", round); - return 1; - } - - int e = pthread_barrier_wait (&b); - if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf ("%ld: parent: 1st barrier_wait failed\n", round); - return 1; - } - - if (pthread_cancel (th) != 0) - { - printf ("%ld: cancel failed\n", round); - return 1; - } - - e = pthread_barrier_wait (&b); - if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf ("%ld: parent: 2nd barrier_wait failed\n", round); - return 1; - } - -#ifndef AFTER_JOIN - if (round & 1) -#endif - { - void *res; - if (pthread_join (th, &res) != 0) - { - printf ("%ld: join failed\n", round); - return 1; - } - if (res != PTHREAD_CANCELED) - { - printf ("%ld: thread not canceled\n", round); - return 1; - } - } - - e = LOCK (&m1); - if (e == 0) - { - printf ("%ld: parent: mutex_lock m1 succeeded\n", round); - return 1; - } - if (e != EOWNERDEAD) - { - printf ("%ld: parent: mutex_lock m1 returned wrong code\n", round); - return 1; - } - - e = LOCK (&m2); - if (e == 0) - { - printf ("%ld: parent: mutex_lock m2 succeeded\n", round); - return 1; - } - if (e != EOWNERDEAD) - { - printf ("%ld: parent: mutex_lock m2 returned wrong code\n", round); - return 1; - } - -#ifndef AFTER_JOIN - if ((round & 1) == 0) - { - void *res; - if (pthread_join (th, &res) != 0) - { - printf ("%ld: join failed\n", round); - return 1; - } - if (res != PTHREAD_CANCELED) - { - printf ("%ld: thread not canceled\n", round); - return 1; - } - } -#endif - -#ifndef NOT_CONSISTENT - e = pthread_mutex_consistent_np (&m1); - if (e != 0) - { - printf ("%ld: mutex_consistent m1 failed with error %d\n", round, e); - return 1; - } - - e = pthread_mutex_consistent_np (&m2); - if (e != 0) - { - printf ("%ld: mutex_consistent m2 failed with error %d\n", round, e); - return 1; - } -#endif - - e = pthread_mutex_unlock (&m1); - if (e != 0) - { - printf ("%ld: mutex_unlock m1 failed with %d\n", round, e); - return 1; - } - - e = pthread_mutex_unlock (&m2); - if (e != 0) - { - printf ("%ld: mutex_unlock m2 failed with %d\n", round, e); - return 1; - } - -#ifdef NOT_CONSISTENT - e = LOCK (&m1); - if (e == 0) - { - printf ("%ld: locking inconsistent mutex m1 succeeded\n", round); - return 1; - } - if (e != ENOTRECOVERABLE) - { - printf ("%ld: locking inconsistent mutex m1 failed with error %d\n", - round, e); - return 1; - } - - if (pthread_mutex_destroy (&m1) != 0) - { - puts ("mutex_destroy m1 failed"); - return 1; - } - - e = LOCK (&m2); - if (e == 0) - { - printf ("%ld: locking inconsistent mutex m2 succeeded\n", round); - return 1; - } - if (e != ENOTRECOVERABLE) - { - printf ("%ld: locking inconsistent mutex m2 failed with error %d\n", - round, e); - return 1; - } - - if (pthread_mutex_destroy (&m2) != 0) - { - puts ("mutex_destroy m2 failed"); - return 1; - } -#endif - } - -#ifndef NOT_CONSISTENT - if (pthread_mutex_destroy (&m1) != 0) - { - puts ("mutex_destroy m1 failed"); - return 1; - } - - if (pthread_mutex_destroy (&m2) != 0) - { - puts ("mutex_destroy m2 failed"); - return 1; - } -#endif - - 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/nptl/tst-robust10.c b/nptl/tst-robust10.c deleted file mode 100644 index db8b7e30f6..0000000000 --- a/nptl/tst-robust10.c +++ /dev/null @@ -1,110 +0,0 @@ -/* Test that pthread_mutex_timedlock properly times out. - Copyright (C) 2016-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 - . */ - -#include -#include -#include -#include -#include - -pthread_mutex_t mutex; - -static void * -thr (void *arg) -{ - struct timespec abstime; - clock_gettime (CLOCK_REALTIME, &abstime); - abstime.tv_sec += 1; - int ret = pthread_mutex_timedlock (&mutex, &abstime); - if (ret == 0) - { - puts ("mutex_timedlock didn't fail"); - exit (1); - } - if (ret != ETIMEDOUT) - { - printf ("mutex_timedlock failed: %s\n", strerror (ret)); - exit (1); - } - - return 0; -} - -static int -do_test (void) -{ - pthread_t pt; - pthread_mutexattr_t ma; - - if (pthread_mutexattr_init (&ma) != 0) - { - puts ("mutexattr_init failed"); - return 0; - } - if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0) - { - puts ("mutexattr_setrobust failed"); - return 1; - } - if (pthread_mutex_init (&mutex, &ma)) - { - puts ("mutex_init failed"); - return 1; - } - - if (pthread_mutexattr_destroy (&ma)) - { - puts ("mutexattr_destroy failed"); - return 1; - } - - if (pthread_mutex_lock (&mutex)) - { - puts ("mutex_lock failed"); - return 1; - } - - if (pthread_create (&pt, NULL, thr, NULL)) - { - puts ("pthread_create failed"); - return 1; - } - - if (pthread_join (pt, NULL)) - { - puts ("pthread_join failed"); - return 1; - } - - if (pthread_mutex_unlock (&mutex)) - { - puts ("mutex_unlock failed"); - return 1; - } - - if (pthread_mutex_destroy (&mutex)) - { - puts ("mutex_destroy failed"); - return 1; - } - - return 0; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/nptl/tst-robust2.c b/nptl/tst-robust2.c deleted file mode 100644 index cf603feb4d..0000000000 --- a/nptl/tst-robust2.c +++ /dev/null @@ -1,3 +0,0 @@ -#define AFTER_JOIN 1 -#define LOCK(m) pthread_mutex_trylock (m) -#include "tst-robust1.c" diff --git a/nptl/tst-robust3.c b/nptl/tst-robust3.c deleted file mode 100644 index e56f2762c7..0000000000 --- a/nptl/tst-robust3.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include - - -static struct timespec tmo; - - -#define PREPARE_TMO \ - do { \ - struct timeval tv; \ - gettimeofday (&tv, NULL); \ - \ - /* Define the timeout as one hour in the future. */ \ - tmo.tv_sec = tv.tv_sec + 3600; \ - tmo.tv_nsec = 0; \ - } while (0) - - -#define LOCK(m) pthread_mutex_timedlock (m, &tmo) -#include "tst-robust1.c" diff --git a/nptl/tst-robust4.c b/nptl/tst-robust4.c deleted file mode 100644 index b9c42b85b9..0000000000 --- a/nptl/tst-robust4.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NOT_CONSISTENT 1 -#include "tst-robust1.c" diff --git a/nptl/tst-robust5.c b/nptl/tst-robust5.c deleted file mode 100644 index b83d3d66cb..0000000000 --- a/nptl/tst-robust5.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NOT_CONSISTENT 1 -#include "tst-robust2.c" diff --git a/nptl/tst-robust6.c b/nptl/tst-robust6.c deleted file mode 100644 index 6713396de1..0000000000 --- a/nptl/tst-robust6.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NOT_CONSISTENT 1 -#include "tst-robust3.c" diff --git a/nptl/tst-robust7.c b/nptl/tst-robust7.c deleted file mode 100644 index be8e7492df..0000000000 --- a/nptl/tst-robust7.c +++ /dev/null @@ -1,212 +0,0 @@ -/* Copyright (C) 2005-2020 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2005. - - 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 - . */ - -#include -#include -#include -#include -#include - - -static pthread_barrier_t b; -static pthread_cond_t c = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t m; -static bool first = true; - - -static void * -tf (void *arg) -{ - long int n = (long int) arg; - - if (pthread_mutex_lock (&m) != 0) - { - printf ("thread %ld: mutex_lock failed\n", n + 1); - exit (1); - } - - int e = pthread_barrier_wait (&b); - if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf ("thread %ld: barrier_wait failed\n", n + 1); - exit (1); - } - - e = pthread_cond_wait (&c, &m); - if (first) - { - if (e != 0) - { - printf ("thread %ld: cond_wait failed\n", n + 1); - exit (1); - } - first = false; - } - else - { - if (e != EOWNERDEAD) - { - printf ("thread %ld: cond_wait did not return EOWNERDEAD\n", n + 1); - exit (1); - } - } - - if (pthread_cancel (pthread_self ()) != 0) - { - printf ("thread %ld: cancel failed\n", n + 1); - exit (1); - } - - pthread_testcancel (); - - printf ("thread %ld: testcancel returned\n", n + 1); - exit (1); -} - - -static int -do_test (void) -{ - pthread_mutexattr_t a; - if (pthread_mutexattr_init (&a) != 0) - { - puts ("mutexattr_init failed"); - return 1; - } - - if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0) - { - puts ("mutexattr_setrobust 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 robust mutexes not supported"); - return 0; - } -#endif - puts ("mutex_init failed"); - return 1; - } - - if (pthread_mutexattr_destroy (&a) != 0) - { - puts ("mutexattr_destroy failed"); - return 1; - } - - if (pthread_barrier_init (&b, NULL, 2) != 0) - { - puts ("barrier_init failed"); - return 1; - } - -#define N 5 - pthread_t th[N]; - for (long int n = 0; n < N; ++n) - { - if (pthread_create (&th[n], NULL, tf, (void *) n) != 0) - { - printf ("pthread_create loop %ld failed\n", n + 1); - return 1; - } - - e = pthread_barrier_wait (&b); - if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) - { - printf ("parent: barrier_wait failed in round %ld\n", n + 1); - return 1; - } - } - - if (pthread_mutex_lock (&m) != 0) - { - puts ("parent: mutex_lock failed"); - return 1; - } - - if (pthread_mutex_unlock (&m) != 0) - { - puts ("parent: mutex_unlock failed"); - return 1; - } - - if (pthread_cond_broadcast (&c) != 0) - { - puts ("cond_broadcast failed"); - return 1; - } - - for (int n = 0; n < N; ++n) - { - void *res; - if (pthread_join (th[n], &res) != 0) - { - printf ("join round %d failed\n", n + 1); - return 1; - } - if (res != PTHREAD_CANCELED) - { - printf ("thread %d not canceled\n", n + 1); - return 1; - } - } - - e = pthread_mutex_lock (&m); - if (e == 0) - { - puts ("parent: 2nd mutex_lock succeeded"); - return 1; - } - if (e != EOWNERDEAD) - { - puts ("parent: mutex_lock did not return EOWNERDEAD"); - return 1; - } - - if (pthread_mutex_unlock (&m) != 0) - { - puts ("parent: 2nd mutex_unlock failed"); - return 1; - } - - if (pthread_mutex_destroy (&m) != 0) - { - puts ("mutex_destroy failed"); - return 1; - } - - return 0; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/nptl/tst-robust8.c b/nptl/tst-robust8.c deleted file mode 100644 index f6969a4b84..0000000000 --- a/nptl/tst-robust8.c +++ /dev/null @@ -1,274 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - - -static void prepare (void); -#define PREPARE(argc, argv) prepare () -static int do_test (void); -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" - - -static int fd; -#define N 100 - -static void -prepare (void) -{ - fd = create_temp_file ("tst-robust8", NULL); - if (fd == -1) - exit (1); -} - - -#define THESIGNAL SIGKILL -#define ROUNDS 5 -#define THREADS 9 - - -static const struct timespec before = { 0, 0 }; - - -static pthread_mutex_t *map; - - -static void * -tf (void *arg) -{ - long int nr = (long int) arg; - int fct = nr % 3; - - uint8_t state[N]; - memset (state, '\0', sizeof (state)); - - while (1) - { - int r = random () % N; - if (state[r] == 0) - { - int e; - - switch (fct) - { - case 0: - e = pthread_mutex_lock (&map[r]); - if (e != 0) - { - printf ("mutex_lock of %d in thread %ld failed with %d\n", - r, nr, e); - exit (1); - } - state[r] = 1; - break; - case 1: - e = pthread_mutex_timedlock (&map[r], &before); - if (e != 0 && e != ETIMEDOUT) - { - printf ("\ -mutex_timedlock of %d in thread %ld failed with %d\n", - r, nr, e); - exit (1); - } - break; - default: - e = pthread_mutex_trylock (&map[r]); - if (e != 0 && e != EBUSY) - { - printf ("mutex_trylock of %d in thread %ld failed with %d\n", - r, nr, e); - exit (1); - } - break; - } - - if (e == EOWNERDEAD) - pthread_mutex_consistent_np (&map[r]); - - if (e == 0 || e == EOWNERDEAD) - state[r] = 1; - } - else - { - int e = pthread_mutex_unlock (&map[r]); - if (e != 0) - { - printf ("mutex_unlock of %d in thread %ld failed with %d\n", - r, nr, e); - exit (1); - } - - state[r] = 0; - } - } -} - - -static void -child (int round) -{ - for (int thread = 1; thread <= THREADS; ++thread) - { - pthread_t th; - if (pthread_create (&th, NULL, tf, (void *) (long int) thread) != 0) - { - printf ("cannot create thread %d in round %d\n", thread, round); - exit (1); - } - } - - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 1000000000 / ROUNDS; - while (nanosleep (&ts, &ts) != 0) - /* nothing */; - - /* Time to die. */ - kill (getpid (), THESIGNAL); - - /* We better never get here. */ - abort (); -} - - -static int -do_test (void) -{ - if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0) - { - puts ("cannot size new file"); - return 1; - } - - map = mmap (NULL, N * sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (map == MAP_FAILED) - { - puts ("mapping failed"); - return 1; - } - - pthread_mutexattr_t ma; - if (pthread_mutexattr_init (&ma) != 0) - { - puts ("mutexattr_init failed"); - return 0; - } - if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0) - { - puts ("mutexattr_setrobust failed"); - return 1; - } - if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0) - { - puts ("mutexattr_setpshared failed"); - return 1; - } -#ifdef ENABLE_PI - if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) - { - puts ("pthread_mutexattr_setprotocol failed"); - return 1; - } -#endif - - for (int round = 1; round <= ROUNDS; ++round) - { - for (int n = 0; n < N; ++n) - { - int e = pthread_mutex_init (&map[n], &ma); - if (e == ENOTSUP) - { -#ifdef ENABLE_PI - puts ("cannot support pshared robust PI mutexes"); -#else - puts ("cannot support pshared robust mutexes"); -#endif - return 0; - } - if (e != 0) - { - printf ("mutex_init %d in round %d failed\n", n + 1, round); - return 1; - } - } - - pid_t p = fork (); - if (p == -1) - { - printf ("fork in round %d failed\n", round); - return 1; - } - if (p == 0) - child (round); - - int status; - if (TEMP_FAILURE_RETRY (waitpid (p, &status, 0)) != p) - { - printf ("waitpid in round %d failed\n", round); - return 1; - } - if (!WIFSIGNALED (status)) - { - printf ("child did not die of a signal in round %d\n", round); - return 1; - } - if (WTERMSIG (status) != THESIGNAL) - { - printf ("child did not die of signal %d in round %d\n", - THESIGNAL, round); - return 1; - } - - for (int n = 0; n < N; ++n) - { - int e = pthread_mutex_lock (&map[n]); - if (e != 0 && e != EOWNERDEAD) - { - printf ("mutex_lock %d failed in round %d\n", n + 1, round); - return 1; - } - } - - for (int n = 0; n < N; ++n) - if (pthread_mutex_unlock (&map[n]) != 0) - { - printf ("mutex_unlock %d failed in round %d\n", n + 1, round); - return 1; - } - - for (int n = 0; n < N; ++n) - { - int e = pthread_mutex_destroy (&map[n]); - if (e != 0) - { - printf ("mutex_destroy %d in round %d failed with %d\n", - n + 1, round, e); - printf("nusers = %d\n", (int) map[n].__data.__nusers); - return 1; - } - } - } - - if (pthread_mutexattr_destroy (&ma) != 0) - { - puts ("mutexattr_destroy failed"); - return 1; - } - - if (munmap (map, N * sizeof (pthread_mutex_t)) != 0) - { - puts ("munmap failed"); - return 1; - } - - return 0; -} diff --git a/nptl/tst-robust9.c b/nptl/tst-robust9.c deleted file mode 100644 index befc14f2d8..0000000000 --- a/nptl/tst-robust9.c +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include -#include -#include -#include - - -static pthread_mutex_t m; - -static void * -tf (void *data) -{ - int err = pthread_mutex_lock (&m); - if (err == EOWNERDEAD) - { - err = pthread_mutex_consistent_np (&m); - if (err) - { - puts ("pthread_mutex_consistent_np"); - exit (1); - } - } - else if (err) - { - puts ("pthread_mutex_lock"); - exit (1); - } - printf ("thread%ld got the lock.\n", (long int) data); - sleep (1); - /* exit without unlock */ - return NULL; -} - -static int -do_test (void) -{ - int err, i; - pthread_t t[3]; - pthread_mutexattr_t ma; - - pthread_mutexattr_init (&ma); - err = pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP); - if (err) - { - puts ("pthread_mutexattr_setrobust_np"); - return 1; - } -#ifdef ENABLE_PI - if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) - { - puts ("pthread_mutexattr_setprotocol failed"); - return 1; - } -#endif - err = pthread_mutex_init (&m, &ma); -#ifdef ENABLE_PI - if (err == ENOTSUP) - { - puts ("PI robust mutexes not supported"); - return 0; - } -#endif - if (err) - { - puts ("pthread_mutex_init"); - return 1; - } - - for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) - { - err = pthread_create (&t[i], NULL, tf, (void *) (long int) i); - if (err) - { - puts ("pthread_create"); - return 1; - } - } - - for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) - { - err = pthread_join (t[i], NULL); - if (err) - { - puts ("pthread_join"); - return 1; - } - } - return 0; -} - -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h index 2bb4baa249..1726ebb122 100644 --- a/sysdeps/htl/pthreadP.h +++ b/sysdeps/htl/pthreadP.h @@ -19,6 +19,8 @@ #ifndef _PTHREADP_H #define _PTHREADP_H 1 +#define __PTHREAD_HTL + #include /* Attribute to indicate thread creation was issued from C11 thrd_create. */ diff --git a/sysdeps/mach/hurd/i386/Makefile b/sysdeps/mach/hurd/i386/Makefile index e6e665b5fe..068f7d0419 100644 --- a/sysdeps/mach/hurd/i386/Makefile +++ b/sysdeps/mach/hurd/i386/Makefile @@ -97,8 +97,8 @@ ifeq ($(subdir),mach) test-xfail-check-abi-libmachuser = yes endif -# For bug 25521 ifeq ($(subdir),htl) +# For bug 25521 test-xfail-tst-mutex4 = yes test-xfail-tst-cond4 = yes test-xfail-tst-cond6 = yes @@ -109,20 +109,26 @@ test-xfail-tst-rwlock4 = yes test-xfail-tst-rwlock12 = yes test-xfail-tst-sem3 = yes test-xfail-tst-barrier2 = yes -endif # For bug 25522 -ifeq ($(subdir),htl) test-xfail-tst-cond24 = yes test-xfail-tst-cond25 = yes -endif # For bug 25524 -ifeq ($(subdir),htl) test-xfail-tst-sem4 = yes test-xfail-tst-sem7 = yes test-xfail-tst-sem8 = yes test-xfail-tst-sem9 = yes + +# For bug 25563 +test-xfail-tst-robust1 = yes +test-xfail-tst-robust2 = yes +test-xfail-tst-robust3 = yes +test-xfail-tst-robust4 = yes +test-xfail-tst-robust5 = yes +test-xfail-tst-robust6 = yes +test-xfail-tst-robust7 = yes +test-xfail-tst-robust9 = yes endif ifeq ($(subdir),elf) diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile index 396f2b18bf..b6491d6309 100644 --- a/sysdeps/pthread/Makefile +++ b/sysdeps/pthread/Makefile @@ -55,6 +55,8 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ tst-key1 tst-key2 tst-key3 tst-key4 \ tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex6 tst-mutex10 \ tst-once1 tst-once2 tst-once3 tst-once4 \ + tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ + tst-robust6 tst-robust7 tst-robust8 tst-robust9 tst-robust10 \ tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock13 tst-rwlock16 \ tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \ tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem6 tst-sem7 \ diff --git a/sysdeps/pthread/tst-robust1.c b/sysdeps/pthread/tst-robust1.c new file mode 100644 index 0000000000..fc21b4f52c --- /dev/null +++ b/sysdeps/pthread/tst-robust1.c @@ -0,0 +1,338 @@ +/* Copyright (C) 2005-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2005. + + 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 + . */ + +#include +#include +#include +#include + + +static pthread_mutex_t m1; +static pthread_mutex_t m2; +static pthread_barrier_t b; + + +#ifndef LOCK +# define LOCK(m) pthread_mutex_lock (m) +#endif + + +static void * +tf (void *arg) +{ + long int round = (long int) arg; + + if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0) + { + printf ("%ld: setcancelstate failed\n", round); + exit (1); + } + + int e = LOCK (&m1); + if (e != 0) + { + printf ("%ld: child: mutex_lock m1 failed with error %d\n", round, e); + exit (1); + } + + e = LOCK (&m2); + if (e != 0) + { + printf ("%ld: child: mutex_lock m2 failed with error %d\n", round, e); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%ld: child: 1st barrier_wait failed\n", round); + exit (1); + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%ld: child: 2nd barrier_wait failed\n", round); + exit (1); + } + + pthread_testcancel (); + + printf ("%ld: testcancel returned\n", round); + exit (1); +} + + +static int +do_test (void) +{ +#ifdef PREPARE_TMO + PREPARE_TMO; +#endif + + pthread_mutexattr_t a; + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + return 1; + } + if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0) + { + puts ("mutexattr_setrobust failed"); + return 1; + } + +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } + else + { + int e = pthread_mutex_init (&m1, &a); + if (e == ENOTSUP) + { + puts ("PI robust mutexes not supported"); + return 0; + } + else if (e != 0) + { + puts ("mutex_init m1 failed"); + return 1; + } + pthread_mutex_destroy (&m1); + } +#endif + +#ifndef NOT_CONSISTENT + if (pthread_mutex_init (&m1, &a) != 0) + { + puts ("mutex_init m1 failed"); + return 1; + } + + if (pthread_mutex_init (&m2, &a) != 0) + { + puts ("mutex_init m2 failed"); + return 1; + } +#endif + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } + + for (long int round = 1; round < 5; ++round) + { +#ifdef NOT_CONSISTENT + if (pthread_mutex_init (&m1 , &a) != 0) + { + puts ("mutex_init m1 failed"); + return 1; + } + if (pthread_mutex_init (&m2 , &a) != 0) + { + puts ("mutex_init m2 failed"); + return 1; + } +#endif + + pthread_t th; + if (pthread_create (&th, NULL, tf, (void *) round) != 0) + { + printf ("%ld: create failed\n", round); + return 1; + } + + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%ld: parent: 1st barrier_wait failed\n", round); + return 1; + } + + if (pthread_cancel (th) != 0) + { + printf ("%ld: cancel failed\n", round); + return 1; + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%ld: parent: 2nd barrier_wait failed\n", round); + return 1; + } + +#ifndef AFTER_JOIN + if (round & 1) +#endif + { + void *res; + if (pthread_join (th, &res) != 0) + { + printf ("%ld: join failed\n", round); + return 1; + } + if (res != PTHREAD_CANCELED) + { + printf ("%ld: thread not canceled\n", round); + return 1; + } + } + + e = LOCK (&m1); + if (e == 0) + { + printf ("%ld: parent: mutex_lock m1 succeeded\n", round); + return 1; + } + if (e != EOWNERDEAD) + { + printf ("%ld: parent: mutex_lock m1 returned wrong code\n", round); + return 1; + } + + e = LOCK (&m2); + if (e == 0) + { + printf ("%ld: parent: mutex_lock m2 succeeded\n", round); + return 1; + } + if (e != EOWNERDEAD) + { + printf ("%ld: parent: mutex_lock m2 returned wrong code\n", round); + return 1; + } + +#ifndef AFTER_JOIN + if ((round & 1) == 0) + { + void *res; + if (pthread_join (th, &res) != 0) + { + printf ("%ld: join failed\n", round); + return 1; + } + if (res != PTHREAD_CANCELED) + { + printf ("%ld: thread not canceled\n", round); + return 1; + } + } +#endif + +#ifndef NOT_CONSISTENT + e = pthread_mutex_consistent_np (&m1); + if (e != 0) + { + printf ("%ld: mutex_consistent m1 failed with error %d\n", round, e); + return 1; + } + + e = pthread_mutex_consistent_np (&m2); + if (e != 0) + { + printf ("%ld: mutex_consistent m2 failed with error %d\n", round, e); + return 1; + } +#endif + + e = pthread_mutex_unlock (&m1); + if (e != 0) + { + printf ("%ld: mutex_unlock m1 failed with %d\n", round, e); + return 1; + } + + e = pthread_mutex_unlock (&m2); + if (e != 0) + { + printf ("%ld: mutex_unlock m2 failed with %d\n", round, e); + return 1; + } + +#ifdef NOT_CONSISTENT + e = LOCK (&m1); + if (e == 0) + { + printf ("%ld: locking inconsistent mutex m1 succeeded\n", round); + return 1; + } + if (e != ENOTRECOVERABLE) + { + printf ("%ld: locking inconsistent mutex m1 failed with error %d\n", + round, e); + return 1; + } + + if (pthread_mutex_destroy (&m1) != 0) + { + puts ("mutex_destroy m1 failed"); + return 1; + } + + e = LOCK (&m2); + if (e == 0) + { + printf ("%ld: locking inconsistent mutex m2 succeeded\n", round); + return 1; + } + if (e != ENOTRECOVERABLE) + { + printf ("%ld: locking inconsistent mutex m2 failed with error %d\n", + round, e); + return 1; + } + + if (pthread_mutex_destroy (&m2) != 0) + { + puts ("mutex_destroy m2 failed"); + return 1; + } +#endif + } + +#ifndef NOT_CONSISTENT + if (pthread_mutex_destroy (&m1) != 0) + { + puts ("mutex_destroy m1 failed"); + return 1; + } + + if (pthread_mutex_destroy (&m2) != 0) + { + puts ("mutex_destroy m2 failed"); + return 1; + } +#endif + + 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-robust10.c b/sysdeps/pthread/tst-robust10.c new file mode 100644 index 0000000000..db8b7e30f6 --- /dev/null +++ b/sysdeps/pthread/tst-robust10.c @@ -0,0 +1,110 @@ +/* Test that pthread_mutex_timedlock properly times out. + Copyright (C) 2016-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 + . */ + +#include +#include +#include +#include +#include + +pthread_mutex_t mutex; + +static void * +thr (void *arg) +{ + struct timespec abstime; + clock_gettime (CLOCK_REALTIME, &abstime); + abstime.tv_sec += 1; + int ret = pthread_mutex_timedlock (&mutex, &abstime); + if (ret == 0) + { + puts ("mutex_timedlock didn't fail"); + exit (1); + } + if (ret != ETIMEDOUT) + { + printf ("mutex_timedlock failed: %s\n", strerror (ret)); + exit (1); + } + + return 0; +} + +static int +do_test (void) +{ + pthread_t pt; + pthread_mutexattr_t ma; + + if (pthread_mutexattr_init (&ma) != 0) + { + puts ("mutexattr_init failed"); + return 0; + } + if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0) + { + puts ("mutexattr_setrobust failed"); + return 1; + } + if (pthread_mutex_init (&mutex, &ma)) + { + puts ("mutex_init failed"); + return 1; + } + + if (pthread_mutexattr_destroy (&ma)) + { + puts ("mutexattr_destroy failed"); + return 1; + } + + if (pthread_mutex_lock (&mutex)) + { + puts ("mutex_lock failed"); + return 1; + } + + if (pthread_create (&pt, NULL, thr, NULL)) + { + puts ("pthread_create failed"); + return 1; + } + + if (pthread_join (pt, NULL)) + { + puts ("pthread_join failed"); + return 1; + } + + if (pthread_mutex_unlock (&mutex)) + { + puts ("mutex_unlock failed"); + return 1; + } + + if (pthread_mutex_destroy (&mutex)) + { + puts ("mutex_destroy failed"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-robust2.c b/sysdeps/pthread/tst-robust2.c new file mode 100644 index 0000000000..cf603feb4d --- /dev/null +++ b/sysdeps/pthread/tst-robust2.c @@ -0,0 +1,3 @@ +#define AFTER_JOIN 1 +#define LOCK(m) pthread_mutex_trylock (m) +#include "tst-robust1.c" diff --git a/sysdeps/pthread/tst-robust3.c b/sysdeps/pthread/tst-robust3.c new file mode 100644 index 0000000000..e56f2762c7 --- /dev/null +++ b/sysdeps/pthread/tst-robust3.c @@ -0,0 +1,20 @@ +#include +#include + + +static struct timespec tmo; + + +#define PREPARE_TMO \ + do { \ + struct timeval tv; \ + gettimeofday (&tv, NULL); \ + \ + /* Define the timeout as one hour in the future. */ \ + tmo.tv_sec = tv.tv_sec + 3600; \ + tmo.tv_nsec = 0; \ + } while (0) + + +#define LOCK(m) pthread_mutex_timedlock (m, &tmo) +#include "tst-robust1.c" diff --git a/sysdeps/pthread/tst-robust4.c b/sysdeps/pthread/tst-robust4.c new file mode 100644 index 0000000000..b9c42b85b9 --- /dev/null +++ b/sysdeps/pthread/tst-robust4.c @@ -0,0 +1,2 @@ +#define NOT_CONSISTENT 1 +#include "tst-robust1.c" diff --git a/sysdeps/pthread/tst-robust5.c b/sysdeps/pthread/tst-robust5.c new file mode 100644 index 0000000000..b83d3d66cb --- /dev/null +++ b/sysdeps/pthread/tst-robust5.c @@ -0,0 +1,2 @@ +#define NOT_CONSISTENT 1 +#include "tst-robust2.c" diff --git a/sysdeps/pthread/tst-robust6.c b/sysdeps/pthread/tst-robust6.c new file mode 100644 index 0000000000..6713396de1 --- /dev/null +++ b/sysdeps/pthread/tst-robust6.c @@ -0,0 +1,2 @@ +#define NOT_CONSISTENT 1 +#include "tst-robust3.c" diff --git a/sysdeps/pthread/tst-robust7.c b/sysdeps/pthread/tst-robust7.c new file mode 100644 index 0000000000..be8e7492df --- /dev/null +++ b/sysdeps/pthread/tst-robust7.c @@ -0,0 +1,212 @@ +/* Copyright (C) 2005-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2005. + + 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 + . */ + +#include +#include +#include +#include +#include + + +static pthread_barrier_t b; +static pthread_cond_t c = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t m; +static bool first = true; + + +static void * +tf (void *arg) +{ + long int n = (long int) arg; + + if (pthread_mutex_lock (&m) != 0) + { + printf ("thread %ld: mutex_lock failed\n", n + 1); + exit (1); + } + + int e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("thread %ld: barrier_wait failed\n", n + 1); + exit (1); + } + + e = pthread_cond_wait (&c, &m); + if (first) + { + if (e != 0) + { + printf ("thread %ld: cond_wait failed\n", n + 1); + exit (1); + } + first = false; + } + else + { + if (e != EOWNERDEAD) + { + printf ("thread %ld: cond_wait did not return EOWNERDEAD\n", n + 1); + exit (1); + } + } + + if (pthread_cancel (pthread_self ()) != 0) + { + printf ("thread %ld: cancel failed\n", n + 1); + exit (1); + } + + pthread_testcancel (); + + printf ("thread %ld: testcancel returned\n", n + 1); + exit (1); +} + + +static int +do_test (void) +{ + pthread_mutexattr_t a; + if (pthread_mutexattr_init (&a) != 0) + { + puts ("mutexattr_init failed"); + return 1; + } + + if (pthread_mutexattr_setrobust_np (&a, PTHREAD_MUTEX_ROBUST_NP) != 0) + { + puts ("mutexattr_setrobust 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 robust mutexes not supported"); + return 0; + } +#endif + puts ("mutex_init failed"); + return 1; + } + + if (pthread_mutexattr_destroy (&a) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + + if (pthread_barrier_init (&b, NULL, 2) != 0) + { + puts ("barrier_init failed"); + return 1; + } + +#define N 5 + pthread_t th[N]; + for (long int n = 0; n < N; ++n) + { + if (pthread_create (&th[n], NULL, tf, (void *) n) != 0) + { + printf ("pthread_create loop %ld failed\n", n + 1); + return 1; + } + + e = pthread_barrier_wait (&b); + if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("parent: barrier_wait failed in round %ld\n", n + 1); + return 1; + } + } + + if (pthread_mutex_lock (&m) != 0) + { + puts ("parent: mutex_lock failed"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("parent: mutex_unlock failed"); + return 1; + } + + if (pthread_cond_broadcast (&c) != 0) + { + puts ("cond_broadcast failed"); + return 1; + } + + for (int n = 0; n < N; ++n) + { + void *res; + if (pthread_join (th[n], &res) != 0) + { + printf ("join round %d failed\n", n + 1); + return 1; + } + if (res != PTHREAD_CANCELED) + { + printf ("thread %d not canceled\n", n + 1); + return 1; + } + } + + e = pthread_mutex_lock (&m); + if (e == 0) + { + puts ("parent: 2nd mutex_lock succeeded"); + return 1; + } + if (e != EOWNERDEAD) + { + puts ("parent: mutex_lock did not return EOWNERDEAD"); + return 1; + } + + if (pthread_mutex_unlock (&m) != 0) + { + puts ("parent: 2nd mutex_unlock failed"); + return 1; + } + + if (pthread_mutex_destroy (&m) != 0) + { + puts ("mutex_destroy failed"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/sysdeps/pthread/tst-robust8.c b/sysdeps/pthread/tst-robust8.c new file mode 100644 index 0000000000..27dd53d2c3 --- /dev/null +++ b/sysdeps/pthread/tst-robust8.c @@ -0,0 +1,277 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + + +static void prepare (void); +#define PREPARE(argc, argv) prepare () +static int do_test (void); +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" + + +static int fd; +#define N 100 + +static void +prepare (void) +{ + fd = create_temp_file ("tst-robust8", NULL); + if (fd == -1) + exit (1); +} + + +#define THESIGNAL SIGKILL +#define ROUNDS 5 +#define THREADS 9 + + +static const struct timespec before = { 0, 0 }; + + +static pthread_mutex_t *map; + + +static void * +tf (void *arg) +{ + long int nr = (long int) arg; + int fct = nr % 3; + + uint8_t state[N]; + memset (state, '\0', sizeof (state)); + + while (1) + { + int r = random () % N; + if (state[r] == 0) + { + int e; + + switch (fct) + { + case 0: + e = pthread_mutex_lock (&map[r]); + if (e != 0) + { + printf ("mutex_lock of %d in thread %ld failed with %d\n", + r, nr, e); + exit (1); + } + state[r] = 1; + break; + case 1: + e = pthread_mutex_timedlock (&map[r], &before); + if (e != 0 && e != ETIMEDOUT) + { + printf ("\ +mutex_timedlock of %d in thread %ld failed with %d\n", + r, nr, e); + exit (1); + } + break; + default: + e = pthread_mutex_trylock (&map[r]); + if (e != 0 && e != EBUSY) + { + printf ("mutex_trylock of %d in thread %ld failed with %d\n", + r, nr, e); + exit (1); + } + break; + } + + if (e == EOWNERDEAD) + pthread_mutex_consistent_np (&map[r]); + + if (e == 0 || e == EOWNERDEAD) + state[r] = 1; + } + else + { + int e = pthread_mutex_unlock (&map[r]); + if (e != 0) + { + printf ("mutex_unlock of %d in thread %ld failed with %d\n", + r, nr, e); + exit (1); + } + + state[r] = 0; + } + } +} + + +static void +child (int round) +{ + for (int thread = 1; thread <= THREADS; ++thread) + { + pthread_t th; + if (pthread_create (&th, NULL, tf, (void *) (long int) thread) != 0) + { + printf ("cannot create thread %d in round %d\n", thread, round); + exit (1); + } + } + + struct timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 1000000000 / ROUNDS; + while (nanosleep (&ts, &ts) != 0) + /* nothing */; + + /* Time to die. */ + kill (getpid (), THESIGNAL); + + /* We better never get here. */ + abort (); +} + + +static int +do_test (void) +{ + if (ftruncate (fd, N * sizeof (pthread_mutex_t)) != 0) + { + puts ("cannot size new file"); + return 1; + } + + map = mmap (NULL, N * sizeof (pthread_mutex_t), PROT_READ | PROT_WRITE, + MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + { + puts ("mapping failed"); + return 1; + } + + pthread_mutexattr_t ma; + if (pthread_mutexattr_init (&ma) != 0) + { + puts ("mutexattr_init failed"); + return 0; + } + if (pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP) != 0) + { + puts ("mutexattr_setrobust failed"); + return 1; + } + if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0) + { + puts ("mutexattr_setpshared failed"); + return 1; + } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + + for (int round = 1; round <= ROUNDS; ++round) + { + for (int n = 0; n < N; ++n) + { + int e = pthread_mutex_init (&map[n], &ma); + if (e == ENOTSUP) + { +#ifdef ENABLE_PI + puts ("cannot support pshared robust PI mutexes"); +#else + puts ("cannot support pshared robust mutexes"); +#endif + return 0; + } + if (e != 0) + { + printf ("mutex_init %d in round %d failed\n", n + 1, round); + return 1; + } + } + + pid_t p = fork (); + if (p == -1) + { + printf ("fork in round %d failed\n", round); + return 1; + } + if (p == 0) + child (round); + + int status; + if (TEMP_FAILURE_RETRY (waitpid (p, &status, 0)) != p) + { + printf ("waitpid in round %d failed\n", round); + return 1; + } + if (!WIFSIGNALED (status)) + { + printf ("child did not die of a signal in round %d\n", round); + return 1; + } + if (WTERMSIG (status) != THESIGNAL) + { + printf ("child did not die of signal %d in round %d\n", + THESIGNAL, round); + return 1; + } + + for (int n = 0; n < N; ++n) + { + int e = pthread_mutex_lock (&map[n]); + if (e != 0 && e != EOWNERDEAD) + { + printf ("mutex_lock %d failed in round %d\n", n + 1, round); + return 1; + } + } + + for (int n = 0; n < N; ++n) + if (pthread_mutex_unlock (&map[n]) != 0) + { + printf ("mutex_unlock %d failed in round %d\n", n + 1, round); + return 1; + } + + for (int n = 0; n < N; ++n) + { + int e = pthread_mutex_destroy (&map[n]); + if (e != 0) + { + printf ("mutex_destroy %d in round %d failed with %d\n", + n + 1, round, e); +#ifdef __PTHREAD_NPTL + printf("nusers = %d\n", (int) map[n].__data.__nusers); +#endif + return 1; + } + } + } + + if (pthread_mutexattr_destroy (&ma) != 0) + { + puts ("mutexattr_destroy failed"); + return 1; + } + + if (munmap (map, N * sizeof (pthread_mutex_t)) != 0) + { + puts ("munmap failed"); + return 1; + } + + return 0; +} diff --git a/sysdeps/pthread/tst-robust9.c b/sysdeps/pthread/tst-robust9.c new file mode 100644 index 0000000000..befc14f2d8 --- /dev/null +++ b/sysdeps/pthread/tst-robust9.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include + + +static pthread_mutex_t m; + +static void * +tf (void *data) +{ + int err = pthread_mutex_lock (&m); + if (err == EOWNERDEAD) + { + err = pthread_mutex_consistent_np (&m); + if (err) + { + puts ("pthread_mutex_consistent_np"); + exit (1); + } + } + else if (err) + { + puts ("pthread_mutex_lock"); + exit (1); + } + printf ("thread%ld got the lock.\n", (long int) data); + sleep (1); + /* exit without unlock */ + return NULL; +} + +static int +do_test (void) +{ + int err, i; + pthread_t t[3]; + pthread_mutexattr_t ma; + + pthread_mutexattr_init (&ma); + err = pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP); + if (err) + { + puts ("pthread_mutexattr_setrobust_np"); + return 1; + } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + err = pthread_mutex_init (&m, &ma); +#ifdef ENABLE_PI + if (err == ENOTSUP) + { + puts ("PI robust mutexes not supported"); + return 0; + } +#endif + if (err) + { + puts ("pthread_mutex_init"); + return 1; + } + + for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) + { + err = pthread_create (&t[i], NULL, tf, (void *) (long int) i); + if (err) + { + puts ("pthread_create"); + return 1; + } + } + + for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) + { + err = pthread_join (t[i], NULL); + if (err) + { + puts ("pthread_join"); + return 1; + } + } + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" -- cgit v1.2.1