Only support ifunc in nptl/pt-vfork.c
[platform/upstream/linaro-glibc.git] / nptl / tst-cancel17.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 <aio.h>
20 #include <errno.h>
21 #include <pthread.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26
27
28 static pthread_barrier_t b;
29
30
31 /* Cleanup handling test.  */
32 static int cl_called;
33
34 static void
35 cl (void *arg)
36 {
37   ++cl_called;
38 }
39
40
41 static void *
42 tf (void *arg)
43 {
44   int r = pthread_barrier_wait (&b);
45   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
46     {
47       puts ("tf: barrier_wait failed");
48       exit (1);
49     }
50
51   pthread_cleanup_push (cl, NULL);
52
53   const struct aiocb *l[1] = { arg };
54
55   TEMP_FAILURE_RETRY (aio_suspend (l, 1, NULL));
56
57   pthread_cleanup_pop (0);
58
59   puts ("tf: aio_suspend returned");
60
61   exit (1);
62 }
63
64
65 static void *
66 tf2 (void *arg)
67 {
68   int r = pthread_barrier_wait (&b);
69   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
70     {
71       puts ("tf2: barrier_wait failed");
72       exit (1);
73     }
74
75   pthread_cleanup_push (cl, NULL);
76
77   const struct aiocb *l[1] = { arg };
78   struct timespec ts = { .tv_sec = 1000, .tv_nsec = 0 };
79
80   TEMP_FAILURE_RETRY (aio_suspend (l, 1, &ts));
81
82   pthread_cleanup_pop (0);
83
84   puts ("tf2: aio_suspend returned");
85
86   exit (1);
87 }
88
89
90 static int
91 do_test (void)
92 {
93   int fds[2];
94   if (pipe (fds) != 0)
95     {
96       puts ("pipe failed");
97       return 1;
98     }
99
100   struct aiocb a, a2, *ap;
101   char mem[1];
102   memset (&a, '\0', sizeof (a));
103   a.aio_fildes = fds[0];
104   a.aio_buf = mem;
105   a.aio_nbytes = sizeof (mem);
106   if (aio_read (&a) != 0)
107     {
108       puts ("aio_read failed");
109       return 1;
110     }
111
112   if (pthread_barrier_init (&b, NULL, 2) != 0)
113     {
114       puts ("barrier_init failed");
115       return 1;
116     }
117
118   pthread_t th;
119   if (pthread_create (&th, NULL, tf, &a) != 0)
120     {
121       puts ("1st create failed");
122       return 1;
123     }
124
125   int r = pthread_barrier_wait (&b);
126   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
127     {
128       puts ("barrier_wait failed");
129       exit (1);
130     }
131
132   struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
133   while (nanosleep (&ts, &ts) != 0)
134     continue;
135
136   puts ("going to cancel tf in-time");
137   if (pthread_cancel (th) != 0)
138     {
139       puts ("1st cancel failed");
140       return 1;
141     }
142
143   void *status;
144   if (pthread_join (th, &status) != 0)
145     {
146       puts ("1st join failed");
147       return 1;
148     }
149   if (status != PTHREAD_CANCELED)
150     {
151       puts ("1st thread not canceled");
152       return 1;
153     }
154
155   if (cl_called == 0)
156     {
157       puts ("tf cleanup handler not called");
158       return 1;
159     }
160   if (cl_called > 1)
161     {
162       puts ("tf cleanup handler called more than once");
163       return 1;
164     }
165
166   cl_called = 0;
167
168   if (pthread_create (&th, NULL, tf2, &a) != 0)
169     {
170       puts ("2nd create failed");
171       return 1;
172     }
173
174   r = pthread_barrier_wait (&b);
175   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
176     {
177       puts ("2nd barrier_wait failed");
178       exit (1);
179     }
180
181   ts.tv_sec = 0;
182   ts.tv_nsec = 100000000;
183   while (nanosleep (&ts, &ts) != 0)
184     continue;
185
186   puts ("going to cancel tf2 in-time");
187   if (pthread_cancel (th) != 0)
188     {
189       puts ("2nd cancel failed");
190       return 1;
191     }
192
193   if (pthread_join (th, &status) != 0)
194     {
195       puts ("2nd join failed");
196       return 1;
197     }
198   if (status != PTHREAD_CANCELED)
199     {
200       puts ("2nd thread not canceled");
201       return 1;
202     }
203
204   if (cl_called == 0)
205     {
206       puts ("tf2 cleanup handler not called");
207       return 1;
208     }
209   if (cl_called > 1)
210     {
211       puts ("tf2 cleanup handler called more than once");
212       return 1;
213     }
214
215   puts ("in-time cancellation succeeded");
216
217   ap = &a;
218   if (aio_cancel (fds[0], &a) != AIO_CANCELED)
219     {
220       puts ("aio_cancel failed");
221       /* If aio_cancel failed, we cannot reuse aiocb a.  */
222       ap = &a2;
223     }
224
225
226   cl_called = 0;
227
228   size_t len2 = fpathconf (fds[1], _PC_PIPE_BUF);
229   size_t page_size = sysconf (_SC_PAGESIZE);
230   len2 = 20 * (len2 < page_size ? page_size : len2) + sizeof (mem) + 1;
231   char *mem2 = malloc (len2);
232   if (mem2 == NULL)
233     {
234       puts ("could not allocate memory for pipe write");
235       return 1;
236     }
237
238   memset (ap, '\0', sizeof (*ap));
239   ap->aio_fildes = fds[1];
240   ap->aio_buf = mem2;
241   ap->aio_nbytes = len2;
242   if (aio_write (ap) != 0)
243     {
244       puts ("aio_write failed");
245       return 1;
246     }
247
248   if (pthread_create (&th, NULL, tf, ap) != 0)
249     {
250       puts ("3rd create failed");
251       return 1;
252     }
253
254   puts ("going to cancel tf early");
255   if (pthread_cancel (th) != 0)
256     {
257       puts ("3rd cancel failed");
258       return 1;
259     }
260
261   r = pthread_barrier_wait (&b);
262   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
263     {
264       puts ("3rd barrier_wait failed");
265       exit (1);
266     }
267
268   if (pthread_join (th, &status) != 0)
269     {
270       puts ("3rd join failed");
271       return 1;
272     }
273   if (status != PTHREAD_CANCELED)
274     {
275       puts ("3rd thread not canceled");
276       return 1;
277     }
278
279   if (cl_called == 0)
280     {
281       puts ("tf cleanup handler not called");
282       return 1;
283     }
284   if (cl_called > 1)
285     {
286       puts ("tf cleanup handler called more than once");
287       return 1;
288     }
289
290   cl_called = 0;
291
292   if (pthread_create (&th, NULL, tf2, ap) != 0)
293     {
294       puts ("4th create failed");
295       return 1;
296     }
297
298   puts ("going to cancel tf2 early");
299   if (pthread_cancel (th) != 0)
300     {
301       puts ("4th cancel failed");
302       return 1;
303     }
304
305   r = pthread_barrier_wait (&b);
306   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
307     {
308       puts ("4th barrier_wait failed");
309       exit (1);
310     }
311
312   if (pthread_join (th, &status) != 0)
313     {
314       puts ("4th join failed");
315       return 1;
316     }
317   if (status != PTHREAD_CANCELED)
318     {
319       puts ("4th thread not canceled");
320       return 1;
321     }
322
323   if (cl_called == 0)
324     {
325       puts ("tf2 cleanup handler not called");
326       return 1;
327     }
328   if (cl_called > 1)
329     {
330       puts ("tf2 cleanup handler called more than once");
331       return 1;
332     }
333
334   puts ("early cancellation succeeded");
335
336   return 0;
337 }
338
339 #define TEST_FUNCTION do_test ()
340 #include "../test-skeleton.c"