(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cond24.c
       1  /* Verify that condition variables synchronized by PI mutexes don't hang.
       2     Copyright (C) 2012-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <pthread.h>
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <errno.h>
      24  #include <sys/types.h>
      25  #include <sys/syscall.h>
      26  #include <unistd.h>
      27  #include <sys/time.h>
      28  #include <time.h>
      29  
      30  #define THREADS_NUM 5
      31  #define MAXITER 50000
      32  
      33  static pthread_mutex_t mutex;
      34  static pthread_mutexattr_t mutex_attr;
      35  static pthread_cond_t cond;
      36  static pthread_t threads[THREADS_NUM];
      37  static int pending = 0;
      38  
      39  typedef void * (*threadfunc) (void *);
      40  
      41  void *
      42  thread_fun_timed (void *arg)
      43  {
      44    int *ret = arg;
      45    int rv, i;
      46  
      47    printf ("Started thread_fun_timed[%d]\n", *ret);
      48  
      49    for (i = 0; i < MAXITER / THREADS_NUM; i++)
      50      {
      51        rv = pthread_mutex_lock (&mutex);
      52        if (rv)
      53          {
      54  	  printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
      55  	  *ret = 1;
      56  	  goto out;
      57  	}
      58  
      59        while (!pending)
      60  	{
      61  	  struct timespec ts;
      62  	  clock_gettime(CLOCK_REALTIME, &ts);
      63  	  ts.tv_sec += 20;
      64  	  rv = pthread_cond_timedwait (&cond, &mutex, &ts);
      65  
      66  	  /* There should be no timeout either.  */
      67  	  if (rv)
      68              {
      69  	      printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
      70  	      *ret = 1;
      71  	      goto out;
      72  	    }
      73  	}
      74  
      75        pending--;
      76  
      77        rv = pthread_mutex_unlock (&mutex);
      78        if (rv)
      79          {
      80  	  printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
      81  	  *ret = 1;
      82  	  goto out;
      83  	}
      84      }
      85  
      86    *ret = 0;
      87  
      88  out:
      89    return ret;
      90  }
      91  
      92  void *
      93  thread_fun (void *arg)
      94  {
      95    int *ret = arg;
      96    int rv, i;
      97  
      98    printf ("Started thread_fun[%d]\n", *ret);
      99  
     100    for (i = 0; i < MAXITER / THREADS_NUM; i++)
     101      {
     102        rv = pthread_mutex_lock (&mutex);
     103        if (rv)
     104          {
     105  	  printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
     106  	  *ret = 1;
     107  	  goto out;
     108  	}
     109  
     110        while (!pending)
     111  	{
     112  	  rv = pthread_cond_wait (&cond, &mutex);
     113  
     114  	  if (rv)
     115              {
     116  	      printf ("pthread_cond_wait: %s(%d)\n", strerror (rv), rv);
     117  	      *ret = 1;
     118  	      goto out;
     119  	    }
     120  	}
     121  
     122        pending--;
     123  
     124        rv = pthread_mutex_unlock (&mutex);
     125        if (rv)
     126          {
     127  	  printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
     128  	  *ret = 1;
     129  	  goto out;
     130  	}
     131      }
     132  
     133    *ret = 0;
     134  
     135  out:
     136    return ret;
     137  }
     138  
     139  static int
     140  do_test_wait (threadfunc f)
     141  {
     142    int i;
     143    int rv;
     144    int counter = 0;
     145    int retval[THREADS_NUM];
     146  
     147    puts ("Starting test");
     148  
     149    rv = pthread_mutexattr_init (&mutex_attr);
     150    if (rv)
     151      {
     152        printf ("pthread_mutexattr_init: %s(%d)\n", strerror (rv), rv);
     153        return 1;
     154      }
     155  
     156    rv = pthread_mutexattr_setprotocol (&mutex_attr, PTHREAD_PRIO_INHERIT);
     157    if (rv)
     158      {
     159        printf ("pthread_mutexattr_setprotocol: %s(%d)\n", strerror (rv), rv);
     160        return 1;
     161      }
     162  
     163    rv = pthread_mutex_init (&mutex, &mutex_attr);
     164    if (rv)
     165      {
     166        printf ("pthread_mutex_init: %s(%d)\n", strerror (rv), rv);
     167        return 1;
     168      }
     169  
     170    rv = pthread_cond_init (&cond, NULL);
     171    if (rv)
     172      {
     173        printf ("pthread_cond_init: %s(%d)\n", strerror (rv), rv);
     174        return 1;
     175      }
     176  
     177    for (i = 0; i < THREADS_NUM; i++)
     178      {
     179        retval[i] = i;
     180        rv = pthread_create (&threads[i], NULL, f, &retval[i]);
     181        if (rv)
     182          {
     183            printf ("pthread_create: %s(%d)\n", strerror (rv), rv);
     184            return 1;
     185          }
     186      }
     187  
     188    for (; counter < MAXITER; counter++)
     189      {
     190        rv = pthread_mutex_lock (&mutex);
     191        if (rv)
     192          {
     193            printf ("pthread_mutex_lock: %s(%d)\n", strerror (rv), rv);
     194            return 1;
     195          }
     196  
     197        if (!(counter % 100))
     198  	printf ("counter: %d\n", counter);
     199        pending += 1;
     200  
     201        rv = pthread_cond_signal (&cond);
     202        if (rv)
     203          {
     204            printf ("pthread_cond_signal: %s(%d)\n", strerror (rv), rv);
     205            return 1;
     206          }
     207  
     208        rv = pthread_mutex_unlock (&mutex);
     209        if (rv)
     210          {
     211            printf ("pthread_mutex_unlock: %s(%d)\n", strerror (rv), rv);
     212            return 1;
     213          }
     214      }
     215  
     216    for (i = 0; i < THREADS_NUM; i++)
     217      {
     218        void *ret;
     219        rv = pthread_join (threads[i], &ret);
     220        if (rv)
     221          {
     222            printf ("pthread_join: %s(%d)\n", strerror (rv), rv);
     223            return 1;
     224          }
     225        if (ret && *(int *)ret)
     226          {
     227  	  printf ("Thread %d returned with an error\n", i);
     228  	  return 1;
     229  	}
     230      }
     231  
     232    return 0;
     233  }
     234  
     235  static int
     236  do_test (void)
     237  {
     238    puts ("Testing pthread_cond_wait");
     239    int ret = do_test_wait (thread_fun);
     240    if (ret)
     241      return ret;
     242  
     243    puts ("Testing pthread_cond_timedwait");
     244    return do_test_wait (thread_fun_timed);
     245  }
     246  
     247  #define TEST_FUNCTION do_test ()
     248  #include "../test-skeleton.c"