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 */ 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 */ 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 */ 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 */ 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