(root)/
glibc-2.38/
sysdeps/
pthread/
tst-mutex3.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 ("1st mutex_unlock in child succeeded");
      35        exit (1);
      36      }
      37    if (e != EPERM)
      38      {
      39        puts ("1st mutex_unlock in child didn't return EPERM");
      40        exit (1);
      41      }
      42  
      43    e = pthread_mutex_trylock (&m);
      44    if (e == 0)
      45      {
      46        puts ("mutex_trylock in second thread succeeded");
      47        exit (1);
      48      }
      49    if (e != EBUSY)
      50      {
      51        puts ("mutex_trylock returned wrong value");
      52        exit (1);
      53      }
      54  
      55    e = pthread_barrier_wait (&b);
      56    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      57      {
      58        puts ("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 ("barrier_wait failed");
      66        exit (1);
      67      }
      68  
      69    e = pthread_mutex_unlock (&m);
      70    if (e == 0)
      71      {
      72        puts ("2nd mutex_unlock in child succeeded");
      73        exit (1);
      74      }
      75    if (e != EPERM)
      76      {
      77        puts ("2nd mutex_unlock in child didn't return EPERM");
      78        exit (1);
      79      }
      80  
      81    if (pthread_mutex_trylock (&m) != 0)
      82      {
      83        puts ("2nd mutex_trylock in second thread failed");
      84        exit (1);
      85      }
      86  
      87    if (pthread_mutex_unlock (&m) != 0)
      88      {
      89        puts ("3rd mutex_unlock in second thread 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  
     102    if (pthread_mutexattr_init (&a) != 0)
     103      {
     104        puts ("mutexattr_init failed");
     105        return 1;
     106      }
     107  
     108    if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
     109      {
     110        puts ("mutexattr_settype failed");
     111        return 1;
     112      }
     113  
     114  #ifdef ENABLE_PI
     115    if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
     116      {
     117        puts ("pthread_mutexattr_setprotocol failed");
     118        return 1;
     119      }
     120  #endif
     121  
     122    int e;
     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    if (pthread_mutex_lock (&m) != 0)
     144      {
     145        puts ("mutex_lock failed");
     146        return 1;
     147      }
     148  
     149    if (pthread_mutex_lock (&m) != 0)
     150      {
     151        puts ("2nd mutex_lock failed");
     152        return 1;
     153      }
     154  
     155    if (pthread_mutex_trylock (&m) != 0)
     156      {
     157        puts ("1st trylock failed");
     158        return 1;
     159      }
     160  
     161    if (pthread_mutex_unlock (&m) != 0)
     162      {
     163        puts ("mutex_unlock failed");
     164        return 1;
     165      }
     166  
     167    if (pthread_mutex_unlock (&m) != 0)
     168      {
     169        puts ("2nd mutex_unlock failed");
     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 ("barrier_wait failed");
     184        return 1;
     185      }
     186  
     187    if (pthread_mutex_unlock (&m) != 0)
     188      {
     189        puts ("3rd mutex_unlock failed");
     190        return 1;
     191      }
     192  
     193    e = pthread_mutex_unlock (&m);
     194    if (e == 0)
     195      {
     196        puts ("4th mutex_unlock succeeded");
     197        return 1;
     198      }
     199    if (e != EPERM)
     200      {
     201        puts ("4th mutex_unlock didn't return EPERM");
     202        return 1;
     203      }
     204  
     205    e = pthread_barrier_wait (&b);
     206    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     207      {
     208        puts ("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_barrier_destroy (&b) != 0)
     219      {
     220        puts ("barrier_destroy failed");
     221        return 1;
     222      }
     223  
     224    if (pthread_mutex_destroy (&m) != 0)
     225      {
     226        puts ("mutex_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"