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