(root)/
glibc-2.38/
sysdeps/
pthread/
tst-mutex7.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  #include <time.h>
      23  
      24  /* This test is a template for other tests to use.  Other tests define
      25     the following macros to change the behaviour of the template test.
      26     The test is very simple, it configures N threads given the parameters
      27     below and then proceeds to go through mutex lock and unlock
      28     operations in each thread as described before for the thread
      29     function.  */
      30  #ifndef TYPE
      31  # define TYPE PTHREAD_MUTEX_DEFAULT
      32  #endif
      33  #ifndef ROBUST
      34  # define ROBUST PTHREAD_MUTEX_STALLED
      35  #endif
      36  #ifndef DELAY_NSEC
      37  # define DELAY_NSEC 11000
      38  #endif
      39  #ifndef ROUNDS
      40  # define ROUNDS 1000
      41  #endif
      42  #ifndef N
      43  # define N 100
      44  #endif
      45  
      46  static pthread_mutex_t lock;
      47  
      48  /* Each thread locks and the subsequently unlocks the lock, yielding
      49     the smallest critical section possible.  After the unlock the thread
      50     waits DELAY_NSEC nanoseconds before doing the lock and unlock again.
      51     Every thread does this ROUNDS times.  The lock and unlock are
      52     checked for errors.  */
      53  static void *
      54  tf (void *arg)
      55  {
      56    int nr = (long int) arg;
      57    int cnt;
      58    struct timespec ts = { .tv_sec = 0, .tv_nsec = DELAY_NSEC };
      59  
      60    for (cnt = 0; cnt < ROUNDS; ++cnt)
      61      {
      62        if (pthread_mutex_lock (&lock) != 0)
      63  	{
      64  	  printf ("thread %d: failed to get the lock\n", nr);
      65  	  return (void *) 1l;
      66  	}
      67  
      68        if (pthread_mutex_unlock (&lock) != 0)
      69  	{
      70  	  printf ("thread %d: failed to release the lock\n", nr);
      71  	  return (void *) 1l;
      72  	}
      73  
      74        if ((ts.tv_sec > 0) || (ts.tv_nsec > 0))
      75  	nanosleep (&ts, NULL);
      76      }
      77  
      78    return NULL;
      79  }
      80  
      81  /* Setup and run N threads, where each thread does as described
      82     in the above thread function.  The threads are given a minimal 1MiB
      83     stack since they don't do anything between the lock and unlock.  */
      84  static int
      85  do_test (void)
      86  {
      87    pthread_mutexattr_t a;
      88  
      89    if (pthread_mutexattr_init (&a) != 0)
      90      {
      91        puts ("mutexattr_init failed");
      92        exit (1);
      93      }
      94  
      95    if (pthread_mutexattr_settype (&a, TYPE) != 0)
      96      {
      97        puts ("mutexattr_settype failed");
      98        exit (1);
      99      }
     100  
     101    if (pthread_mutexattr_setrobust (&a, ROBUST) != 0)
     102      {
     103        puts ("mutexattr_setrobust failed");
     104        exit (1);
     105      }
     106  
     107  #ifdef ENABLE_PI
     108    if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
     109      {
     110        puts ("pthread_mutexattr_setprotocol failed");
     111        return 1;
     112      }
     113  #endif
     114  
     115    int e = pthread_mutex_init (&lock, &a);
     116    if (e != 0)
     117      {
     118  #ifdef ENABLE_PI
     119        if (e == ENOTSUP)
     120  	{
     121  	  puts ("PI mutexes unsupported");
     122  	  return 0;
     123  	}
     124  #endif
     125        puts ("mutex_init failed");
     126        return 1;
     127      }
     128  
     129    if (pthread_mutexattr_destroy (&a) != 0)
     130      {
     131        puts ("mutexattr_destroy failed");
     132        return 1;
     133      }
     134  
     135    pthread_attr_t at;
     136    pthread_t th[N];
     137    int cnt;
     138  
     139    if (pthread_attr_init (&at) != 0)
     140      {
     141        puts ("attr_init failed");
     142        return 1;
     143      }
     144  
     145    if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
     146      {
     147        puts ("attr_setstacksize failed");
     148        return 1;
     149      }
     150  
     151    if (pthread_mutex_lock (&lock) != 0)
     152      {
     153        puts ("locking in parent failed");
     154        return 1;
     155      }
     156  
     157    for (cnt = 0; cnt < N; ++cnt)
     158      if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
     159        {
     160  	printf ("creating thread %d failed\n", cnt);
     161  	return 1;
     162        }
     163  
     164    if (pthread_attr_destroy (&at) != 0)
     165      {
     166        puts ("attr_destroy failed");
     167        return 1;
     168      }
     169  
     170    if (pthread_mutex_unlock (&lock) != 0)
     171      {
     172        puts ("unlocking in parent failed");
     173        return 1;
     174      }
     175  
     176    for (cnt = 0; cnt < N; ++cnt)
     177      if (pthread_join (th[cnt], NULL) != 0)
     178        {
     179  	printf ("joining thread %d failed\n", cnt);
     180  	return 1;
     181        }
     182  
     183    return 0;
     184  }
     185  
     186  #define TIMEOUT 60
     187  #define TEST_FUNCTION do_test ()
     188  #include "../test-skeleton.c"