(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cond18.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 <errno.h>
      19  #include <limits.h>
      20  #include <fcntl.h>
      21  #include <pthread.h>
      22  #include <stdbool.h>
      23  #include <stdlib.h>
      24  #include <stdio.h>
      25  #include <unistd.h>
      26  
      27  #include <support/xunistd.h>
      28  
      29  pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
      30  pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
      31  bool exiting;
      32  int fd, spins, nn;
      33  enum { count = 8 };		/* Number of worker threads.  */
      34  
      35  void *
      36  tf (void *id)
      37  {
      38    pthread_mutex_lock (&lock);
      39  
      40    if ((long) id == 0)
      41      {
      42        while (!exiting)
      43  	{
      44  	  if ((spins++ % 1000) == 0)
      45  	    xwrite (fd, ".", 1);
      46  	  pthread_mutex_unlock (&lock);
      47  
      48  	  pthread_mutex_lock (&lock);
      49  	  int njobs = rand () % (count + 1);
      50  	  nn = njobs;
      51  	  if ((rand () % 30) == 0)
      52  	    pthread_cond_broadcast (&cv);
      53  	  else
      54  	    while (njobs--)
      55  	      pthread_cond_signal (&cv);
      56  	}
      57  
      58        pthread_cond_broadcast (&cv);
      59      }
      60    else
      61      {
      62        while (!exiting)
      63  	{
      64  	  while (!nn && !exiting)
      65  	    pthread_cond_wait (&cv, &lock);
      66  	  --nn;
      67  	  pthread_mutex_unlock (&lock);
      68  
      69  	  pthread_mutex_lock (&lock);
      70  	}
      71      }
      72  
      73    pthread_mutex_unlock (&lock);
      74    return NULL;
      75  }
      76  
      77  int
      78  do_test (void)
      79  {
      80    fd = open ("/dev/null", O_WRONLY);
      81    if (fd < 0)
      82      {
      83        printf ("couldn't open /dev/null, %m\n");
      84        return 1;
      85      }
      86  
      87    pthread_t th[count + 1];
      88    pthread_attr_t attr;
      89    int i, ret, sz;
      90    pthread_attr_init (&attr);
      91    sz = sysconf (_SC_PAGESIZE);
      92  #ifdef PTHREAD_STACK_MIN
      93    if (sz < PTHREAD_STACK_MIN)
      94  	  sz = PTHREAD_STACK_MIN;
      95  #endif
      96    pthread_attr_setstacksize (&attr, sz);
      97  
      98    for (i = 0; i <= count; ++i)
      99      if ((ret = pthread_create (&th[i], &attr, tf, (void *) (long) i)) != 0)
     100        {
     101  	errno = ret;
     102  	printf ("pthread_create %d failed: %m\n", i);
     103  	return 1;
     104        }
     105  
     106    struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
     107    while (nanosleep (&ts, &ts) != 0);
     108  
     109    pthread_mutex_lock (&lock);
     110    exiting = true;
     111    pthread_mutex_unlock (&lock);
     112  
     113    for (i = 0; i < count; ++i)
     114      pthread_join (th[i], NULL);
     115  
     116    close (fd);
     117    return 0;
     118  }
     119  
     120  #define TEST_FUNCTION do_test ()
     121  #define TIMEOUT 40
     122  #include "../test-skeleton.c"