OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / test / nptl / tst-cleanup4.c
1 /* Copyright (C) 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Jakub Jelinek <jakub@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 <pthread.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23
24 /* LinuxThreads pthread_cleanup_{push,pop} helpers.  */
25 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
26                                    void (*__routine) (void *),
27                                    void *__arg);
28 extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
29                                   int __execute);
30
31 static int fds[2];
32 static pthread_barrier_t b2;
33 static int global;
34
35 /* Defined in tst-cleanup4aux.c, never compiled with -fexceptions.  */
36 extern void fn5 (void);
37 extern void fn7 (void);
38 extern void fn9 (void);
39
40 void
41 clh (void *arg)
42 {
43   int val = (long int) arg;
44
45   printf ("clh (%d)\n", val);
46
47   global *= val;
48   global += val;
49 }
50
51
52 static __attribute__((noinline)) void
53 fn_read (void)
54 {
55   int r = pthread_barrier_wait (&b2);
56   if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
57     {
58       printf ("%s: barrier_wait failed\n", __FUNCTION__);
59       exit (1);
60     }
61
62   char c;
63   read (fds[0], &c, 1);
64 }
65
66
67 __attribute__((noinline)) void
68 fn0 (void)
69 {
70   pthread_cleanup_push (clh, (void *) 1l);
71
72   fn_read ();
73
74   pthread_cleanup_pop (1);
75 }
76
77
78 __attribute__((noinline)) void
79 fn1 (void)
80 {
81   /* This is the old LinuxThreads pthread_cleanup_{push,pop}.  */
82   struct _pthread_cleanup_buffer b;
83   _pthread_cleanup_push (&b, clh, (void *) 2l);
84
85   fn0 ();
86
87   _pthread_cleanup_pop (&b, 1);
88 }
89
90
91 static __attribute__((noinline)) void
92 fn2 (void)
93 {
94   pthread_cleanup_push (clh, (void *) 3l);
95
96   fn1 ();
97
98   pthread_cleanup_pop (1);
99 }
100
101
102 static void *
103 tf (void *a)
104 {
105   switch ((long) a)
106     {
107     case 0:
108       fn2 ();
109       break;
110     case 1:
111       fn5 ();
112       break;
113     case 2:
114       fn7 ();
115       break;
116     case 3:
117       fn9 ();
118       break;
119     }
120
121   return NULL;
122 }
123
124
125 int
126 do_test (void)
127 {
128   int result = 0;
129
130   if (pipe (fds) != 0)
131     {
132       puts ("pipe failed");
133       exit (1);
134     }
135
136   if (pthread_barrier_init (&b2, NULL, 2) != 0)
137     {
138       puts ("b2 init failed");
139       exit (1);
140     }
141
142   const int expect[] =
143     {
144       15,       /* 1 2 3 */
145       276,      /* 1 4 5 6 */
146       120,      /* 1 7 8 */
147       460       /* 1 2 9 10 */
148     };
149
150   long i;
151   for (i = 0; i < 4; ++i)
152     {
153       global = 0;
154
155       printf ("test %ld\n", i);
156
157       pthread_t th;
158       if (pthread_create (&th, NULL, tf, (void *) i) != 0)
159         {
160           puts ("create failed");
161           exit (1);
162         }
163
164       int e = pthread_barrier_wait (&b2);
165       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
166         {
167           printf ("%s: barrier_wait failed\n", __FUNCTION__);
168           exit (1);
169         }
170
171       pthread_cancel (th);
172
173       void *r;
174       if ((e = pthread_join (th, &r)) != 0)
175         {
176           printf ("join failed: %d\n", e);
177           _exit (1);
178         }
179
180       if (r != PTHREAD_CANCELED)
181         {
182           puts ("thread not canceled");
183           exit (1);
184         }
185
186       if (global != expect[i])
187         {
188           printf ("global = %d, expected %d\n", global, expect[i]);
189           result = 1;
190         }
191     }
192
193   return result;
194 }
195
196 #define TEST_FUNCTION do_test ()
197 #include "../test-skeleton.c"