(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cond20.c
       1  /* Copyright (C) 2004-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 <pthread.h>
      19  #include <stdio.h>
      20  #include <stdlib.h>
      21  #include <string.h>
      22  #include <unistd.h>
      23  
      24  #define N 10
      25  #define ROUNDS 1000
      26  static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
      27  static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
      28  static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
      29  static pthread_barrier_t b;
      30  static int count;
      31  
      32  static void *
      33  tf (void *p)
      34  {
      35    int i;
      36    for (i = 0; i < ROUNDS; ++i)
      37      {
      38        pthread_mutex_lock (&mut);
      39  
      40        if (++count == N)
      41  	pthread_cond_signal (&cond2);
      42  
      43  #ifdef TIMED
      44        struct timeval tv;
      45        gettimeofday (&tv, NULL);
      46        struct timespec ts;
      47        /* Wait three seconds.  */
      48        ts.tv_sec = tv.tv_sec + 3;
      49        ts.tv_nsec = tv.tv_usec * 1000;
      50        pthread_cond_timedwait (&cond, &mut, &ts);
      51  #else
      52        pthread_cond_wait (&cond, &mut);
      53  #endif
      54  
      55        pthread_mutex_unlock (&mut);
      56  
      57        int err = pthread_barrier_wait (&b);
      58        if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
      59  	{
      60  	  puts ("child: barrier_wait failed");
      61  	  exit (1);
      62  	}
      63  
      64        err = pthread_barrier_wait (&b);
      65        if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
      66  	{
      67  	  puts ("child: barrier_wait failed");
      68  	  exit (1);
      69  	}
      70      }
      71  
      72    return NULL;
      73  }
      74  
      75  
      76  static int
      77  do_test (void)
      78  {
      79    if (pthread_barrier_init (&b, NULL, N + 1) != 0)
      80      {
      81        puts ("barrier_init failed");
      82        return 1;
      83      }
      84  
      85    pthread_mutex_lock (&mut);
      86  
      87    int i, j, err;
      88    pthread_t th[N];
      89    for (i = 0; i < N; ++i)
      90      if ((err = pthread_create (&th[i], NULL, tf, NULL)) != 0)
      91        {
      92  	printf ("cannot create thread %d: %s\n", i, strerror (err));
      93  	return 1;
      94        }
      95  
      96    for (i = 0; i < ROUNDS; ++i)
      97      {
      98        /* Make sure we discard spurious wake-ups.  */
      99        do
     100  	pthread_cond_wait (&cond2, &mut);
     101        while (count != N);
     102  
     103        if (i & 1)
     104          pthread_mutex_unlock (&mut);
     105  
     106        if (i & 2)
     107  	pthread_cond_broadcast (&cond);
     108        else if (i & 4)
     109  	for (j = 0; j < N; ++j)
     110  	  pthread_cond_signal (&cond);
     111        else
     112  	{
     113  	  for (j = 0; j < (i / 8) % N; ++j)
     114  	    pthread_cond_signal (&cond);
     115  	  pthread_cond_broadcast (&cond);
     116  	}
     117  
     118        if ((i & 1) == 0)
     119          pthread_mutex_unlock (&mut);
     120  
     121        err = pthread_cond_destroy (&cond);
     122        if (err)
     123  	{
     124  	  printf ("pthread_cond_destroy failed: %s\n", strerror (err));
     125  	  return 1;
     126  	}
     127  
     128        /* Now clobber the cond variable which has been successfully
     129           destroyed above.  */
     130        memset (&cond, (char) i, sizeof (cond));
     131  
     132        err = pthread_barrier_wait (&b);
     133        if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
     134  	{
     135  	  puts ("parent: barrier_wait failed");
     136  	  return 1;
     137  	}
     138  
     139        pthread_mutex_lock (&mut);
     140  
     141        err = pthread_barrier_wait (&b);
     142        if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
     143  	{
     144  	  puts ("parent: barrier_wait failed");
     145  	  return 1;
     146  	}
     147  
     148        count = 0;
     149        err = pthread_cond_init (&cond, NULL);
     150        if (err)
     151  	{
     152  	  printf ("pthread_cond_init failed: %s\n", strerror (err));
     153  	  return 1;
     154  	}
     155      }
     156  
     157    for (i = 0; i < N; ++i)
     158      if ((err = pthread_join (th[i], NULL)) != 0)
     159        {
     160  	printf ("failed to join thread %d: %s\n", i, strerror (err));
     161  	return 1;
     162        }
     163  
     164    puts ("done");
     165  
     166    return 0;
     167  }
     168  
     169  
     170  #define TEST_FUNCTION do_test ()
     171  #include "../test-skeleton.c"