Back to index

glibc  2.9
tst-tls2.c
Go to the documentation of this file.
00001 /* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <pthread.h>
00022 #include <signal.h>
00023 #include <semaphore.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <unistd.h>
00027 
00028 #if HAVE___THREAD
00029 
00030 #define N 10
00031 static pthread_t th[N];
00032 
00033 
00034 #define CB(n) \
00035 static void                                                          \
00036 cb##n (void)                                                         \
00037 {                                                                    \
00038   if (th[n] != pthread_self ())                                             \
00039     {                                                                \
00040       write (STDOUT_FILENO, "wrong callback\n", 15);                        \
00041       _exit (1);                                                     \
00042     }                                                                \
00043 }
00044 CB (0)
00045 CB (1)
00046 CB (2)
00047 CB (3)
00048 CB (4)
00049 CB (5)
00050 CB (6)
00051 CB (7)
00052 CB (8)
00053 CB (9)
00054 static void (*cbs[]) (void) =
00055 {
00056   cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
00057 };
00058 
00059 
00060 static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
00061 
00062 
00063 static sem_t s;
00064 
00065 
00066 #define THE_SIG SIGUSR1
00067 static void
00068 handler (int sig)
00069 {
00070   if (sig != THE_SIG)
00071     {
00072       write (STDOUT_FILENO, "wrong signal\n", 13);
00073       _exit (1);
00074     }
00075 
00076   fp ();
00077 
00078   if (sem_post (&s) != 0)
00079     {
00080       write (STDOUT_FILENO, "sem_post failed\n", 16);
00081       _exit (1);
00082     }
00083 }
00084 
00085 
00086 static pthread_barrier_t b;
00087 
00088 #define TOTAL_SIGS 1000
00089 static int nsigs;
00090 
00091 
00092 static void *
00093 tf (void *arg)
00094 {
00095   fp = arg;
00096 
00097   pthread_barrier_wait (&b);
00098 
00099   pthread_barrier_wait (&b);
00100 
00101   if (nsigs != TOTAL_SIGS)
00102     {
00103       puts ("barrier_wait prematurely returns");
00104       exit (1);
00105     }
00106 
00107   return NULL;
00108 }
00109 #endif
00110 
00111 int
00112 do_test (void)
00113 {
00114 #if !HAVE___THREAD
00115 
00116   puts ("No __thread support in compiler, test skipped.");
00117 
00118   return 0;
00119 #else
00120 
00121   if (pthread_barrier_init (&b, NULL, N + 1) != 0)
00122     {
00123       puts ("barrier_init failed");
00124       exit (1);
00125     }
00126 
00127   if (sem_init (&s, 0, 0) != 0)
00128     {
00129       puts ("sem_init failed");
00130       exit (1);
00131     }
00132 
00133   struct sigaction sa;
00134   sa.sa_handler = handler;
00135   sigemptyset (&sa.sa_mask);
00136   sa.sa_flags = 0;
00137   if (sigaction (THE_SIG, &sa, NULL) != 0)
00138     {
00139       puts ("sigaction failed");
00140       exit (1);
00141     }
00142 
00143   pthread_attr_t a;
00144 
00145   if (pthread_attr_init (&a) != 0)
00146     {
00147       puts ("attr_init failed");
00148       exit (1);
00149     }
00150 
00151   if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
00152     {
00153       puts ("attr_setstacksize failed");
00154       return 1;
00155     }
00156 
00157   int i;
00158   for (i = 0; i < N; ++i)
00159     if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
00160       {
00161        puts ("pthread_create failed");
00162        exit (1);
00163       }
00164 
00165   if (pthread_attr_destroy (&a) != 0)
00166     {
00167       puts ("attr_destroy failed");
00168       exit (1);
00169     }
00170 
00171   pthread_barrier_wait (&b);
00172 
00173   sigset_t ss;
00174   sigemptyset (&ss);
00175   sigaddset (&ss, THE_SIG);
00176   if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
00177     {
00178       puts ("pthread_sigmask failed");
00179       exit (1);
00180     }
00181 
00182   /* Start sending signals.  */
00183   for (i = 0; i < TOTAL_SIGS; ++i)
00184     {
00185       if (kill (getpid (), THE_SIG) != 0)
00186        {
00187          puts ("kill failed");
00188          exit (1);
00189        }
00190 
00191       if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
00192        {
00193          puts ("sem_wait failed");
00194          exit (1);
00195        }
00196 
00197       ++nsigs;
00198     }
00199 
00200   pthread_barrier_wait (&b);
00201 
00202   for (i = 0; i < N; ++i)
00203     if (pthread_join (th[i], NULL) != 0)
00204       {
00205        puts ("join failed");
00206        exit (1);
00207       }
00208 
00209   return 0;
00210 #endif
00211 }
00212 
00213 
00214 #define TEST_FUNCTION do_test ()
00215 #include "../test-skeleton.c"