iconv: Suppress array out of bounds warning.
[platform/upstream/glibc.git] / nptl / tst-once3.c
1 /* Copyright (C) 2002-2015 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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
24
25 #define N 100
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   puts ("once_handler1: locked");
46
47   int r = pthread_barrier_wait (&bar);
48   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
49     {
50       puts ("once_handler1: barrier_wait failed");
51       exit (1);
52     }
53
54   puts ("once_handler1: going to wait on cond");
55
56   pthread_cond_wait (&cond, &mut);
57
58   /* We should never get here.  */
59   exit (42);
60 }
61
62 static void
63 once_handler2 (void)
64 {
65   global = 1;
66 }
67
68
69 static void
70 cl (void *arg)
71 {
72   cl_called = 1;
73 }
74
75
76 static void *
77 tf (void *arg)
78 {
79   pthread_cleanup_push (cl, NULL)
80
81   pthread_once (&once, once_handler1);
82
83   pthread_cleanup_pop (0);
84
85   /* We should never get here.  */
86   puts ("pthread_once in tf returned");
87   exit (1);
88 }
89
90
91 static int
92 do_test (void)
93 {
94   pthread_t th;
95
96   if (pthread_barrier_init (&bar, NULL, 2) != 0)
97     {
98       puts ("barrier_init failed");
99       return 1;
100     }
101
102   if (pthread_create (&th, NULL, tf, NULL) != 0)
103     {
104       puts ("first create failed");
105       return 1;
106     }
107
108   int r = pthread_barrier_wait (&bar);
109   if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
110     {
111       puts ("barrier_wait failed");
112       return 1;
113     }
114
115   if (pthread_mutex_lock (&mut) != 0)
116     {
117       puts ("mutex_lock failed");
118       return 1;
119     }
120   /* We unlock the mutex so that we catch the case where the pthread_cond_wait
121      call incorrectly resumes and tries to get the mutex.  */
122   if (pthread_mutex_unlock (&mut) != 0)
123     {
124       puts ("mutex_unlock failed");
125       return 1;
126     }
127
128   /* Cancel the thread.  */
129   puts ("going to cancel");
130   if (pthread_cancel (th) != 0)
131     {
132       puts ("cancel failed");
133       return 1;
134     }
135
136   void *result;
137   pthread_join (th, &result);
138   if (result != PTHREAD_CANCELED)
139     {
140       puts ("join didn't return PTHREAD_CANCELED");
141       return 1;
142     }
143   puts ("joined successfully");
144
145   printf ("once = %d\n", *(int *) &once);
146
147   if (cl_called != 1)
148     {
149       puts ("cleanup handler not called");
150       return 1;
151     }
152
153   pthread_once (&once, once_handler2);
154
155   if (global != 1)
156     {
157       puts ("global still 0");
158       return 1;
159     }
160
161   return 0;
162 }
163
164 #define TEST_FUNCTION do_test ()
165 #define TIMEOUT 4
166 #include "../test-skeleton.c"