1 /* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <getopt.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/stat.h> 13 #include <unistd.h> 14 15 #include <OS.h> 16 17 #include "time_stats.h" 18 19 20 #define SCHEDULING_ANALYSIS_BUFFER_SIZE 10 * 1024 * 1024 21 22 23 extern const char* __progname; 24 25 static const char* kUsage = 26 "Usage: %s [ <options> ] <command line>\n" 27 "Executes the given command line <command line> and print an analysis of\n" 28 "the user and kernel times of all threads that ran during that time.\n" 29 "\n" 30 "Options:\n" 31 " -b <size> - When doing scheduling analysis: the size of the buffer\n" 32 " used (in MB)\n" 33 " -h, --help - Print this usage info.\n" 34 " -o <output> - Print the results to file <output>.\n" 35 " -s - Also perform a scheduling analysis over the time the\n" 36 " child process ran. This requires that scheduler kernel\n" 37 " tracing had been enabled at compile time.\n" 38 ; 39 40 41 static void 42 print_usage_and_exit(bool error) 43 { 44 fprintf(error ? stderr : stdout, kUsage, __progname); 45 exit(error ? 1 : 0); 46 } 47 48 49 int 50 main(int argc, const char* const* argv) 51 { 52 const char* outputFile = NULL; 53 bool schedulingAnalysis = false; 54 size_t bufferSize = SCHEDULING_ANALYSIS_BUFFER_SIZE; 55 56 while (true) { 57 static struct option sLongOptions[] = { 58 { "help", no_argument, 0, 'h' }, 59 { "output", required_argument, 0, 'o' }, 60 { 0, 0, 0, 0 } 61 }; 62 63 opterr = 0; // don't print errors 64 int c = getopt_long(argc, (char**)argv, "+b:ho:s", sLongOptions, NULL); 65 if (c == -1) 66 break; 67 68 switch (c) { 69 case 'b': 70 bufferSize = atol(optarg); 71 if (bufferSize < 1 || bufferSize > 1024) { 72 fprintf(stderr, "Error: Invalid buffer size. Should be " 73 "between 1 and 1024 MB\n"); 74 exit(1); 75 } 76 bufferSize *= 1024 * 1024; 77 break; 78 case 'h': 79 print_usage_and_exit(false); 80 break; 81 case 'o': 82 outputFile = optarg; 83 break; 84 case 's': 85 schedulingAnalysis = true; 86 break; 87 88 default: 89 print_usage_and_exit(true); 90 break; 91 } 92 } 93 94 if (optind >= argc) 95 print_usage_and_exit(true); 96 97 // open output file, if specified 98 int outFD = -1; 99 if (outputFile != NULL) { 100 outFD = open(outputFile, O_WRONLY | O_CREAT | O_TRUNC, 101 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH); 102 if (outFD < 0) { 103 fprintf(stderr, "Error: Failed to open \"%s\": %s\n", outputFile, 104 strerror(errno)); 105 exit(1); 106 } 107 } 108 109 do_timing_analysis(argc - optind, argv + optind, schedulingAnalysis, outFD, 110 bufferSize); 111 112 return 0; 113 } 114