OSDN Git Service

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