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