1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 06/20/2001 Robbie Williamson (robbiew (at) us.ibm.com) 4 * 11/08/2001 Manoj Iyer (manjo (at) austin.ibm.com) 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * Usage: stress_cd [-n n] [-f file] [-m xx] [-d] 23 * where: 24 * -n n Number of threads to create 25 * -f file File or device to read from 26 * -m xx Number of MB to read from file 27 * -b xx Number of bytes to read from file 28 * -d Enable debugging messages 29 */ 30 31 #include <pthread.h> 32 #include <fcntl.h> 33 #include <stdlib.h> 34 #include <stdio.h> 35 #include <assert.h> 36 #include <errno.h> 37 #include <sys/types.h> 38 #include <unistd.h> 39 #include <string.h> 40 41 #define DEFAULT_NUM_THREADS 10 42 #define DEFAULT_NUM_BYTES (1024*1024*100) /* 100Mb */ 43 #define DEFAULT_FILE "/dev/cdrom" 44 45 static void sys_error(const char *, int); 46 static void parse_args(int, char **); 47 static void *thread(int *); 48 static int read_data(int, unsigned long *); 49 50 static int num_threads = DEFAULT_NUM_THREADS; 51 static int num_bytes = DEFAULT_NUM_BYTES; 52 static char *file = DEFAULT_FILE; 53 static unsigned long checksum; 54 static int debug; 55 56 int main(int argc, char **argv) 57 { 58 pthread_attr_t attr; 59 int rc = 0, i; 60 61 /* Parse command line arguments and print out program header */ 62 parse_args(argc, argv); 63 64 /* Read data from CDROM & compute checksum */ 65 read_data(0, &checksum); 66 if (debug) 67 printf("Thread [main] checksum: %-#12lx\n", checksum); 68 69 if (pthread_attr_init(&attr)) 70 sys_error("pthread_attr_init failed", __LINE__); 71 if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) 72 sys_error("pthread_attr_setdetachstate failed", __LINE__); 73 74 printf("\tThread [main] Creating %d threads\n", num_threads); 75 76 pthread_t array[num_threads]; 77 int arg[num_threads]; 78 79 for (i = 0; i < num_threads; i++) { 80 if (debug) 81 printf("\tThread [main]: creating thread %d\n", i + 1); 82 arg[i] = i + 1; 83 if (pthread_create((pthread_t *)&array[i], &attr, 84 (void *)thread, (void *)&arg[i])) { 85 if (errno == EAGAIN) { 86 fprintf(stderr, 87 "\tThread [main]: unable to create " 88 "thread %d\n", i); 89 } else { 90 sys_error("pthread_create failed", __LINE__); 91 } 92 } 93 if (debug) 94 printf("\tThread [main]: created thread %d\n", i + 1); 95 } 96 if (pthread_attr_destroy(&attr)) 97 sys_error("pthread_attr_destroy failed", __LINE__); 98 99 for (i = 0; i < num_threads; i++) { 100 void *exit_value; 101 printf("\tThread [main]: waiting for thread: %d\n", i + 1); 102 if (pthread_join(array[i], &exit_value)) 103 sys_error("pthread_join failed", __LINE__); 104 105 if (debug) 106 printf("\tThread [%d]: return %ld\n", i + 1, 107 (long)exit_value); 108 rc += (long)exit_value; 109 } 110 111 if (rc != 0) { 112 printf("test failed!\n"); 113 exit(-1); 114 } 115 116 printf("\tThread [main] All threads completed successfully...\n"); 117 exit(0); 118 } 119 120 static void *thread(int *parm) 121 { 122 int num = *parm; 123 unsigned long cksum = 0; 124 125 if (debug) 126 printf("\tThread [%d]: begin\n", num); 127 128 read_data(num, &cksum); 129 if (checksum != cksum) { 130 fprintf(stderr, "\tThread [%d]: checksum mismatch!\n", num); 131 pthread_exit((void *)-1); 132 } 133 134 if (debug) 135 printf("\tThread [%d]: done\n", num); 136 137 pthread_exit(NULL); 138 } 139 140 static int read_data(int num, unsigned long *cksum) 141 { 142 int fd; 143 const int bufSize = 1024; 144 char *buffer; 145 int bytes_read = 0; 146 int n; 147 char *p; 148 149 if (debug) 150 printf("\tThread [%d]: read_data()\n", num); 151 152 if ((fd = open(file, O_RDONLY, NULL)) < 0) 153 sys_error("open failed /dev/cdrom", __LINE__); 154 155 buffer = malloc(sizeof(char) * bufSize); 156 assert(buffer); 157 158 lseek(fd, 1024 * 36, SEEK_SET); 159 while (bytes_read < num_bytes) { 160 n = read(fd, buffer, bufSize); 161 if (n < 0) 162 sys_error("read failed", __LINE__); 163 else if (n == 0) 164 sys_error("End of file", __LINE__); 165 bytes_read += n; 166 167 for (p = buffer; p < buffer + n; p++) 168 *cksum += *p; 169 170 if (debug) 171 printf("\tThread [%d] bytes read: %5d checksum: " 172 "%-#12lx\n", num, bytes_read, *cksum); 173 } 174 free(buffer); 175 176 if (debug) 177 printf("\tThread [%d] bytes read: %5d checksum: %-#12lx\n", 178 num, bytes_read, *cksum); 179 180 if (close(fd) < 0) 181 sys_error("close failed", __LINE__); 182 183 if (debug) 184 printf("\tThread [%d]: done\n", num); 185 186 return (0); 187 } 188 189 static void parse_args(int argc, char **argv) 190 { 191 int i; 192 int errflag = 0; 193 char *program_name = *argv; 194 extern char *optarg; /* Command line option */ 195 196 while ((i = getopt(argc, argv, "df:n:b:m:?")) != EOF) { 197 switch (i) { 198 case 'd': /* debug option */ 199 debug++; 200 break; 201 case 'f': /* file to read from */ 202 file = optarg; 203 break; 204 case 'm': /* num MB to read */ 205 num_bytes = atoi(optarg) * 1024 * 1024; 206 break; 207 case 'b': /* num bytes to read */ 208 num_bytes = atoi(optarg); 209 break; 210 case 'n': /* number of threads */ 211 num_threads = atoi(optarg); 212 break; 213 case '?': /* help */ 214 errflag++; 215 break; 216 } 217 } 218 if (num_bytes < 0) { 219 errflag++; 220 fprintf(stderr, "ERROR: num_bytes must be greater than 0"); 221 } 222 if (num_threads < 0) { 223 errflag++; 224 fprintf(stderr, "ERROR: num_threads must be greater than 0"); 225 } 226 227 if (errflag) { 228 fprintf(stderr, "\nUsage: %s" 229 " [-n xx] [-m|b xx] [-d]\n\n" 230 "\t-n xx Number of threads to create (up to %d)\n" 231 "\t-f file File to read from\n" 232 "\t-m xx Number of MB to read\n" 233 "\t-b xx Number of bytes to read\n" 234 "\t-d Debug option\n", program_name, 235 DEFAULT_NUM_THREADS); 236 exit(2); 237 } 238 } 239 240 static void sys_error(const char *msg, int line) 241 { 242 fprintf(stderr, "ERROR [%d: %s: %s]\n", line, msg, strerror(errno)); 243 exit(-1); 244 } 245