(root)/
glibc-2.38/
sysdeps/
pthread/
tst-kill6.c
       1  /* Copyright (C) 2003-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 <pthread.h>
      20  #include <semaphore.h>
      21  #include <signal.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <unistd.h>
      25  
      26  
      27  static int do_test (void);
      28  
      29  #define TEST_FUNCTION do_test ()
      30  #include "../test-skeleton.c"
      31  
      32  static pthread_t receiver;
      33  static sem_t sem;
      34  static pthread_barrier_t b;
      35  
      36  static void
      37  handler (int sig)
      38  {
      39    if (sig != SIGUSR1)
      40      {
      41        write_message ("wrong signal\n");
      42        _exit (1);
      43      }
      44  
      45    if (pthread_self () != receiver)
      46      {
      47        write_message ("not the intended receiver\n");
      48        _exit (1);
      49      }
      50  
      51    if (sem_post (&sem) != 0)
      52      {
      53        write_message ("sem_post failed\n");
      54        _exit (1);
      55      }
      56  }
      57  
      58  
      59  static void *
      60  tf (void *a)
      61  {
      62    int e = pthread_barrier_wait (&b);
      63    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
      64      {
      65        puts ("child: barrier_wait failed");
      66        exit (1);
      67      }
      68  
      69    return NULL;
      70  }
      71  
      72  
      73  int
      74  do_test (void)
      75  {
      76    struct sigaction sa;
      77    sigemptyset (&sa.sa_mask);
      78    sa.sa_flags = 0;
      79    sa.sa_handler = handler;
      80    if (sigaction (SIGUSR1, &sa, NULL) != 0)
      81      {
      82        puts ("sigaction failed");
      83        exit (1);
      84      }
      85  
      86  #define N 20
      87  
      88    if (pthread_barrier_init (&b, NULL, N + 1) != 0)
      89      {
      90        puts ("barrier_init failed");
      91        exit (1);
      92      }
      93  
      94    pthread_attr_t a;
      95  
      96    if (pthread_attr_init (&a) != 0)
      97      {
      98        puts ("attr_init failed");
      99        exit (1);
     100      }
     101  
     102    if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
     103      {
     104        puts ("attr_setstacksize failed");
     105        return 1;
     106      }
     107  
     108    pthread_t th[N];
     109    int i;
     110    for (i = 0; i < N; ++i)
     111      if (pthread_create (&th[i], &a, tf, NULL) != 0)
     112        {
     113  	puts ("create failed");
     114  	exit (1);
     115        }
     116  
     117    if (pthread_attr_destroy (&a) != 0)
     118      {
     119        puts ("attr_destroy failed");
     120        exit (1);
     121      }
     122  
     123    if (sem_init (&sem, 0, 0) != 0)
     124      {
     125        puts ("sem_init failed");
     126        exit (1);
     127      }
     128  
     129    for (i = 0; i < N * 10; ++i)
     130      {
     131        receiver = th[i % N];
     132  
     133        if (pthread_kill (receiver, SIGUSR1) != 0)
     134  	{
     135  	  puts ("kill failed");
     136  	  exit (1);
     137  	}
     138  
     139        if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
     140  	{
     141  	  puts ("sem_wait failed");
     142  	  exit (1);
     143  	}
     144      }
     145  
     146    int e = pthread_barrier_wait (&b);
     147    if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     148      {
     149        puts ("barrier_wait failed");
     150        exit (1);
     151      }
     152  
     153    for (i = 0; i < N; ++i)
     154      if (pthread_join (th[i], NULL) != 0)
     155        {
     156  	puts ("join failed");
     157  	exit (1);
     158        }
     159  
     160    return 0;
     161  }