• 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  *  -> pthread_self() returns the thread ID of the calling thread.
19  *      Therefore, it never returns the same value for 2 different running threads.
20 
21  * The steps are:
22  * -> Create some threads with different parameters
23  * -> Get the threads IDs
24  * -> Compare all the threads IDs to find duplicates.
25 
26  */
27 
28  /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
29 #define _POSIX_C_SOURCE 200112L
30 
31  /* Some routines are part of the XSI Extensions */
32 #ifndef WITHOUT_XOPEN
33 #define _XOPEN_SOURCE	600
34 #endif
35 /********************************************************************************************/
36 /****************************** standard includes *****************************************/
37 /********************************************************************************************/
38 #include <pthread.h>
39 #include <stdarg.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 
45 #include <semaphore.h>
46 #include <errno.h>
47 #include <signal.h>
48 
49 /********************************************************************************************/
50 /******************************   Test framework   *****************************************/
51 /********************************************************************************************/
52 #include "testfrmw.h"
53 #include "testfrmw.c"
54  /* This header is responsible for defining the following macros:
55   * UNRESOLVED(ret, descr);
56   *    where descr is a description of the error and ret is an int (error code for example)
57   * FAILED(descr);
58   *    where descr is a short text saying why the test has failed.
59   * PASSED();
60   *    No parameter.
61   *
62   * Both three macros shall terminate the calling process.
63   * The testcase shall not terminate in any other maneer.
64   *
65   * The other file defines the functions
66   * void output_init()
67   * void output(char * string, ...)
68   *
69   * Those may be used to output information.
70   */
71 
72 /********************************************************************************************/
73 /********************************** Configuration ******************************************/
74 /********************************************************************************************/
75 #ifndef VERBOSE
76 #define VERBOSE 1
77 #endif
78 
79 /********************************************************************************************/
80 /***********************************    Test cases  *****************************************/
81 /********************************************************************************************/
82 
83 #include "threads_scenarii.c"
84 
85 /* This file will define the following objects:
86  * scenarii: array of struct __scenario type.
87  * NSCENAR : macro giving the total # of scenarii
88  * scenar_init(): function to call before use the scenarii array.
89  * scenar_fini(): function to call after end of use of the scenarii array.
90  */
91 
92 /********************************************************************************************/
93 /***********************************    Real Test   *****************************************/
94 /********************************************************************************************/
95 
96 char do_it = 1;
97 long long iterations = 0;
98 
99 /* Handler for user request to terminate */
sighdl(int sig)100 void sighdl(int sig)
101 {
102 	/* do_it = 0 */
103 	do {
104 		do_it = 0;
105 	}
106 	while (do_it);
107 }
108 
109 /* Protect concurrent access to the shared data */
110 pthread_mutex_t m_synchro = PTHREAD_MUTEX_INITIALIZER;
111 
112 /* Signaled when all threads are running */
113 pthread_cond_t c_synchro = PTHREAD_COND_INITIALIZER;
114 int c_boolean;
115 
116 /* Thread ID returned by pthread_self  */
117 pthread_t running[NSCENAR];
118 
119 /* Thread function */
threaded(void * arg)120 void *threaded(void *arg)
121 {
122 	int ret = 0;
123 	int me = *(int *)arg;
124 
125 #if VERBOSE > 6
126 	output("[child%d] starting\n", me);
127 #endif
128 	/* Wait for all threads being created */
129 	ret = pthread_mutex_lock(&m_synchro);
130 	if (ret != 0) {
131 		UNRESOLVED(ret, "Mutex lock failed");
132 	}
133 #if VERBOSE > 6
134 	output("[child%d] got mutex\n", me);
135 #endif
136 
137 	running[me] = pthread_self();
138 
139 	/* Signal we're running */
140 	do {
141 		ret = sem_post(&scenarii[me].sem);
142 	}
143 	while ((ret == -1) && (errno == EINTR));
144 	if (ret == -1) {
145 		UNRESOLVED(errno, "Failed to post the semaphore");
146 	}
147 #if VERBOSE > 6
148 	output("[child%d] posted semaphore %p\n", me, &scenarii[me].sem);
149 #endif
150 
151 	while (!c_boolean) {
152 		ret = pthread_cond_wait(&c_synchro, &m_synchro);
153 		if (ret != 0) {
154 			UNRESOLVED(ret, "Failed to wait the condvar");
155 		}
156 #if VERBOSE > 6
157 		output("[child%d] awaken\n", me);
158 #endif
159 	}
160 
161 	ret = pthread_mutex_unlock(&m_synchro);
162 	if (ret != 0) {
163 		UNRESOLVED(ret, "Mutex unlock failed");
164 	}
165 #if VERBOSE > 6
166 	output("[child%d] exiting\n", me);
167 #endif
168 
169 	return arg;
170 }
171 
172 /* Main function */
main(int argc,char * argv[])173 int main(int argc, char *argv[])
174 {
175 	int ret = 0;
176 	struct sigaction sa;
177 
178 	pthread_t creation[NSCENAR];	/* Thread ID returned in pthread_create */
179 	int status[NSCENAR];	/* Status of thread creation */
180 	int ids[NSCENAR];
181 
182 	int i;
183 
184 	for (sc = 0; sc < NSCENAR; sc++)
185 		ids[sc] = sc;
186 
187 	/* Initialize output routine */
188 	output_init();
189 
190 	/* Initialize thread attribute objects */
191 	scenar_init();
192 
193 	/* Register the signal handler for SIGUSR1 */
194 	sigemptyset(&sa.sa_mask);
195 	sa.sa_flags = 0;
196 	sa.sa_handler = sighdl;
197 	if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
198 		UNRESOLVED(ret, "Unable to register signal handler");
199 	}
200 	if ((ret = sigaction(SIGALRM, &sa, NULL))) {
201 		UNRESOLVED(ret, "Unable to register signal handler");
202 	}
203 #if VERBOSE > 1
204 	output("[parent] Signal handler registered\n");
205 #endif
206 
207 	while (do_it) {
208 		/* Initialize the shared data */
209 		c_boolean = 0;
210 
211 		/* Create all the threads */
212 		for (sc = 0; sc < NSCENAR; sc++) {
213 			/* Create the thread */
214 			status[sc] =
215 			    pthread_create(&creation[sc], &scenarii[sc].ta,
216 					   threaded, &ids[sc]);
217 
218 			/* Check creation status */
219 			switch (scenarii[sc].result) {
220 			case 0:	/* Operation was expected to succeed */
221 				if (status[sc] != 0) {
222 					UNRESOLVED(ret,
223 						   "Failed to create this thread");
224 				}
225 				break;
226 
227 			case 1:	/* Operation was expected to fail */
228 				if (status[sc] == 0) {
229 					UNRESOLVED(-1,
230 						   "An error was expected but the thread creation succeeded");
231 				}
232 				break;
233 
234 			case 2:	/* We did not know the expected result */
235 			default:
236 				/* Nothing */
237 				;
238 			}
239 		}
240 #if VERBOSE > 6
241 		output("[parent] threads created\n");
242 #endif
243 
244 		/* Now wait that all threads are running */
245 		for (sc = 0; sc < NSCENAR; sc++) {
246 			if (status[sc] == 0) {	/* The new thread is running */
247 #if VERBOSE > 6
248 				output("[parent] Waiting for thread %d: %p\n",
249 				       sc, &scenarii[sc].sem);
250 #endif
251 				do {
252 					ret = sem_wait(&scenarii[sc].sem);
253 				}
254 				while ((ret == -1) && (errno == EINTR));
255 				if (ret == -1) {
256 					UNRESOLVED(errno,
257 						   "Failed to wait for the semaphore");
258 				}
259 			}
260 		}
261 
262 #if VERBOSE > 6
263 		output("[parent] Locking the mutex\n");
264 #endif
265 
266 		ret = pthread_mutex_lock(&m_synchro);
267 		if (ret != 0) {
268 			UNRESOLVED(ret, "Mutex lock failed");
269 		}
270 
271 		/* Now, we've got all shared data set, so we can seek for duplicates */
272 		for (sc = 0; sc < NSCENAR; sc++) {
273 			if (status[sc] != 0)	/* The new thread is running */
274 				continue;
275 
276 			if (pthread_equal(creation[sc], running[sc]) == 0) {
277 				output("pthread_create returned an ID of %p\n",
278 				       creation[sc]);
279 				output
280 				    ("pthread_self in the thread returned %p\n",
281 				     running[sc]);
282 				FAILED("Error: Values mismatch");
283 			}
284 
285 			for (i = sc + 1; i < NSCENAR; i++) {
286 				if (status[i] != 0)
287 					continue;
288 
289 				if (pthread_equal(creation[sc], creation[i])) {
290 					FAILED
291 					    ("Two different running threads have the same ID");
292 				}
293 			}
294 		}
295 #if VERBOSE > 6
296 		output("[parent] No duplicate found\n");
297 #endif
298 
299 		/* We're done, we can terminate the threads */
300 		c_boolean = 1;
301 		ret = pthread_mutex_unlock(&m_synchro);
302 		if (ret != 0) {
303 			UNRESOLVED(ret, "Mutex unlock failed");
304 		}
305 
306 		ret = pthread_cond_broadcast(&c_synchro);
307 		if (ret != 0) {
308 			UNRESOLVED(ret, "Failed to broadcast the cond");
309 		}
310 #if VERBOSE > 6
311 		output("[parent] Cond broadcasted\n");
312 #endif
313 
314 		/* Join the joinable threads */
315 		for (sc = 0; sc < NSCENAR; sc++) {
316 			if (status[sc] != 0)	/* The new thread is running */
317 				continue;
318 
319 			if (scenarii[sc].detached == 0) {
320 #if VERBOSE > 6
321 				output("[parent] Joining %d\n", sc);
322 #endif
323 				ret = pthread_join(creation[sc], NULL);
324 				if (ret != 0) {
325 					UNRESOLVED(ret,
326 						   "Unalbe to join a thread");
327 				}
328 #if VERBOSE > 6
329 				output("[parent] Joined %d\n", sc);
330 #endif
331 			}
332 
333 		}
334 		iterations++;
335 	}
336 
337 	/* We've been asked to stop */
338 
339 	scenar_fini();
340 
341 	output("pthread_exit stress test PASSED -- %llu iterations\n",
342 	       iterations);
343 
344 	PASSED;
345 }
346