(root)/
glibc-2.38/
sysdeps/
pthread/
tst-mutex2.c
       1  /* Copyright (C) 2002-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 m;
      25  static pthread_barrier_t b;
      26  
      27  
      28  static void *
      29  tf (void *arg)
      30  {
      31    int e = pthread_mutex_unlock (&m);
      32    if (e == 0)
      33      {
      34        puts ("child: 1st mutex_unlock succeeded");
      35        exit (1);
      36      }
      37    else if (e != EPERM)
      38      {
      39        puts ("child: 1st mutex_unlock error != EPERM");
      40        exit (1);
      41      }
      42  
      43    e = pthread_mutex_trylock (&m);
      44    if (e == 0)
      45      {
      46        puts ("child: 1st trylock succeeded");
      47        exit (1);
      48      }
      49    if (e != EBUSY)
      50      {
      51        puts ("child: 1st trylock didn't return EBUSY");
      52        exit (1);
      53      }
      54  
      55    e = pthread_barrier_wait (&b);
      56    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      57      {
      58        puts ("child: 1st barrier_wait failed");
      59        exit (1);
      60      }
      61  
      62    e = pthread_barrier_wait (&b);
      63    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      64      {
      65        puts ("child: 2nd barrier_wait failed");
      66        exit (1);
      67      }
      68  
      69    e = pthread_mutex_unlock (&m);
      70    if (e == 0)
      71      {
      72        puts ("child: 2nd mutex_unlock succeeded");
      73        exit (1);
      74      }
      75    else if (e != EPERM)
      76      {
      77        puts ("child: 2nd mutex_unlock error != EPERM");
      78        exit (1);
      79      }
      80  
      81    if (pthread_mutex_trylock (&m) != 0)
      82      {
      83        puts ("child: 2nd trylock failed");
      84        exit (1);
      85      }
      86  
      87    if (pthread_mutex_unlock (&m) != 0)
      88      {
      89        puts ("child: 3rd mutex_unlock failed");
      90        exit (1);
      91      }
      92  
      93    return NULL;
      94  }
      95  
      96  
      97  static int
      98  do_test (void)
      99  {
     100    pthread_mutexattr_t a;
     101    int e;
     102  
     103    if (pthread_mutexattr_init (&a) != 0)
     104      {
     105        puts ("mutexattr_init failed");
     106        return 1;
     107      }
     108  
     109    if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_ERRORCHECK) != 0)
     110      {
     111        puts ("mutexattr_settype failed");
     112        return 1;
     113      }
     114  
     115  #ifdef ENABLE_PI
     116    if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
     117      {
     118        puts ("pthread_mutexattr_setprotocol failed");
     119        return 1;
     120      }
     121  #endif
     122  
     123    e = pthread_mutex_init (&m, &a);
     124    if (e != 0)
     125      {
     126  #ifdef ENABLE_PI
     127        if (e == ENOTSUP)
     128  	{
     129  	  puts ("PI mutexes unsupported");
     130  	  return 0;
     131  	}
     132  #endif
     133        puts ("mutex_init failed");
     134        return 1;
     135      }
     136  
     137    if (pthread_barrier_init (&b, NULL, 2) != 0)
     138      {
     139        puts ("barrier_init failed");
     140        return 1;
     141      }
     142  
     143    e = pthread_mutex_unlock (&m);
     144    if (e == 0)
     145      {
     146        puts ("1st mutex_unlock succeeded");
     147        return 1;
     148      }
     149    else if (e != EPERM)
     150      {
     151        puts ("1st mutex_unlock error != EPERM");
     152        return 1;
     153      }
     154  
     155    if (pthread_mutex_lock (&m) != 0)
     156      {
     157        puts ("mutex_lock failed");
     158        return 1;
     159      }
     160  
     161    e = pthread_mutex_lock (&m);
     162    if (e == 0)
     163      {
     164        puts ("2nd mutex_lock succeeded");
     165        return 1;
     166      }
     167    else if (e != EDEADLK)
     168      {
     169        puts ("2nd mutex_lock error != EDEADLK");
     170        return 1;
     171      }
     172  
     173    pthread_t th;
     174    if (pthread_create (&th, NULL, tf, NULL) != 0)
     175      {
     176        puts ("create failed");
     177        return 1;
     178      }
     179  
     180    e = pthread_barrier_wait (&b);
     181    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     182      {
     183        puts ("1st barrier_wait failed");
     184        return 1;
     185      }
     186  
     187    if (pthread_mutex_unlock (&m) != 0)
     188      {
     189        puts ("2nd mutex_unlock failed");
     190        return 1;
     191      }
     192  
     193    e = pthread_mutex_unlock (&m);
     194    if (e == 0)
     195      {
     196        puts ("3rd mutex_unlock succeeded");
     197        return 1;
     198      }
     199    else if (e != EPERM)
     200      {
     201        puts ("3rd mutex_unlock error != EPERM");
     202        return 1;
     203      }
     204  
     205    e = pthread_barrier_wait (&b);
     206    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     207      {
     208        puts ("2nd barrier_wait failed");
     209        return 1;
     210      }
     211  
     212    if (pthread_join (th, NULL) != 0)
     213      {
     214        puts ("join failed");
     215        return 1;
     216      }
     217  
     218    if (pthread_mutex_destroy (&m) != 0)
     219      {
     220        puts ("mutex_destroy failed");
     221        return 1;
     222      }
     223  
     224    if (pthread_barrier_destroy (&b) != 0)
     225      {
     226        puts ("barrier_destroy failed");
     227        return 1;
     228      }
     229  
     230    if (pthread_mutexattr_destroy (&a) != 0)
     231      {
     232        puts ("mutexattr_destroy failed");
     233        return 1;
     234      }
     235  
     236    return 0;
     237  }
     238  
     239  #define TEST_FUNCTION do_test ()
     240  #include "../test-skeleton.c"