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