(root)/
glibc-2.38/
sysdeps/
pthread/
tst-barrier3.c
       1  /* Test of POSIX barriers.
       2     Copyright (C) 2002-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  
      24  #define NTHREADS 20
      25  
      26  #define ROUNDS 20
      27  
      28  static pthread_barrier_t barriers[NTHREADS];
      29  
      30  static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
      31  static int counters[NTHREADS];
      32  static int serial[NTHREADS];
      33  
      34  static void *
      35  worker (void *arg)
      36  {
      37    void *result = NULL;
      38    int nr = (long int) arg;
      39    int i;
      40  
      41    for (i = 0; i < ROUNDS; ++i)
      42      {
      43        int j;
      44        int retval;
      45  
      46        if (nr == 0)
      47  	{
      48  	  memset (counters, '\0', sizeof (counters));
      49  	  memset (serial, '\0', sizeof (serial));
      50  	}
      51  
      52        retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
      53        if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
      54  	{
      55  	  printf ("thread %d failed to wait for all the others\n", nr);
      56  	  result = (void *) 1;
      57  	}
      58  
      59        for (j = nr; j < NTHREADS; ++j)
      60  	{
      61  	  /* Increment the counter for this round.  */
      62  	  pthread_mutex_lock (&lock);
      63  	  ++counters[j];
      64  	  pthread_mutex_unlock (&lock);
      65  
      66  	  /* Wait for the rest.  */
      67  	  retval = pthread_barrier_wait (&barriers[j]);
      68  
      69  	  /* Test the result.  */
      70  	  if (nr == 0 && counters[j] != j + 1)
      71  	    {
      72  	      printf ("barrier in round %d released but count is %d\n",
      73  		      j, counters[j]);
      74  	      result = (void *) 1;
      75  	    }
      76  
      77  	  if (retval != 0)
      78  	    {
      79  	      if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
      80  		{
      81  		  printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
      82  			  nr, j);
      83  		  result = (void *) 1;
      84  		}
      85  	      else
      86  		{
      87  		  pthread_mutex_lock (&lock);
      88  		  ++serial[j];
      89  		  pthread_mutex_unlock (&lock);
      90  		}
      91  	    }
      92  
      93  	  /* Wait for the rest again.  */
      94  	  retval = pthread_barrier_wait (&barriers[j]);
      95  
      96  	  /* Now we can check whether exactly one thread was serializing.  */
      97  	  if (nr == 0 && serial[j] != 1)
      98  	    {
      99  	      printf ("not exactly one serial thread in round %d\n", j);
     100  	      result = (void *) 1;
     101  	    }
     102  	}
     103      }
     104  
     105    return result;
     106  }
     107  
     108  
     109  #define TEST_FUNCTION do_test ()
     110  #define TIMEOUT 60
     111  static int
     112  do_test (void)
     113  {
     114    pthread_t threads[NTHREADS];
     115    int i;
     116    void *res;
     117    int result = 0;
     118  
     119    /* Initialized the barrier variables.  */
     120    for (i = 0; i < NTHREADS; ++i)
     121      if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
     122        {
     123  	printf ("Failed to initialize barrier %d\n", i);
     124  	exit (1);
     125        }
     126  
     127    /* Start the threads.  */
     128    for (i = 0; i < NTHREADS; ++i)
     129      if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
     130        {
     131  	printf ("Failed to start thread %d\n", i);
     132  	exit (1);
     133        }
     134  
     135    /* And wait for them.  */
     136    for (i = 0; i < NTHREADS; ++i)
     137      if (pthread_join (threads[i], &res) != 0 || res != NULL)
     138        {
     139  	printf ("thread %d returned a failure\n", i);
     140  	result = 1;
     141        }
     142      else
     143        printf ("joined threads %d\n", i);
     144  
     145    if (result == 0)
     146      puts ("all OK");
     147  
     148    return result;
     149  }
     150  
     151  #include "../test-skeleton.c"