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 char do_it = 1;
79
80 /* Handler for user request to terminate */
sighdl(int sig)81 void sighdl(int sig)
82 {
83 do {
84 do_it = 0;
85 }
86 while (do_it);
87 }
88
89 long long canceled, ended;
90
91 /* The canceled thread */
th(void * arg)92 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 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