Home | History | Annotate | Download | only in pthreads
      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