/* * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * FILE : openfile.c * DESCRIPTION : Create files and open simultaneously * HISTORY: * 03/21/2001 Paul Larson (plars@us.ibm.com) * -Ported * 11/01/2001 Mnaoj Iyer (manjo@austin.ibm.com) * - Modified. * added #inclide <unistd.h> * */ #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <unistd.h> #include "test.h" char *TCID = "openfile01"; /* Test program identifier. */ int TST_TOTAL = 1; #define MAXFILES 32768 #define MAXTHREADS 10 /* Control Structure */ struct cb { pthread_mutex_t m; pthread_cond_t init_cv; pthread_cond_t thr_cv; int thr_sleeping; } c; /* Global Variables */ int numthreads = 10, numfiles = 10; int debug = 0; char *filename = "FILETOOPEN"; void setup(void) { tst_tmpdir(); } void cleanup(void) { tst_rmdir(); } /* Procedures */ void *threads(void *thread_id); /* ************************************************************************** * MAIN PROCEDURE * ************************************************************************** */ int main(int argc, char *argv[]) { int i, opt, badopts = 0; FILE *fd; pthread_t th_id; char msg[80] = ""; extern char *optarg; while ((opt = getopt(argc, argv, "df:t:h")) != EOF) { switch ((char)opt) { case 'd': debug = 1; break; case 'f': numfiles = atoi(optarg); if (numfiles <= 0) badopts = 1; break; case 't': numthreads = atoi(optarg); if (numthreads <= 0) badopts = 1; break; case 'h': default: printf("Usage: openfile [-d] -f FILES -t THREADS\n"); _exit(1); } } if (badopts) { printf("Usage: openfile [-d] -f FILES -t THREADS\n"); _exit(1); } setup(); /* Check if numthreads is less than MAXFILES */ if (numfiles > MAXFILES) { sprintf(msg, "%s\nCannot use %d files", msg, numfiles); sprintf(msg, "%s, used %d files instead\n", msg, MAXFILES); numfiles = MAXFILES; } /* Check if numthreads is less than MAXTHREADS */ if (numthreads > MAXTHREADS) { sprintf(msg, "%s\nCannot use %d threads", msg, numthreads); sprintf(msg, "%s, used %d threads instead\n", msg, MAXTHREADS); numthreads = MAXTHREADS; } /* Create files */ if ((fd = fopen(filename, "w")) == NULL) { tst_resm(TFAIL, "Could not create file"); cleanup(); } /* Initialize thread control variables, lock & condition */ pthread_mutex_init(&c.m, NULL); pthread_cond_init(&c.init_cv, NULL); pthread_cond_init(&c.thr_cv, NULL); c.thr_sleeping = 0; /* Grab mutex lock */ if (pthread_mutex_lock(&c.m)) { tst_resm(TFAIL, "failed to grab mutex lock"); fclose(fd); unlink(filename); cleanup(); } printf("Creating Reading Threads\n"); /* Create threads */ for (i = 0; i < numthreads; i++) if (pthread_create(&th_id, NULL, threads, (void *)(uintptr_t) i)) { tst_resm(TFAIL, "failed creating a pthread; increase limits"); fclose(fd); unlink(filename); cleanup(); } /* Sleep until all threads are created */ while (c.thr_sleeping != numthreads) if (pthread_cond_wait(&c.init_cv, &c.m)) { tst_resm(TFAIL, "error while waiting for reading threads"); fclose(fd); unlink(filename); cleanup(); } /* Wake up all threads */ if (pthread_cond_broadcast(&c.thr_cv)) { tst_resm(TFAIL, "failed trying to wake up reading threads"); fclose(fd); unlink(filename); cleanup(); } /* Release mutex lock */ if (pthread_mutex_unlock(&c.m)) { tst_resm(TFAIL, "failed to release mutex lock"); fclose(fd); unlink(filename); cleanup(); } tst_resm(TPASS, "Threads are done reading"); fclose(fd); unlink(filename); cleanup(); _exit(0); } /* ************************************************************************** * OTHER PROCEDURES * ************************************************************************** */ void close_files(FILE * fd_list[], int len) { int i; for (i = 0; i < len; i++) { fclose(fd_list[i]); } } /* threads: Each thread opens the files specified */ void *threads(void *thread_id_) { int thread_id = (uintptr_t) thread_id_; char errmsg[80]; FILE *fd_list[MAXFILES]; int i; /* Open files */ for (i = 0; i < numfiles; i++) { if (debug) printf("Thread %d : Opening file number %d \n", thread_id, i); if ((fd_list[i] = fopen(filename, "rw")) == NULL) { sprintf(errmsg, "FAIL - Couldn't open file #%d", i); perror(errmsg); if (i > 0) { close_files(fd_list, i - 1); } unlink(filename); pthread_exit((void *)1); } } /* Grab mutex lock */ if (pthread_mutex_lock(&c.m)) { perror("FAIL - failed to grab mutex lock"); close_files(fd_list, numfiles); unlink(filename); pthread_exit((void *)1); } /* Check if you should wake up main thread */ if (++c.thr_sleeping == numthreads) if (pthread_cond_signal(&c.init_cv)) { perror("FAIL - failed to signal main thread"); close_files(fd_list, numfiles); unlink(filename); pthread_exit((void *)1); } /* Sleep until woken up */ if (pthread_cond_wait(&c.thr_cv, &c.m)) { perror("FAIL - failed to wake up correctly"); close_files(fd_list, numfiles); unlink(filename); pthread_exit((void *)1); } /* Release mutex lock */ if (pthread_mutex_unlock(&c.m)) { perror("FAIL - failed to release mutex lock"); close_files(fd_list, numfiles); unlink(filename); pthread_exit((void *)1); } /* Close file handles and exit */ close_files(fd_list, numfiles); unlink(filename); pthread_exit(NULL); }