1 /* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * FILE : pth_str02.c 22 * DESCRIPTION : Create n threads 23 * HISTORY: 24 * 05/16/2001 Paul Larson (plars (at) us.ibm.com) 25 * -Ported 26 * 27 */ 28 29 #include <pthread.h> 30 #include <stdio.h> 31 #include <unistd.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 #include "test.h" 36 37 /* Defines 38 * 39 * DEFAULT_NUM_THREADS: Default number of threads to create, 40 * user can specifiy with [-n] command line option. 41 * 42 * USAGE: usage statement 43 */ 44 45 #define DEFAULT_NUM_THREADS 10 46 #define USAGE "\nUsage: %s [-l | -n num_threads] [-d]\n\n" \ 47 "\t-l Test as many as threads as possible\n" \ 48 "\t-n num_threads Number of threads to create\n" \ 49 "\t-d Debug option\n\n" 50 51 /* 52 * Function prototypes 53 * 54 * sys_error (): System error message function 55 * error (): Error message function 56 * parse_args (): Parses command line arguments 57 */ 58 59 static void sys_error(const char *, int); 60 static void error(const char *, int); 61 static void parse_args(int, char **); 62 void *thread(void *); 63 64 /* 65 * Global Variables 66 */ 67 68 int num_threads = DEFAULT_NUM_THREADS; 69 int test_limit = 0; 70 int debug = 0; 71 72 char *TCID = "pth_str02"; 73 int TST_TOTAL = 1; 74 75 /*---------------------------------------------------------------------+ 76 | main () | 77 | ==================================================================== | 78 | | 79 | Function: Main program (see prolog for more details) | 80 | | 81 +---------------------------------------------------------------------*/ 82 int main(int argc, char **argv) 83 { 84 /* 85 * Parse command line arguments and print out program header 86 */ 87 parse_args(argc, argv); 88 89 if (test_limit) { 90 tst_resm(TINFO, "Creating as many threads as possible"); 91 } else { 92 tst_resm(TINFO, "Creating %d threads", num_threads); 93 } 94 thread(0); 95 96 /* 97 * Program completed successfully... 98 */ 99 tst_resm(TPASS, "Test passed"); 100 exit(0); 101 } 102 103 /*---------------------------------------------------------------------+ 104 | thread () | 105 | ==================================================================== | 106 | | 107 | Function: Recursively creates threads while num < num_threads | 108 | | 109 +---------------------------------------------------------------------*/ 110 void *thread(void *parm) 111 { 112 intptr_t num = (intptr_t) parm; 113 pthread_t th; 114 pthread_attr_t attr; 115 size_t stacksize = 1046528; 116 int pcrterr; 117 118 /* 119 * Create threads while num < num_threads... 120 */ 121 if (test_limit || (num < num_threads)) { 122 123 if (pthread_attr_init(&attr)) 124 sys_error("pthread_attr_init failed", __LINE__); 125 if (pthread_attr_setstacksize(&attr, stacksize)) 126 sys_error("pthread_attr_setstacksize failed", __LINE__); 127 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) 128 sys_error("pthread_attr_setdetachstate failed", 129 __LINE__); 130 /************************************************/ 131 /* pthread_create does not touch errno. It RETURNS the error 132 * if it fails. errno has no bearing on this test, so it was 133 * removed and replaced with return value check(see man page 134 * for pthread_create(); 135 */ 136 pcrterr = pthread_create(&th, &attr, thread, (void *)(num + 1)); 137 if (pcrterr != 0) { 138 if (test_limit) { 139 tst_resm(TINFO, 140 "Testing pthread limit, %d pthreads created.", 141 (int)num); 142 pthread_exit(0); 143 } 144 if (pcrterr == EAGAIN) { 145 tst_resm(TINFO, 146 "Thread [%d]: unable to create more threads!", 147 (int)num); 148 return NULL; 149 } else 150 sys_error("pthread_create failed", __LINE__); 151 } 152 pthread_join(th, NULL); 153 } 154 155 return 0; 156 /* 157 pthread_exit(0); 158 */ 159 } 160 161 /*---------------------------------------------------------------------+ 162 | parse_args () | 163 | ==================================================================== | 164 | | 165 | Function: Parse the command line arguments & initialize global | 166 | variables. | 167 | | 168 +---------------------------------------------------------------------*/ 169 static void parse_args(int argc, char **argv) 170 { 171 int i; 172 int errflag = 0; 173 char *program_name = *argv; 174 175 while ((i = getopt(argc, argv, "dln:?")) != EOF) { 176 switch (i) { 177 case 'd': /* debug option */ 178 debug++; 179 break; 180 case 'l': /* test pthread limit */ 181 test_limit++; 182 break; 183 case 'n': /* number of threads */ 184 num_threads = atoi(optarg); 185 break; 186 case '?': 187 errflag++; 188 break; 189 } 190 } 191 192 /* If any errors exit program */ 193 if (errflag) { 194 fprintf(stderr, USAGE, program_name); 195 exit(2); 196 } 197 } 198 199 /*---------------------------------------------------------------------+ 200 | sys_error () | 201 | ==================================================================== | 202 | | 203 | Function: Creates system error message and calls error () | 204 | | 205 +---------------------------------------------------------------------*/ 206 static void sys_error(const char *msg, int line) 207 { 208 char syserr_msg[256]; 209 210 sprintf(syserr_msg, "%s: %s\n", msg, strerror(errno)); 211 error(syserr_msg, line); 212 } 213 214 /*---------------------------------------------------------------------+ 215 | error () | 216 | ==================================================================== | 217 | | 218 | Function: Prints out message and exits... | 219 | | 220 +---------------------------------------------------------------------*/ 221 static void error(const char *msg, int line) 222 { 223 fprintf(stderr, "ERROR [line: %d] %s\n", line, msg); 224 tst_resm(TFAIL, "Test failed"); 225 exit(-1); 226 } 227