• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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