]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel16.c
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / test / nptl / tst-cancel16.c
1 /* Copyright (C) 2003 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 <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/mman.h>
26 #include <sys/wait.h>
27
28
29 static pthread_barrier_t b2;
30 static int fd;
31 static int called;
32
33
34 static void
35 cl (void *arg)
36 {
37   called = 1;
38 }
39
40
41 static void *
42 tf (void *arg)
43 {
44   int r = pthread_barrier_wait (&b2);
45   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
46     {
47       puts ("child thread: barrier_wait failed");
48       exit (1);
49     }
50
51   pthread_cleanup_push (cl, NULL);
52
53   /* This call should never return.  */
54   (void) lockf (fd, F_LOCK, 0);
55
56   pthread_cleanup_pop (0);
57
58   return NULL;
59 }
60
61
62 static int
63 do_test (void)
64 {
65   char fname[] = "/tmp/cancel16XXXXXX";
66   fd = mkstemp (fname);
67   if (fd == -1)
68     {
69       puts ("mkstemp failed");
70       return 1;
71     }
72   unlink (fname);
73
74   char mem[sizeof (pthread_barrier_t)];
75   memset (mem, '\0', sizeof (mem));
76   if (TEMP_FAILURE_RETRY (pwrite (fd, mem, sizeof (mem), 0)) != sizeof (mem))
77     {
78       puts ("pwrite failed");
79       return 1;
80     }
81
82   void *p = mmap (NULL, sizeof (mem), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
83   if (p == MAP_FAILED)
84     {
85       puts ("mmap failed");
86       return 1;
87     }
88   pthread_barrier_t *b = (pthread_barrier_t *) p;
89
90   pthread_barrierattr_t ba;
91   if (pthread_barrierattr_init (&ba) != 0)
92     {
93       puts ("barrierattr_init failed");
94       return 1;
95     }
96   if (pthread_barrierattr_setpshared (&ba, 1) != 0)
97     {
98       puts ("barrierattr_setshared failed");
99       return 1;
100     }
101
102   if (pthread_barrier_init (b, &ba, 2) != 0)
103     {
104       puts ("1st barrier_init failed");
105       return 1;
106     }
107   if (pthread_barrierattr_destroy (&ba) != 0)
108     {
109       puts ("barrier_destroy failed");
110       return 1;
111     }
112
113   pid_t pid = fork ();
114   if (pid == 0)
115     {
116       /* Child.  Lock the file and wait.  */
117       if (lockf (fd, F_LOCK, 0) != 0)
118         {
119           puts ("child process: lockf failed");
120           _exit (1);
121         }
122
123       int r = pthread_barrier_wait (b);
124       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
125         {
126           puts ("child process: 1st barrier_wait failed");
127           _exit (1);
128         }
129
130       /* Make sure the process dies.  */
131       alarm (5);
132
133       r = pthread_barrier_wait (b);
134       if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
135         {
136           puts ("child process: 2nd barrier_wait failed");
137           _exit (1);
138         }
139
140       _exit (0);
141     }
142   if (pid == -1)
143     {
144       puts ("fork failed");
145       return 1;
146     }
147
148   int r = pthread_barrier_wait (b);
149   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
150     {
151       puts ("main: 1st barrier_wait failed");
152       _exit (1);
153     }
154
155   if (pthread_barrier_init (&b2, NULL, 2) != 0)
156     {
157       puts ("2nd barrier_init failed");
158       return 1;
159     }
160
161   pthread_t th;
162   if (pthread_create (&th, NULL, tf, NULL) != 0)
163     {
164       puts ("create failed");
165       return 1;
166     }
167
168   r = pthread_barrier_wait (&b2);
169   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
170     {
171       puts ("main: 2nd barrier_wait failed");
172       return 1;
173     }
174
175   /* Delay.  */
176   sleep (1);
177
178   if (pthread_cancel (th) != 0)
179     {
180       puts ("cancel failed");
181       return 1;
182     }
183
184   void *result;
185   if (pthread_join (th, &result) != 0)
186     {
187       puts ("join failed");
188       return 1;
189     }
190   if (result != PTHREAD_CANCELED)
191     {
192       puts ("thread not canceled");
193       return 1;
194     }
195   if (called == 0)
196     {
197       puts ("cleanup handler not called");
198       return 1;
199     }
200
201   r = pthread_barrier_wait (b);
202   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
203     {
204       puts ("main: 3rd barrier_wait failed");
205       return 1;
206     }
207
208   int status;
209   if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
210     {
211       puts ("waitpid failed");
212       return 1;
213     }
214   if (WEXITSTATUS (status) != 0)
215     {
216       printf ("child process exits with %d\n", WEXITSTATUS (status));
217       return 1;
218     }
219
220   if (lockf (fd, F_LOCK, 0) != 0)
221     {
222       puts ("main: lockf failed");
223       return 1;
224     }
225
226   return 0;
227 }
228
229 #define TEST_FUNCTION do_test ()
230 #include "../test-skeleton.c"