/* Copyright (C) 2005-2016 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"