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@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 +---------------------------------------------------------------------*/
main(int argc,char ** argv)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 +---------------------------------------------------------------------*/
thread(void * parm)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 +---------------------------------------------------------------------*/
parse_args(int argc,char ** argv)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 +---------------------------------------------------------------------*/
sys_error(const char * msg,int line)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 +---------------------------------------------------------------------*/
error(const char * msg,int line)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