| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| /* |
| * FILE : pth_str02.c |
| * DESCRIPTION : Create n threads |
| * HISTORY: |
| * 05/16/2001 Paul Larson (plars@us.ibm.com) |
| * -Ported |
| * |
| */ |
| |
| #include <pthread.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include "test.h" |
| |
| /* Defines |
| * |
| * DEFAULT_NUM_THREADS: Default number of threads to create, |
| * user can specifiy with [-n] command line option. |
| * |
| * USAGE: usage statement |
| */ |
| |
| #define DEFAULT_NUM_THREADS 10 |
| #define USAGE "\nUsage: %s [-l | -n num_threads] [-d]\n\n" \ |
| "\t-l Test as many as threads as possible\n" \ |
| "\t-n num_threads Number of threads to create\n" \ |
| "\t-d Debug option\n\n" |
| |
| /* |
| * Function prototypes |
| * |
| * sys_error (): System error message function |
| * error (): Error message function |
| * parse_args (): Parses command line arguments |
| */ |
| |
| static void sys_error (const char *, int); |
| static void error (const char *, int); |
| static void parse_args (int, char **); |
| void *thread (void *); |
| |
| /* |
| * Global Variables |
| */ |
| |
| int num_threads = DEFAULT_NUM_THREADS; |
| int test_limit = 0; |
| int debug = 0; |
| |
| char *TCID = "pth_str02"; |
| int TST_TOTAL = 1; |
| |
| /*---------------------------------------------------------------------+ |
| | main () | |
| | ==================================================================== | |
| | | |
| | Function: Main program (see prolog for more details) | |
| | | |
| +---------------------------------------------------------------------*/ |
| int main (int argc, char **argv) |
| { |
| /* |
| * Parse command line arguments and print out program header |
| */ |
| parse_args (argc, argv); |
| |
| if (test_limit) { |
| tst_resm (TINFO, "Creating as many threads as possible"); |
| } else { |
| tst_resm (TINFO, "Creating %d threads", num_threads); |
| } |
| thread (0); |
| |
| /* |
| * Program completed successfully... |
| */ |
| tst_resm(TPASS, "Test passed"); |
| exit (0); |
| } |
| |
| /*---------------------------------------------------------------------+ |
| | thread () | |
| | ==================================================================== | |
| | | |
| | Function: Recursively creates threads while num < num_threads | |
| | | |
| +---------------------------------------------------------------------*/ |
| void *thread (void *parm) |
| { |
| intptr_t num = (intptr_t) parm; |
| pthread_t th; |
| pthread_attr_t attr; |
| size_t stacksize = 1046528; |
| int pcrterr; |
| |
| /* |
| * Create threads while num < num_threads... |
| */ |
| if (test_limit || (num < num_threads)) { |
| |
| if (pthread_attr_init (&attr)) |
| sys_error ("pthread_attr_init failed", __LINE__); |
| if (pthread_attr_setstacksize (&attr, stacksize)) |
| sys_error ("pthread_attr_setstacksize failed", __LINE__); |
| if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE)) |
| sys_error ("pthread_attr_setdetachstate failed", __LINE__); |
| /************************************************/ |
| /* pthread_create does not touch errno. It RETURNS the error |
| * if it fails. errno has no bearing on this test, so it was |
| * removed and replaced with return value check(see man page |
| * for pthread_create(); |
| */ |
| pcrterr = pthread_create (&th, &attr, thread, (void *)(num + 1)); |
| if (pcrterr != 0) { |
| if (test_limit) { |
| tst_resm (TINFO, "Testing pthread limit, %d pthreads created.", (int)num); |
| pthread_exit(0); |
| } |
| if (pcrterr == EAGAIN) { |
| tst_resm (TINFO, "Thread [%d]: unable to create more threads!", (int)num); |
| return NULL; |
| } |
| else |
| sys_error ("pthread_create failed", __LINE__); |
| } |
| pthread_join (th, (void *) NULL); |
| } |
| |
| return 0; |
| /* |
| pthread_exit(0); |
| */ |
| } |
| |
| /*---------------------------------------------------------------------+ |
| | parse_args () | |
| | ==================================================================== | |
| | | |
| | Function: Parse the command line arguments & initialize global | |
| | variables. | |
| | | |
| +---------------------------------------------------------------------*/ |
| static void parse_args (int argc, char **argv) |
| { |
| int i; |
| int errflag = 0; |
| char *program_name = *argv; |
| |
| while ((i = getopt(argc, argv, "dln:?")) != EOF) { |
| switch (i) { |
| case 'd': /* debug option */ |
| debug++; |
| break; |
| case 'l': /* test pthread limit */ |
| test_limit++; |
| break; |
| case 'n': /* number of threads */ |
| num_threads = atoi (optarg); |
| break; |
| case '?': |
| errflag++; |
| break; |
| } |
| } |
| |
| /* If any errors exit program */ |
| if (errflag) { |
| fprintf (stderr, USAGE, program_name); |
| exit (2); |
| } |
| } |
| |
| /*---------------------------------------------------------------------+ |
| | sys_error () | |
| | ==================================================================== | |
| | | |
| | Function: Creates system error message and calls error () | |
| | | |
| +---------------------------------------------------------------------*/ |
| static void sys_error (const char *msg, int line) |
| { |
| char syserr_msg [256]; |
| |
| sprintf (syserr_msg, "%s: %s\n", msg, strerror (errno)); |
| error (syserr_msg, line); |
| } |
| |
| /*---------------------------------------------------------------------+ |
| | error () | |
| | ==================================================================== | |
| | | |
| | Function: Prints out message and exits... | |
| | | |
| +---------------------------------------------------------------------*/ |
| static void error (const char *msg, int line) |
| { |
| fprintf (stderr, "ERROR [line: %d] %s\n", line, msg); |
| tst_resm(TFAIL, "Test failed"); |
| exit (-1); |
| } |