(root)/
glibc-2.38/
sysdeps/
pthread/
tst-robust7.c
       1  /* Copyright (C) 2005-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <pthread.h>
      20  #include <stdbool.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  
      24  
      25  static pthread_barrier_t b;
      26  static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
      27  static pthread_mutex_t m;
      28  static bool first = true;
      29  
      30  
      31  static void *
      32  tf (void *arg)
      33  {
      34    long int n = (long int) arg;
      35  
      36    if (pthread_mutex_lock (&m) != 0)
      37      {
      38        printf ("thread %ld: mutex_lock failed\n", n + 1);
      39        exit (1);
      40      }
      41  
      42    int e = pthread_barrier_wait (&b);
      43    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      44      {
      45        printf ("thread %ld: barrier_wait failed\n", n + 1);
      46        exit (1);
      47      }
      48  
      49    e = pthread_cond_wait (&c, &m);
      50    if (first)
      51      {
      52        if (e != 0)
      53  	{
      54  	  printf ("thread %ld: cond_wait failed\n", n + 1);
      55  	  exit (1);
      56  	}
      57        first = false;
      58      }
      59    else
      60      {
      61        if (e != EOWNERDEAD)
      62  	{
      63  	  printf ("thread %ld: cond_wait did not return EOWNERDEAD\n", n + 1);
      64  	  exit (1);
      65  	}
      66      }
      67  
      68    if (pthread_cancel (pthread_self ()) != 0)
      69      {
      70        printf ("thread %ld: cancel failed\n", n + 1);
      71        exit (1);
      72      }
      73  
      74    pthread_testcancel ();
      75  
      76    printf ("thread %ld: testcancel returned\n", n + 1);
      77    exit (1);
      78  }
      79  
      80  
      81  static int
      82  do_test (void)
      83  {
      84    pthread_mutexattr_t a;
      85    if (pthread_mutexattr_init (&a) != 0)
      86      {
      87        puts ("mutexattr_init failed");
      88        return 1;
      89      }
      90  
      91    if (pthread_mutexattr_setrobust (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
      92      {
      93        puts ("mutexattr_setrobust failed");
      94        return 1;
      95      }
      96  
      97  #ifdef ENABLE_PI
      98    if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
      99      {
     100        puts ("pthread_mutexattr_setprotocol failed");
     101        return 1;
     102      }
     103  #endif
     104  
     105    int e;
     106    e = pthread_mutex_init (&m, &a);
     107    if (e != 0)
     108      {
     109  #ifdef ENABLE_PI
     110        if (e == ENOTSUP)
     111  	{
     112  	  puts ("PI robust mutexes not supported");
     113  	  return 0;
     114  	}
     115  #endif
     116        puts ("mutex_init failed");
     117        return 1;
     118      }
     119  
     120    if (pthread_mutexattr_destroy (&a) != 0)
     121      {
     122        puts ("mutexattr_destroy failed");
     123        return 1;
     124      }
     125  
     126    if (pthread_barrier_init (&b, NULL, 2) != 0)
     127      {
     128        puts ("barrier_init failed");
     129        return 1;
     130      }
     131  
     132  #define N 5
     133    pthread_t th[N];
     134    for (long int n = 0; n < N; ++n)
     135      {
     136        if (pthread_create (&th[n], NULL, tf, (void *) n) != 0)
     137  	{
     138  	  printf ("pthread_create loop %ld failed\n", n + 1);
     139  	  return 1;
     140  	}
     141  
     142        e = pthread_barrier_wait (&b);
     143        if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     144  	{
     145  	  printf ("parent: barrier_wait failed in round %ld\n", n + 1);
     146  	  return 1;
     147  	}
     148      }
     149  
     150    if (pthread_mutex_lock (&m) != 0)
     151      {
     152        puts ("parent: mutex_lock failed");
     153        return 1;
     154      }
     155  
     156    if (pthread_mutex_unlock (&m) != 0)
     157      {
     158        puts ("parent: mutex_unlock failed");
     159        return 1;
     160      }
     161  
     162    if (pthread_cond_broadcast (&c) != 0)
     163      {
     164        puts ("cond_broadcast failed");
     165        return 1;
     166      }
     167  
     168    for (int n = 0; n < N; ++n)
     169      {
     170        void *res;
     171        if (pthread_join (th[n], &res) != 0)
     172  	{
     173  	  printf ("join round %d failed\n", n + 1);
     174  	  return 1;
     175  	}
     176        if (res != PTHREAD_CANCELED)
     177  	{
     178  	  printf ("thread %d not canceled\n", n + 1);
     179  	  return 1;
     180  	}
     181      }
     182  
     183    e = pthread_mutex_lock (&m);
     184    if (e == 0)
     185      {
     186        puts ("parent: 2nd mutex_lock succeeded");
     187        return 1;
     188      }
     189    if (e != EOWNERDEAD)
     190      {
     191        puts ("parent: mutex_lock did not return EOWNERDEAD");
     192        return 1;
     193      }
     194  
     195    if (pthread_mutex_unlock (&m) != 0)
     196      {
     197        puts ("parent: 2nd mutex_unlock failed");
     198        return 1;
     199      }
     200  
     201    if (pthread_mutex_destroy (&m) != 0)
     202      {
     203        puts ("mutex_destroy failed");
     204        return 1;
     205      }
     206  
     207    return 0;
     208  }
     209  
     210  #define TEST_FUNCTION do_test ()
     211  #include "../test-skeleton.c"