(root)/
glibc-2.38/
nptl/
tst-barrier5.c
       1  /* This tests the barrier reset mechanism.
       2     Copyright (C) 2004-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 <errno.h>
      20  #include <pthread.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <internaltypes.h>
      24  
      25  
      26  static pthread_barrier_t b1;
      27  static pthread_barrier_t b2;
      28  
      29  
      30  #define N 20
      31  #define ROUNDS_PER_RUN 20
      32  #define START ((BARRIER_IN_THRESHOLD / N - ROUNDS_PER_RUN / 2) * N)
      33  
      34  static void *
      35  tf (void *arg)
      36  {
      37    int runs = 0;
      38  
      39    while (runs++ < 30)
      40      {
      41        /* In each run, we execute a number of rounds and initialize the barrier
      42  	 so that we will go over the reset threshold with those rounds.  */
      43        for (int rounds = 0; rounds < ROUNDS_PER_RUN; rounds++)
      44  	pthread_barrier_wait (&b1);
      45  
      46        if (pthread_barrier_wait (&b1) == PTHREAD_BARRIER_SERIAL_THREAD)
      47  	{
      48  	  pthread_barrier_destroy (&b1);
      49  	  if (pthread_barrier_init (&b1, NULL, N) != 0)
      50  	    {
      51  	      puts ("tf: 1st barrier_init failed");
      52  	      exit (1);
      53  	    }
      54  	  puts ("b1 reinitialized");
      55  	  /* Trigger a reset.  */
      56  	  struct pthread_barrier *bar = (struct pthread_barrier *) &b1;
      57  	  bar->in = START;
      58  	  bar->out = START;
      59  	  /* We deliberately don't set bar->current_round so that we also
      60  	     test whether the helping for the updates of current_round
      61  	     works correctly.  */
      62  	}
      63  
      64        /* Same as above, just for b2.  */
      65        for (int rounds = 0; rounds < ROUNDS_PER_RUN; rounds++)
      66  	pthread_barrier_wait (&b2);
      67  
      68        if (pthread_barrier_wait (&b2) == PTHREAD_BARRIER_SERIAL_THREAD)
      69  	{
      70  	  pthread_barrier_destroy (&b2);
      71  	  if (pthread_barrier_init (&b2, NULL, N) != 0)
      72  	    {
      73  	      puts ("tf: 2nd barrier_init failed");
      74  	      exit (1);
      75  	    }
      76  	  puts ("b2 reinitialized");
      77  	  /* Trigger a reset.  See above.  */
      78  	  struct pthread_barrier *bar = (struct pthread_barrier *) &b2;
      79  	  bar->in = START;
      80  	  bar->out = START;
      81  	}
      82      }
      83  
      84    return NULL;
      85  }
      86  
      87  
      88  static int
      89  do_test (void)
      90  {
      91    pthread_attr_t at;
      92    int cnt;
      93  
      94    if (pthread_attr_init (&at) != 0)
      95      {
      96        puts ("attr_init failed");
      97        return 1;
      98      }
      99  
     100    if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
     101      {
     102        puts ("attr_setstacksize failed");
     103        return 1;
     104      }
     105  
     106    if (pthread_barrier_init (&b1, NULL, N) != 0)
     107      {
     108        puts ("1st barrier_init failed");
     109        return 1;
     110      }
     111  
     112    if (pthread_barrier_init (&b2, NULL, N) != 0)
     113      {
     114        puts ("2nd barrier_init failed");
     115        return 1;
     116      }
     117  
     118    pthread_t th[N - 1];
     119    for (cnt = 0; cnt < N - 1; ++cnt)
     120      if (pthread_create (&th[cnt], &at, tf, NULL) != 0)
     121        {
     122  	puts ("pthread_create failed");
     123  	return 1;
     124        }
     125  
     126    if (pthread_attr_destroy (&at) != 0)
     127      {
     128        puts ("attr_destroy failed");
     129        return 1;
     130      }
     131  
     132    tf (NULL);
     133  
     134    for (cnt = 0; cnt < N - 1; ++cnt)
     135      if (pthread_join (th[cnt], NULL) != 0)
     136        {
     137  	puts ("pthread_join failed");
     138  	return 1;
     139        }
     140  
     141    return 0;
     142  }
     143  
     144  #define TEST_FUNCTION do_test ()
     145  #include "../test-skeleton.c"