(root)/
glibc-2.38/
sysdeps/
pthread/
tst-robust1.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 <stdio.h>
      21  #include <stdlib.h>
      22  
      23  
      24  static pthread_mutex_t m1;
      25  static pthread_mutex_t m2;
      26  static pthread_barrier_t b;
      27  
      28  
      29  #ifndef LOCK
      30  # define LOCK(m) pthread_mutex_lock (m)
      31  #endif
      32  
      33  
      34  static void *
      35  tf (void *arg)
      36  {
      37    long int round = (long int) arg;
      38  
      39    if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
      40      {
      41        printf ("%ld: setcancelstate failed\n", round);
      42        exit (1);
      43      }
      44  
      45    int e = LOCK (&m1);
      46    if (e != 0)
      47      {
      48        printf ("%ld: child: mutex_lock m1 failed with error %d\n", round, e);
      49        exit (1);
      50      }
      51  
      52    e = LOCK (&m2);
      53    if (e != 0)
      54      {
      55        printf ("%ld: child: mutex_lock m2 failed with error %d\n", round, e);
      56        exit (1);
      57      }
      58  
      59    e = pthread_barrier_wait (&b);
      60    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      61      {
      62        printf ("%ld: child: 1st barrier_wait failed\n", round);
      63        exit (1);
      64      }
      65  
      66    e = pthread_barrier_wait (&b);
      67    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      68      {
      69        printf ("%ld: child: 2nd barrier_wait failed\n", round);
      70        exit (1);
      71      }
      72  
      73    pthread_testcancel ();
      74  
      75    printf ("%ld: testcancel returned\n", round);
      76    exit (1);
      77  }
      78  
      79  
      80  static int
      81  do_test (void)
      82  {
      83  #ifdef PREPARE_TMO
      84    PREPARE_TMO;
      85  #endif
      86  
      87    pthread_mutexattr_t a;
      88    if (pthread_mutexattr_init (&a) != 0)
      89      {
      90        puts ("mutexattr_init failed");
      91        return 1;
      92      }
      93    if (pthread_mutexattr_setrobust (&a, PTHREAD_MUTEX_ROBUST_NP) != 0)
      94      {
      95        puts ("mutexattr_setrobust failed");
      96        return 1;
      97      }
      98  
      99  #ifdef ENABLE_PI
     100    if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
     101      {
     102        puts ("pthread_mutexattr_setprotocol failed");
     103        return 1;
     104      }
     105    else
     106      {
     107        int e = pthread_mutex_init (&m1, &a);
     108        if (e == ENOTSUP)
     109  	{
     110  	  puts ("PI robust mutexes not supported");
     111  	  return 0;
     112  	}
     113        else if (e != 0)
     114  	{
     115  	  puts ("mutex_init m1 failed");
     116  	  return 1;
     117  	}
     118        pthread_mutex_destroy (&m1);
     119      }
     120  #endif
     121  
     122  #ifndef NOT_CONSISTENT
     123    if (pthread_mutex_init (&m1, &a) != 0)
     124      {
     125        puts ("mutex_init m1 failed");
     126        return 1;
     127      }
     128  
     129    if (pthread_mutex_init (&m2, &a) != 0)
     130      {
     131        puts ("mutex_init m2 failed");
     132        return 1;
     133      }
     134  #endif
     135  
     136    if (pthread_barrier_init (&b, NULL, 2) != 0)
     137      {
     138        puts ("barrier_init failed");
     139        return 1;
     140      }
     141  
     142    for (long int round = 1; round < 5; ++round)
     143      {
     144  #ifdef NOT_CONSISTENT
     145        if (pthread_mutex_init (&m1 , &a) != 0)
     146  	{
     147  	  puts ("mutex_init m1 failed");
     148  	  return 1;
     149  	}
     150        if (pthread_mutex_init (&m2 , &a) != 0)
     151  	{
     152  	  puts ("mutex_init m2 failed");
     153  	  return 1;
     154  	}
     155  #endif
     156  
     157        pthread_t th;
     158        if (pthread_create (&th, NULL, tf, (void *) round) != 0)
     159  	{
     160  	  printf ("%ld: create failed\n", round);
     161  	  return 1;
     162  	}
     163  
     164        int e = pthread_barrier_wait (&b);
     165        if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     166  	{
     167  	  printf ("%ld: parent: 1st barrier_wait failed\n", round);
     168  	  return 1;
     169  	}
     170  
     171        if (pthread_cancel (th) != 0)
     172  	{
     173  	  printf ("%ld: cancel failed\n", round);
     174  	  return 1;
     175  	}
     176  
     177        e = pthread_barrier_wait (&b);
     178        if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     179  	{
     180  	  printf ("%ld: parent: 2nd barrier_wait failed\n", round);
     181  	  return 1;
     182  	}
     183  
     184  #ifndef AFTER_JOIN
     185        if (round & 1)
     186  #endif
     187  	{
     188  	  void *res;
     189  	  if (pthread_join (th, &res) != 0)
     190  	    {
     191  	      printf ("%ld: join failed\n", round);
     192  	      return 1;
     193  	    }
     194  	  if (res != PTHREAD_CANCELED)
     195  	    {
     196  	      printf ("%ld: thread not canceled\n", round);
     197  	      return 1;
     198  	    }
     199  	}
     200  
     201        e = LOCK (&m1);
     202        if (e == 0)
     203  	{
     204  	  printf ("%ld: parent: mutex_lock m1 succeeded\n", round);
     205  	  return 1;
     206  	}
     207        if (e != EOWNERDEAD)
     208  	{
     209  	  printf ("%ld: parent: mutex_lock m1 returned wrong code\n", round);
     210  	  return 1;
     211  	}
     212  
     213        e = LOCK (&m2);
     214        if (e == 0)
     215  	{
     216  	  printf ("%ld: parent: mutex_lock m2 succeeded\n", round);
     217  	  return 1;
     218  	}
     219        if (e != EOWNERDEAD)
     220  	{
     221  	  printf ("%ld: parent: mutex_lock m2 returned wrong code\n", round);
     222  	  return 1;
     223  	}
     224  
     225  #ifndef AFTER_JOIN
     226        if ((round & 1) == 0)
     227  	{
     228  	  void *res;
     229  	  if (pthread_join (th, &res) != 0)
     230  	    {
     231  	      printf ("%ld: join failed\n", round);
     232  	      return 1;
     233  	    }
     234  	  if (res != PTHREAD_CANCELED)
     235  	    {
     236  	      printf ("%ld: thread not canceled\n", round);
     237  	      return 1;
     238  	    }
     239  	}
     240  #endif
     241  
     242  #ifndef NOT_CONSISTENT
     243        e = pthread_mutex_consistent (&m1);
     244        if (e != 0)
     245  	{
     246  	  printf ("%ld: mutex_consistent m1 failed with error %d\n", round, e);
     247  	  return 1;
     248  	}
     249  
     250        e = pthread_mutex_consistent (&m2);
     251        if (e != 0)
     252  	{
     253  	  printf ("%ld: mutex_consistent m2 failed with error %d\n", round, e);
     254  	  return 1;
     255  	}
     256  #endif
     257  
     258        e = pthread_mutex_unlock (&m1);
     259        if (e != 0)
     260  	{
     261  	  printf ("%ld: mutex_unlock m1 failed with %d\n", round, e);
     262  	  return 1;
     263  	}
     264  
     265        e = pthread_mutex_unlock (&m2);
     266        if (e != 0)
     267  	{
     268  	  printf ("%ld: mutex_unlock m2 failed with %d\n", round, e);
     269  	  return 1;
     270  	}
     271  
     272  #ifdef NOT_CONSISTENT
     273        e = LOCK (&m1);
     274        if (e == 0)
     275  	{
     276  	  printf ("%ld: locking inconsistent mutex m1 succeeded\n", round);
     277  	  return 1;
     278  	}
     279        if (e != ENOTRECOVERABLE)
     280  	{
     281  	  printf ("%ld: locking inconsistent mutex m1 failed with error %d\n",
     282  		  round, e);
     283  	  return 1;
     284  	}
     285  
     286        if (pthread_mutex_destroy (&m1) != 0)
     287  	{
     288  	  puts ("mutex_destroy m1 failed");
     289  	  return 1;
     290  	}
     291  
     292        e = LOCK (&m2);
     293        if (e == 0)
     294  	{
     295  	  printf ("%ld: locking inconsistent mutex m2 succeeded\n", round);
     296  	  return 1;
     297  	}
     298        if (e != ENOTRECOVERABLE)
     299  	{
     300  	  printf ("%ld: locking inconsistent mutex m2 failed with error %d\n",
     301  		  round, e);
     302  	  return 1;
     303  	}
     304  
     305        if (pthread_mutex_destroy (&m2) != 0)
     306  	{
     307  	  puts ("mutex_destroy m2 failed");
     308  	  return 1;
     309  	}
     310  #endif
     311      }
     312  
     313  #ifndef NOT_CONSISTENT
     314    if (pthread_mutex_destroy (&m1) != 0)
     315      {
     316        puts ("mutex_destroy m1 failed");
     317        return 1;
     318      }
     319  
     320    if (pthread_mutex_destroy (&m2) != 0)
     321      {
     322        puts ("mutex_destroy m2 failed");
     323        return 1;
     324      }
     325  #endif
     326  
     327    if (pthread_mutexattr_destroy (&a) != 0)
     328      {
     329        puts ("mutexattr_destroy failed");
     330        return 1;
     331      }
     332  
     333    return 0;
     334  }
     335  
     336  #define TEST_FUNCTION do_test ()
     337  #include "../test-skeleton.c"