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