(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cnd-broadcast.c
       1  /* C11 threads condition broadcast variable tests.
       2     Copyright (C) 2018-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 <threads.h>
      20  #include <stdbool.h>
      21  #include <stdio.h>
      22  #include <unistd.h>
      23  
      24  #include <support/check.h>
      25  
      26  /* Condition variable where child threads will wait.  */
      27  static cnd_t cond;
      28  
      29  /* Mutex to control wait on cond.  */
      30  static mtx_t mutex;
      31  
      32  /* Number of threads which have entered the cnd_wait region.  */
      33  static unsigned int waiting_threads;
      34  
      35  /* Code executed by each thread.  */
      36  static int
      37  child_wait (void* data)
      38  {
      39    /* Wait until parent thread sends broadcast here.  */
      40    mtx_lock (&mutex);
      41    ++waiting_threads;
      42    cnd_wait (&cond, &mutex);
      43    mtx_unlock (&mutex);
      44  
      45    thrd_exit (thrd_success);
      46  }
      47  
      48  #define N 5
      49  
      50  static int
      51  do_test (void)
      52  {
      53    thrd_t ids[N];
      54    unsigned char i;
      55  
      56    if (cnd_init (&cond) != thrd_success)
      57      FAIL_EXIT1 ("cnd_init failed");
      58    if (mtx_init (&mutex, mtx_plain) != thrd_success)
      59      FAIL_EXIT1 ("mtx_init failed");
      60  
      61    /* Create N new threads.  */
      62    for (i = 0; i < N; ++i)
      63      {
      64        if (thrd_create (&ids[i], child_wait, NULL) != thrd_success)
      65  	FAIL_EXIT1 ("thrd_create failed");
      66      }
      67  
      68    /* Wait for other threads to reach their wait func.  */
      69    while (true)
      70      {
      71        mtx_lock (&mutex);
      72        TEST_VERIFY (waiting_threads <= N);
      73        bool done_waiting = waiting_threads == N;
      74        mtx_unlock (&mutex);
      75        if (done_waiting)
      76  	break;
      77        thrd_sleep (&((struct timespec){.tv_nsec = 100 * 1000 * 1000}), NULL);
      78      }
      79  
      80    mtx_lock (&mutex);
      81    if (cnd_broadcast (&cond) != thrd_success)
      82      FAIL_EXIT1 ("cnd_broadcast failed");
      83    mtx_unlock (&mutex);
      84  
      85    for (i = 0; i < N; ++i)
      86      {
      87        if (thrd_join (ids[i], NULL) != thrd_success)
      88  	FAIL_EXIT1 ("thrd_join failed");
      89      }
      90  
      91    mtx_destroy (&mutex);
      92    cnd_destroy (&cond);
      93  
      94    return 0;
      95  }
      96  
      97  #include <support/test-driver.c>