OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / test / nptl / tst-once4.c
1 /* Copyright (C) 2003, 2004 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 <pthread.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <time.h>
23 #include <unistd.h>
24
25
26 static pthread_once_t once = PTHREAD_ONCE_INIT;
27
28 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
29 static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
30
31 static pthread_barrier_t bar;
32
33 static int global;
34 static int cl_called;
35
36 static void
37 once_handler1 (void)
38 {
39   if (pthread_mutex_lock (&mut) != 0)
40     {
41       puts ("once_handler1: mutex_lock failed");
42       exit (1);
43     }
44
45   int r = pthread_barrier_wait (&bar);
46   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
47     {
48       puts ("once_handler1: barrier_wait failed");
49       exit (1);
50     }
51
52   pthread_cond_wait (&cond, &mut);
53
54   /* We should never get here.  */
55 }
56
57
58 static void
59 once_handler2 (void)
60 {
61   global = 1;
62 }
63
64
65 static void
66 cl (void *arg)
67 {
68   ++cl_called;
69 }
70
71
72 static void *
73 tf1 (void *arg)
74 {
75   pthread_cleanup_push (cl, NULL);
76
77   pthread_once (&once, once_handler1);
78
79   pthread_cleanup_pop (0);
80
81   /* We should never get here.  */
82   puts ("pthread_once in tf returned");
83   exit (1);
84 }
85
86
87 static void *
88 tf2 (void *arg)
89 {
90   pthread_cleanup_push (cl, NULL);
91
92   int r = pthread_barrier_wait (&bar);
93   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
94     {
95       puts ("once_handler2: barrier_wait failed");
96       exit (1);
97     }
98
99   pthread_cleanup_pop (0);
100
101   pthread_once (&once, once_handler2);
102
103   return NULL;
104 }
105
106
107 static int
108 do_test (void)
109 {
110   pthread_t th[2];
111
112   if (pthread_barrier_init (&bar, NULL, 2) != 0)
113     {
114       puts ("barrier_init failed");
115       return 1;
116     }
117
118   if (pthread_create (&th[0], NULL, tf1, NULL) != 0)
119     {
120       puts ("first create failed");
121       return 1;
122     }
123
124   int r = pthread_barrier_wait (&bar);
125   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
126     {
127       puts ("first barrier_wait failed");
128       return 1;
129     }
130
131   if (pthread_mutex_lock (&mut) != 0)
132     {
133       puts ("mutex_lock failed");
134       return 1;
135     }
136   /* We unlock the mutex so that we catch the case where the pthread_cond_wait
137      call incorrectly resumes and tries to get the mutex.  */
138   if (pthread_mutex_unlock (&mut) != 0)
139     {
140       puts ("mutex_unlock failed");
141       return 1;
142     }
143
144   if (pthread_create (&th[1], NULL, tf2, NULL) != 0)
145     {
146       puts ("second create failed");
147       return 1;
148     }
149
150   r = pthread_barrier_wait (&bar);
151   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
152     {
153       puts ("second barrier_wait failed");
154       return 1;
155     }
156
157   /* Give the second thread a chance to reach the pthread_once call.  */
158   sleep (2);
159
160   /* Cancel the thread.  */
161   if (pthread_cancel (th[0]) != 0)
162     {
163       puts ("cancel failed");
164       return 1;
165     }
166
167   void *result;
168   pthread_join (th[0], &result);
169   if (result != PTHREAD_CANCELED)
170     {
171       puts ("first join didn't return PTHREAD_CANCELED");
172       return 1;
173     }
174
175   puts ("joined first thread");
176
177   pthread_join (th[1], &result);
178   if (result != NULL)
179     {
180       puts ("second join didn't return PTHREAD_CANCELED");
181       return 1;
182     }
183
184   if (global != 1)
185     {
186       puts ("global still 0");
187       return 1;
188     }
189
190   if (cl_called != 1)
191     {
192       printf ("cl_called = %d\n", cl_called);
193       return 1;
194     }
195
196   return 0;
197 }
198
199 #define TEST_FUNCTION do_test ()
200 #define TIMEOUT 4
201 #include "../test-skeleton.c"