• 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 *  Heavy cancelation does not break the system or the user application.
20 
21 * The steps are:
22 * Create some threads which:
23 *  Create a thread.
24 *  Cancel this thread, as it terminates.
25 *  Check the return value.
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 
83 /* Handler for user request to terminate */
sighdl(int sig)84 void sighdl(int sig)
85 {
86 	do {
87 		do_it = 0;
88 	}
89 	while (do_it);
90 }
91 
92 long long canceled, ended;
93 
94 /* The canceled thread */
th(void * arg)95 void *th(void *arg)
96 {
97 	int ret = 0;
98 	ret = pthread_barrier_wait(arg);
99 
100 	if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
101 		UNRESOLVED(ret, "Failed to wait for the barrier");
102 	}
103 
104 	return NULL;
105 }
106 
107 /* Thread function */
threaded(void * arg)108 void *threaded(void *arg)
109 {
110 	int ret = 0;
111 	pthread_t child;
112 
113 	/* Initialize the barrier */
114 	ret = pthread_barrier_init(arg, NULL, 2);
115 
116 	if (ret != 0) {
117 		UNRESOLVED(ret, "Failed to initialize a barrier");
118 	}
119 
120 	while (do_it) {
121 		/* Create the thread */
122 		ret = pthread_create(&child, NULL, th, arg);
123 
124 		if (ret != 0) {
125 			UNRESOLVED(ret, "Thread creation failed");
126 		}
127 
128 		/* Synchronize */
129 		ret = pthread_barrier_wait(arg);
130 
131 		if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
132 			UNRESOLVED(ret, "Failed to wait for the barrier");
133 		}
134 
135 		/* Cancel the thread */
136 		ret = pthread_cancel(child);
137 
138 		if (ret == 0)
139 			canceled++;
140 		else
141 			ended++;
142 
143 		/* Join the thread */
144 		ret = pthread_join(child, NULL);
145 
146 		if (ret != 0) {
147 			UNRESOLVED(ret, "Unable to join the child");
148 		}
149 
150 	}
151 
152 	/* Destroy the barrier */
153 	ret = pthread_barrier_destroy(arg);
154 
155 	if (ret != 0) {
156 		UNRESOLVED(ret, "Failed to destroy a barrier");
157 	}
158 
159 	return NULL;
160 }
161 
162 /* Main function */
main(int argc,char * argv[])163 int main(int argc, char *argv[])
164 {
165 	int ret = 0, i;
166 
167 	struct sigaction sa;
168 
169 	pthread_t th[NTHREADS];
170 	pthread_barrier_t b[NTHREADS];
171 
172 	/* Initialize output routine */
173 	output_init();
174 
175 	/* Register the signal handler for SIGUSR1 */
176 	sigemptyset(&sa.sa_mask);
177 
178 	sa.sa_flags = 0;
179 
180 	sa.sa_handler = sighdl;
181 
182 	if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
183 		UNRESOLVED(ret, "Unable to register signal handler");
184 	}
185 
186 	if ((ret = sigaction(SIGALRM, &sa, NULL))) {
187 		UNRESOLVED(ret, "Unable to register signal handler");
188 	}
189 #if VERBOSE > 1
190 	output("[parent] Signal handler registered\n");
191 
192 #endif
193 
194 	for (i = 0; i < NTHREADS; i++) {
195 		ret = pthread_create(&th[i], NULL, threaded, &b[i]);
196 
197 		if (ret != 0) {
198 			UNRESOLVED(ret, "Failed to create a thread");
199 		}
200 	}
201 
202 #if VERBOSE > 1
203 	output("[parent] All threads are running\n");
204 
205 #endif
206 
207 	/* Then join */
208 	for (i = 0; i < NTHREADS; i++) {
209 		ret = pthread_join(th[i], NULL);
210 
211 		if (ret != 0) {
212 			UNRESOLVED(ret, "Failed to join a thread");
213 		}
214 	}
215 
216 	/* We've been asked to stop */
217 
218 	output("pthread_cancel stress test PASSED\n");
219 
220 	output(" - %llu threads canceled\n", canceled);
221 
222 	output(" - %llu threads ended\n", ended);
223 
224 	PASSED;
225 }
226