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