(root)/
glibc-2.38/
sysdeps/
pthread/
tst-pt-tls2.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 <signal.h>
      21  #include <semaphore.h>
      22  #include <stdio.h>
      23  #include <stdlib.h>
      24  #include <unistd.h>
      25  
      26  
      27  #define N 10
      28  static pthread_t th[N];
      29  
      30  
      31  static int do_test (void);
      32  
      33  #define TEST_FUNCTION do_test ()
      34  #include "../test-skeleton.c"
      35  
      36  #define CB(n) \
      37  static void								      \
      38  cb##n (void)								      \
      39  {									      \
      40    if (th[n] != pthread_self ())						      \
      41      {									      \
      42        write_message ("wrong callback\n");				      \
      43        _exit (1);							      \
      44      }									      \
      45  }
      46  CB (0)
      47  CB (1)
      48  CB (2)
      49  CB (3)
      50  CB (4)
      51  CB (5)
      52  CB (6)
      53  CB (7)
      54  CB (8)
      55  CB (9)
      56  static void (*cbs[]) (void) =
      57  {
      58    cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
      59  };
      60  
      61  
      62  static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
      63  
      64  
      65  static sem_t s;
      66  
      67  
      68  #define THE_SIG SIGUSR1
      69  static void
      70  handler (int sig)
      71  {
      72    if (sig != THE_SIG)
      73      {
      74        write_message ("wrong signal\n");
      75        _exit (1);
      76      }
      77  
      78    fp ();
      79  
      80    if (sem_post (&s) != 0)
      81      {
      82        write_message ("sem_post failed\n");
      83        _exit (1);
      84      }
      85  }
      86  
      87  
      88  static pthread_barrier_t b;
      89  
      90  #define TOTAL_SIGS 1000
      91  static int nsigs;
      92  
      93  
      94  static void *
      95  tf (void *arg)
      96  {
      97    fp = arg;
      98  
      99    pthread_barrier_wait (&b);
     100  
     101    pthread_barrier_wait (&b);
     102  
     103    if (nsigs != TOTAL_SIGS)
     104      {
     105        puts ("barrier_wait prematurely returns");
     106        exit (1);
     107      }
     108  
     109    return NULL;
     110  }
     111  
     112  
     113  int
     114  do_test (void)
     115  {
     116    if (pthread_barrier_init (&b, NULL, N + 1) != 0)
     117      {
     118        puts ("barrier_init failed");
     119        exit (1);
     120      }
     121  
     122    if (sem_init (&s, 0, 0) != 0)
     123      {
     124        puts ("sem_init failed");
     125        exit (1);
     126      }
     127  
     128    struct sigaction sa;
     129    sa.sa_handler = handler;
     130    sigemptyset (&sa.sa_mask);
     131    sa.sa_flags = 0;
     132    if (sigaction (THE_SIG, &sa, NULL) != 0)
     133      {
     134        puts ("sigaction failed");
     135        exit (1);
     136      }
     137  
     138    pthread_attr_t a;
     139  
     140    if (pthread_attr_init (&a) != 0)
     141      {
     142        puts ("attr_init failed");
     143        exit (1);
     144      }
     145  
     146    if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
     147      {
     148        puts ("attr_setstacksize failed");
     149        return 1;
     150      }
     151  
     152    int i;
     153    for (i = 0; i < N; ++i)
     154      if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
     155        {
     156  	puts ("pthread_create failed");
     157  	exit (1);
     158        }
     159  
     160    if (pthread_attr_destroy (&a) != 0)
     161      {
     162        puts ("attr_destroy failed");
     163        exit (1);
     164      }
     165  
     166    pthread_barrier_wait (&b);
     167  
     168    sigset_t ss;
     169    sigemptyset (&ss);
     170    sigaddset (&ss, THE_SIG);
     171    if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
     172      {
     173        puts ("pthread_sigmask failed");
     174        exit (1);
     175      }
     176  
     177    /* Start sending signals.  */
     178    for (i = 0; i < TOTAL_SIGS; ++i)
     179      {
     180        if (kill (getpid (), THE_SIG) != 0)
     181  	{
     182  	  puts ("kill failed");
     183  	  exit (1);
     184  	}
     185  
     186        if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
     187  	{
     188  	  puts ("sem_wait failed");
     189  	  exit (1);
     190  	}
     191  
     192        ++nsigs;
     193      }
     194  
     195    pthread_barrier_wait (&b);
     196  
     197    for (i = 0; i < N; ++i)
     198      if (pthread_join (th[i], NULL) != 0)
     199        {
     200  	puts ("join failed");
     201  	exit (1);
     202        }
     203  
     204    return 0;
     205  }