• 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 /********************************************************************************************/
30 /****************************** standard includes *****************************************/
31 /********************************************************************************************/
32 #include <pthread.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 
39 #include <errno.h>
40 #include <signal.h>
41 
42 /********************************************************************************************/
43 /******************************   Test framework   *****************************************/
44 /********************************************************************************************/
45 #include "testfrmw.h"
46 #include "testfrmw.c"
47 /* This header is responsible for defining the following macros:
48  * UNRESOLVED(ret, descr);
49  *    where descr is a description of the error and ret is an int (error code for example)
50  * FAILED(descr);
51  *    where descr is a short text saying why the test has failed.
52  * PASSED();
53  *    No parameter.
54  *
55  * Both three macros shall terminate the calling process.
56  * The testcase shall not terminate in any other maneer.
57  *
58  * The other file defines the functions
59  * void output_init()
60  * void output(char * string, ...)
61  *
62  * Those may be used to output information.
63  */
64 
65 /********************************************************************************************/
66 /********************************** Configuration ******************************************/
67 /********************************************************************************************/
68 #ifndef VERBOSE
69 #define VERBOSE 1
70 #endif
71 
72 #define NTHREADS 30
73 
74 /********************************************************************************************/
75 /***********************************    Test cases  *****************************************/
76 /********************************************************************************************/
77 
78 static char do_it = 1;
79 
80 /* Handler for user request to terminate */
sighdl(int sig)81 static void sighdl(int sig)
82 {
83 	do {
84 		do_it = 0;
85 	}
86 	while (do_it);
87 }
88 
89 static long long canceled, ended;
90 
91 /* The canceled thread */
th(void * arg)92 static void *th(void *arg)
93 {
94 	int ret = 0;
95 	ret = pthread_barrier_wait(arg);
96 
97 	if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
98 		UNRESOLVED(ret, "Failed to wait for the barrier");
99 	}
100 
101 	return NULL;
102 }
103 
104 /* Thread function */
threaded(void * arg)105 static void *threaded(void *arg)
106 {
107 	int ret = 0;
108 	pthread_t child;
109 
110 	/* Initialize the barrier */
111 	ret = pthread_barrier_init(arg, NULL, 2);
112 
113 	if (ret != 0) {
114 		UNRESOLVED(ret, "Failed to initialize a barrier");
115 	}
116 
117 	while (do_it) {
118 		/* Create the thread */
119 		ret = pthread_create(&child, NULL, th, arg);
120 
121 		if (ret != 0) {
122 			UNRESOLVED(ret, "Thread creation failed");
123 		}
124 
125 		/* Synchronize */
126 		ret = pthread_barrier_wait(arg);
127 
128 		if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) {
129 			UNRESOLVED(ret, "Failed to wait for the barrier");
130 		}
131 
132 		/* Cancel the thread */
133 		ret = pthread_cancel(child);
134 
135 		if (ret == 0)
136 			canceled++;
137 		else
138 			ended++;
139 
140 		/* Join the thread */
141 		ret = pthread_join(child, NULL);
142 
143 		if (ret != 0) {
144 			UNRESOLVED(ret, "Unable to join the child");
145 		}
146 
147 	}
148 
149 	/* Destroy the barrier */
150 	ret = pthread_barrier_destroy(arg);
151 
152 	if (ret != 0) {
153 		UNRESOLVED(ret, "Failed to destroy a barrier");
154 	}
155 
156 	return NULL;
157 }
158 
159 /* Main function */
main(int argc,char * argv[])160 int main(int argc, char *argv[])
161 {
162 	int ret = 0, i;
163 
164 	struct sigaction sa;
165 
166 	pthread_t th[NTHREADS];
167 	pthread_barrier_t b[NTHREADS];
168 
169 	/* Initialize output routine */
170 	output_init();
171 
172 	/* Register the signal handler for SIGUSR1 */
173 	sigemptyset(&sa.sa_mask);
174 
175 	sa.sa_flags = 0;
176 
177 	sa.sa_handler = sighdl;
178 
179 	if ((ret = sigaction(SIGUSR1, &sa, NULL))) {
180 		UNRESOLVED(ret, "Unable to register signal handler");
181 	}
182 
183 	if ((ret = sigaction(SIGALRM, &sa, NULL))) {
184 		UNRESOLVED(ret, "Unable to register signal handler");
185 	}
186 #if VERBOSE > 1
187 	output("[parent] Signal handler registered\n");
188 
189 #endif
190 
191 	for (i = 0; i < NTHREADS; i++) {
192 		ret = pthread_create(&th[i], NULL, threaded, &b[i]);
193 
194 		if (ret != 0) {
195 			UNRESOLVED(ret, "Failed to create a thread");
196 		}
197 	}
198 
199 #if VERBOSE > 1
200 	output("[parent] All threads are running\n");
201 
202 #endif
203 
204 	/* Then join */
205 	for (i = 0; i < NTHREADS; i++) {
206 		ret = pthread_join(th[i], NULL);
207 
208 		if (ret != 0) {
209 			UNRESOLVED(ret, "Failed to join a thread");
210 		}
211 	}
212 
213 	/* We've been asked to stop */
214 
215 	output("pthread_cancel stress test PASSED\n");
216 
217 	output(" - %llu threads canceled\n", canceled);
218 
219 	output(" - %llu threads ended\n", ended);
220 
221 	PASSED;
222 }
223