1 /*
2 * Copyright (c) 2004, Bull S.A.. All rights reserved.
3 * Created by: Sebastien Decugis
4
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17 * This stress test aims to test the following assertion:
18
19 * The init_routine from pthread_once never execute
20 * more or less than once.
21
22 * The steps are:
23 * -> Create several threads
24 * -> All threads call pthread_once at the same time
25 * -> Check the init_routine executed once.
26
27 */
28
29 /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
30 #define _POSIX_C_SOURCE 200112L
31
32 /********************************************************************************************/
33 /****************************** standard includes *****************************************/
34 /********************************************************************************************/
35 #include <pthread.h>
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41
42 #include <errno.h>
43 #include <signal.h>
44
45 /********************************************************************************************/
46 /****************************** Test framework *****************************************/
47 /********************************************************************************************/
48 #include "testfrmw.h"
49 #include "testfrmw.c"
50 /* This header is responsible for defining the following macros:
51 * UNRESOLVED(ret, descr);
52 * where descr is a description of the error and ret is an int (error code for example)
53 * FAILED(descr);
54 * where descr is a short text saying why the test has failed.
55 * PASSED();
56 * No parameter.
57 *
58 * Both three macros shall terminate the calling process.
59 * The testcase shall not terminate in any other maneer.
60 *
61 * The other file defines the functions
62 * void output_init()
63 * void output(char * string, ...)
64 *
65 * Those may be used to output information.
66 */
67
68 /********************************************************************************************/
69 /********************************** Configuration ******************************************/
70 /********************************************************************************************/
71 #ifndef VERBOSE
72 #define VERBOSE 1
73 #endif
74
75 #define NTHREADS 30
76
77 /********************************************************************************************/
78 /*********************************** Test cases *****************************************/
79 /********************************************************************************************/
80
81 char do_it = 1;
82 long long iterations = 0;
83
84 /* Handler for user request to terminate */
sighdl(int sig)85 void sighdl(int sig)
86 {
87 do {
88 do_it = 0;
89 }
90 while (do_it);
91 }
92
93 pthread_once_t once_ctl;
94 int once_chk;
95 pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
96
init_routine(void)97 void init_routine(void)
98 {
99 int ret = 0;
100 ret = pthread_mutex_lock(&mtx);
101
102 if (ret != 0) {
103 UNRESOLVED(ret, "Failed to lock mutex in initializer");
104 }
105
106 once_chk++;
107
108 ret = pthread_mutex_unlock(&mtx);
109
110 if (ret != 0) {
111 UNRESOLVED(ret, "Failed to unlock mutex in initializer");
112 }
113
114 return;
115 }
116
117 /* Thread function */
threaded(void * arg)118 void *threaded(void *arg)
119 {
120 int ret = 0;
121
122 /* Wait for all threads being created */
123 ret = pthread_barrier_wait(arg);
124
125 if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
126 UNRESOLVED(ret, "Barrier wait failed");
127 }
128
129 /* Call init routine */
130 ret = pthread_once(&once_ctl, init_routine);
131
132 if (ret != 0) {
133 UNRESOLVED(ret, "pthread_once failed");
134 }
135
136 return NULL;
137 }
138
139 /* Main function */
main(int argc,char * argv[])140 int main(int argc, char *argv[])
141 {
142 int ret = 0, i;
143
144 struct sigaction sa;
145
146 pthread_barrier_t bar;
147
148 pthread_t th[NTHREADS];
149
150 /* Initialize output routine */
151 output_init();
152
153 /* Initialize barrier */
154 ret = pthread_barrier_init(&bar, NULL, NTHREADS);
155
156 if (ret != 0) {
157 UNRESOLVED(ret, "Failed to init barrier");
158 }
159
160 /* Register the signal handler for SIGUSR1 */
161 sigemptyset(&sa.sa_mask);
162
163 sa.sa_flags = 0;
164
165 sa.sa_handler = sighdl;
166
167 if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
168 UNRESOLVED(ret, "Unable to register signal handler");
169 }
170
171 if ((ret = sigaction(SIGALRM, &sa, NULL))) {
172 UNRESOLVED(ret, "Unable to register signal handler");
173 }
174 #if VERBOSE > 1
175 output("[parent] Signal handler registered\n");
176
177 #endif
178
179 while (do_it) {
180 /* Reinitialize once handler & check value */
181 once_ctl = PTHREAD_ONCE_INIT;
182 once_chk = 0;
183
184 /* create the threads */
185
186 for (i = 0; i < NTHREADS; i++) {
187 ret = pthread_create(&th[i], NULL, threaded, &bar);
188
189 if (ret != 0) {
190 UNRESOLVED(ret, "Failed to create a thread");
191 }
192 }
193
194 /* Then join */
195 for (i = 0; i < NTHREADS; i++) {
196 ret = pthread_join(th[i], NULL);
197
198 if (ret != 0) {
199 UNRESOLVED(ret, "Failed to join a thread");
200 }
201 }
202
203 /* check the value */
204 ret = pthread_mutex_lock(&mtx);
205
206 if (ret != 0) {
207 UNRESOLVED(ret, "Failed to lock mutex in initializer");
208 }
209
210 if (once_chk != 1) {
211 output("Control: %d\n", once_chk);
212 FAILED("The initializer function did not execute once");
213 }
214
215 ret = pthread_mutex_unlock(&mtx);
216
217 if (ret != 0) {
218 UNRESOLVED(ret,
219 "Failed to unlock mutex in initializer");
220 }
221
222 iterations++;
223 }
224
225 /* We've been asked to stop */
226
227 output("pthread_once stress test PASSED -- %llu iterations\n",
228 iterations);
229
230 ret = pthread_barrier_destroy(&bar);
231
232 if (ret != 0) {
233 UNRESOLVED(ret, "Failed to destroy the barrier");
234 }
235
236 PASSED;
237 }
238