1*10673SKrishnendu.Sadhukhan@Sun.COM /* 2*10673SKrishnendu.Sadhukhan@Sun.COM * CDDL HEADER START 3*10673SKrishnendu.Sadhukhan@Sun.COM * 4*10673SKrishnendu.Sadhukhan@Sun.COM * The contents of this file are subject to the terms of the 5*10673SKrishnendu.Sadhukhan@Sun.COM * Common Development and Distribution License (the "License"). 6*10673SKrishnendu.Sadhukhan@Sun.COM * You may not use this file except in compliance with the License. 7*10673SKrishnendu.Sadhukhan@Sun.COM * 8*10673SKrishnendu.Sadhukhan@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*10673SKrishnendu.Sadhukhan@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*10673SKrishnendu.Sadhukhan@Sun.COM * See the License for the specific language governing permissions 11*10673SKrishnendu.Sadhukhan@Sun.COM * and limitations under the License. 12*10673SKrishnendu.Sadhukhan@Sun.COM * 13*10673SKrishnendu.Sadhukhan@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*10673SKrishnendu.Sadhukhan@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*10673SKrishnendu.Sadhukhan@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*10673SKrishnendu.Sadhukhan@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*10673SKrishnendu.Sadhukhan@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*10673SKrishnendu.Sadhukhan@Sun.COM * 19*10673SKrishnendu.Sadhukhan@Sun.COM * CDDL HEADER END 20*10673SKrishnendu.Sadhukhan@Sun.COM */ 21*10673SKrishnendu.Sadhukhan@Sun.COM /* 22*10673SKrishnendu.Sadhukhan@Sun.COM * Copyright (c) 2008-2009, Intel Corporation. 23*10673SKrishnendu.Sadhukhan@Sun.COM * All Rights Reserved. 24*10673SKrishnendu.Sadhukhan@Sun.COM */ 25*10673SKrishnendu.Sadhukhan@Sun.COM 26*10673SKrishnendu.Sadhukhan@Sun.COM #include <unistd.h> 27*10673SKrishnendu.Sadhukhan@Sun.COM #include <getopt.h> 28*10673SKrishnendu.Sadhukhan@Sun.COM #include <stdio.h> 29*10673SKrishnendu.Sadhukhan@Sun.COM #include <string.h> 30*10673SKrishnendu.Sadhukhan@Sun.COM #include <stdlib.h> 31*10673SKrishnendu.Sadhukhan@Sun.COM #include <limits.h> 32*10673SKrishnendu.Sadhukhan@Sun.COM #include <libgen.h> 33*10673SKrishnendu.Sadhukhan@Sun.COM #include <signal.h> 34*10673SKrishnendu.Sadhukhan@Sun.COM #include "latencytop.h" 35*10673SKrishnendu.Sadhukhan@Sun.COM 36*10673SKrishnendu.Sadhukhan@Sun.COM #define CMPOPT(a, b) strncmp((a), (b), sizeof (b)) 37*10673SKrishnendu.Sadhukhan@Sun.COM 38*10673SKrishnendu.Sadhukhan@Sun.COM lt_config_t g_config; 39*10673SKrishnendu.Sadhukhan@Sun.COM 40*10673SKrishnendu.Sadhukhan@Sun.COM typedef enum { 41*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_INTERVAL, 42*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_LOG_FILE, 43*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_LOG_LEVEL, 44*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_LOG_INTERVAL, 45*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_CONFIG_FILE, 46*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_FILTER, 47*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_SCHED, 48*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_SOBJ, 49*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_LOW, 50*10673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT__LAST /* Must be last one */ 51*10673SKrishnendu.Sadhukhan@Sun.COM } lt_cmd_option_id_t; 52*10673SKrishnendu.Sadhukhan@Sun.COM 53*10673SKrishnendu.Sadhukhan@Sun.COM /* 54*10673SKrishnendu.Sadhukhan@Sun.COM * Check for duplicate command line options. 55*10673SKrishnendu.Sadhukhan@Sun.COM * Returns TRUE if duplicate options with different values are found, 56*10673SKrishnendu.Sadhukhan@Sun.COM * returns FALSE otherwise. 57*10673SKrishnendu.Sadhukhan@Sun.COM */ 58*10673SKrishnendu.Sadhukhan@Sun.COM static int 59*10673SKrishnendu.Sadhukhan@Sun.COM check_opt_dup(lt_cmd_option_id_t id, uint64_t value) { 60*10673SKrishnendu.Sadhukhan@Sun.COM 61*10673SKrishnendu.Sadhukhan@Sun.COM static int opt_set[(int)LT_CMDOPT__LAST]; 62*10673SKrishnendu.Sadhukhan@Sun.COM static uint64_t opt_val[(int)LT_CMDOPT__LAST]; 63*10673SKrishnendu.Sadhukhan@Sun.COM 64*10673SKrishnendu.Sadhukhan@Sun.COM const char *errmsg[] = { 65*10673SKrishnendu.Sadhukhan@Sun.COM "-t is set more than once with different values.", 66*10673SKrishnendu.Sadhukhan@Sun.COM "-o is set more than once.", 67*10673SKrishnendu.Sadhukhan@Sun.COM "-k is set more than once with different values.", 68*10673SKrishnendu.Sadhukhan@Sun.COM "-l is set more than once with different values.", 69*10673SKrishnendu.Sadhukhan@Sun.COM "-c is set more than once.", 70*10673SKrishnendu.Sadhukhan@Sun.COM "-f [no]filter is set more than once with different values.", 71*10673SKrishnendu.Sadhukhan@Sun.COM "-f [no]sched is set more than once with different values.", 72*10673SKrishnendu.Sadhukhan@Sun.COM "-f [no]sobj is set more than once with different values.", 73*10673SKrishnendu.Sadhukhan@Sun.COM "-f [no]low is set more than once with different values.", 74*10673SKrishnendu.Sadhukhan@Sun.COM }; 75*10673SKrishnendu.Sadhukhan@Sun.COM 76*10673SKrishnendu.Sadhukhan@Sun.COM g_assert(sizeof (errmsg)/sizeof (errmsg[0]) == (int)LT_CMDOPT__LAST); 77*10673SKrishnendu.Sadhukhan@Sun.COM 78*10673SKrishnendu.Sadhukhan@Sun.COM if (!opt_set[(int)id]) { 79*10673SKrishnendu.Sadhukhan@Sun.COM opt_set[(int)id] = TRUE; 80*10673SKrishnendu.Sadhukhan@Sun.COM opt_val[(int)id] = value; 81*10673SKrishnendu.Sadhukhan@Sun.COM return (FALSE); 82*10673SKrishnendu.Sadhukhan@Sun.COM } 83*10673SKrishnendu.Sadhukhan@Sun.COM 84*10673SKrishnendu.Sadhukhan@Sun.COM if (opt_val[(int)id] != value) { 85*10673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "%s\n", errmsg[(int)id]); 86*10673SKrishnendu.Sadhukhan@Sun.COM return (TRUE); 87*10673SKrishnendu.Sadhukhan@Sun.COM } 88*10673SKrishnendu.Sadhukhan@Sun.COM 89*10673SKrishnendu.Sadhukhan@Sun.COM return (FALSE); 90*10673SKrishnendu.Sadhukhan@Sun.COM } 91*10673SKrishnendu.Sadhukhan@Sun.COM 92*10673SKrishnendu.Sadhukhan@Sun.COM /* 93*10673SKrishnendu.Sadhukhan@Sun.COM * Print command-line help message. 94*10673SKrishnendu.Sadhukhan@Sun.COM */ 95*10673SKrishnendu.Sadhukhan@Sun.COM static void 96*10673SKrishnendu.Sadhukhan@Sun.COM print_usage(const char *execname, int long_help) 97*10673SKrishnendu.Sadhukhan@Sun.COM { 98*10673SKrishnendu.Sadhukhan@Sun.COM char buffer[PATH_MAX]; 99*10673SKrishnendu.Sadhukhan@Sun.COM (void) snprintf(buffer, sizeof (buffer), "%s", execname); 100*10673SKrishnendu.Sadhukhan@Sun.COM 101*10673SKrishnendu.Sadhukhan@Sun.COM if (!long_help) { 102*10673SKrishnendu.Sadhukhan@Sun.COM /* Print short help to stderr. */ 103*10673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "Usage: %s [option(s)], ", 104*10673SKrishnendu.Sadhukhan@Sun.COM basename(buffer)); 105*10673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "use '%s -h' for details.\n", 106*10673SKrishnendu.Sadhukhan@Sun.COM basename(buffer)); 107*10673SKrishnendu.Sadhukhan@Sun.COM return; 108*10673SKrishnendu.Sadhukhan@Sun.COM } 109*10673SKrishnendu.Sadhukhan@Sun.COM 110*10673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Usage: %s [option(s)]\n", basename(buffer)); 111*10673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Options:\n" 112*10673SKrishnendu.Sadhukhan@Sun.COM " -h, --help\n" 113*10673SKrishnendu.Sadhukhan@Sun.COM " Print this help.\n" 114*10673SKrishnendu.Sadhukhan@Sun.COM " -t, --interval TIME\n" 115*10673SKrishnendu.Sadhukhan@Sun.COM " Set refresh interval to TIME. " 116*10673SKrishnendu.Sadhukhan@Sun.COM "Valid range [1...60] seconds, default = 5\n" 117*10673SKrishnendu.Sadhukhan@Sun.COM /* 118*10673SKrishnendu.Sadhukhan@Sun.COM * Option "-c, --config FILE" is not user-visible for now. 119*10673SKrishnendu.Sadhukhan@Sun.COM * When we have chance to properly document the format of translation 120*10673SKrishnendu.Sadhukhan@Sun.COM * rules, we'll make it user-visible. 121*10673SKrishnendu.Sadhukhan@Sun.COM */ 122*10673SKrishnendu.Sadhukhan@Sun.COM " -o, --output-log-file FILE\n" 123*10673SKrishnendu.Sadhukhan@Sun.COM " Output kernel log to FILE. Default = " 124*10673SKrishnendu.Sadhukhan@Sun.COM DEFAULT_KLOG_FILE "\n" 125*10673SKrishnendu.Sadhukhan@Sun.COM " -k, --kernel-log-level LEVEL\n" 126*10673SKrishnendu.Sadhukhan@Sun.COM " Set kernel log level to LEVEL.\n" 127*10673SKrishnendu.Sadhukhan@Sun.COM " 0(default) = None, 1 = Unmapped, 2 = Mapped, 3 = All.\n" 128*10673SKrishnendu.Sadhukhan@Sun.COM " -f, --feature [no]feature1,[no]feature2,...\n" 129*10673SKrishnendu.Sadhukhan@Sun.COM " Enable/disable features in LatencyTOP.\n" 130*10673SKrishnendu.Sadhukhan@Sun.COM " [no]filter:\n" 131*10673SKrishnendu.Sadhukhan@Sun.COM " Filter large interruptible latencies, e.g. sleep.\n" 132*10673SKrishnendu.Sadhukhan@Sun.COM " [no]sched:\n" 133*10673SKrishnendu.Sadhukhan@Sun.COM " Monitors sched (PID=0).\n" 134*10673SKrishnendu.Sadhukhan@Sun.COM " [no]sobj:\n" 135*10673SKrishnendu.Sadhukhan@Sun.COM " Monitors synchronization objects.\n" 136*10673SKrishnendu.Sadhukhan@Sun.COM " [no]low:\n" 137*10673SKrishnendu.Sadhukhan@Sun.COM " Lower overhead by sampling small latencies.\n" 138*10673SKrishnendu.Sadhukhan@Sun.COM " -l, --log-period TIME\n" 139*10673SKrishnendu.Sadhukhan@Sun.COM " Write and restart log every TIME seconds, TIME >= 60\n"); 140*10673SKrishnendu.Sadhukhan@Sun.COM } 141*10673SKrishnendu.Sadhukhan@Sun.COM 142*10673SKrishnendu.Sadhukhan@Sun.COM /* 143*10673SKrishnendu.Sadhukhan@Sun.COM * Properly exit latencytop when it receives SIGINT or SIGTERM. 144*10673SKrishnendu.Sadhukhan@Sun.COM */ 145*10673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */ 146*10673SKrishnendu.Sadhukhan@Sun.COM static void 147*10673SKrishnendu.Sadhukhan@Sun.COM signal_handler(int sig) 148*10673SKrishnendu.Sadhukhan@Sun.COM { 149*10673SKrishnendu.Sadhukhan@Sun.COM lt_gpipe_break("q"); 150*10673SKrishnendu.Sadhukhan@Sun.COM } 151*10673SKrishnendu.Sadhukhan@Sun.COM 152*10673SKrishnendu.Sadhukhan@Sun.COM /* 153*10673SKrishnendu.Sadhukhan@Sun.COM * Convert string to integer. It returns error if extra characters are found. 154*10673SKrishnendu.Sadhukhan@Sun.COM */ 155*10673SKrishnendu.Sadhukhan@Sun.COM static int 156*10673SKrishnendu.Sadhukhan@Sun.COM to_int(const char *str, int *result) 157*10673SKrishnendu.Sadhukhan@Sun.COM { 158*10673SKrishnendu.Sadhukhan@Sun.COM char *tail = NULL; 159*10673SKrishnendu.Sadhukhan@Sun.COM long ret; 160*10673SKrishnendu.Sadhukhan@Sun.COM 161*10673SKrishnendu.Sadhukhan@Sun.COM if (str == NULL || result == NULL) { 162*10673SKrishnendu.Sadhukhan@Sun.COM return (-1); 163*10673SKrishnendu.Sadhukhan@Sun.COM } 164*10673SKrishnendu.Sadhukhan@Sun.COM 165*10673SKrishnendu.Sadhukhan@Sun.COM ret = strtol(str, &tail, 10); 166*10673SKrishnendu.Sadhukhan@Sun.COM 167*10673SKrishnendu.Sadhukhan@Sun.COM if (tail != NULL && *tail != '\0') { 168*10673SKrishnendu.Sadhukhan@Sun.COM return (-1); 169*10673SKrishnendu.Sadhukhan@Sun.COM } 170*10673SKrishnendu.Sadhukhan@Sun.COM 171*10673SKrishnendu.Sadhukhan@Sun.COM *result = (int)ret; 172*10673SKrishnendu.Sadhukhan@Sun.COM 173*10673SKrishnendu.Sadhukhan@Sun.COM return (0); 174*10673SKrishnendu.Sadhukhan@Sun.COM } 175*10673SKrishnendu.Sadhukhan@Sun.COM 176*10673SKrishnendu.Sadhukhan@Sun.COM /* 177*10673SKrishnendu.Sadhukhan@Sun.COM * The main function. 178*10673SKrishnendu.Sadhukhan@Sun.COM */ 179*10673SKrishnendu.Sadhukhan@Sun.COM int 180*10673SKrishnendu.Sadhukhan@Sun.COM main(int argc, char *argv[]) 181*10673SKrishnendu.Sadhukhan@Sun.COM { 182*10673SKrishnendu.Sadhukhan@Sun.COM const char *opt_string = "t:o:k:hf:l:c:"; 183*10673SKrishnendu.Sadhukhan@Sun.COM struct option const longopts[] = { 184*10673SKrishnendu.Sadhukhan@Sun.COM {"interval", required_argument, NULL, 't'}, 185*10673SKrishnendu.Sadhukhan@Sun.COM {"output-log-file", required_argument, NULL, 'o'}, 186*10673SKrishnendu.Sadhukhan@Sun.COM {"kernel-log-level", required_argument, NULL, 'k'}, 187*10673SKrishnendu.Sadhukhan@Sun.COM {"help", no_argument, NULL, 'h'}, 188*10673SKrishnendu.Sadhukhan@Sun.COM {"feature", required_argument, NULL, 'f'}, 189*10673SKrishnendu.Sadhukhan@Sun.COM {"log-period", required_argument, NULL, 'l'}, 190*10673SKrishnendu.Sadhukhan@Sun.COM {"config", required_argument, NULL, 'c'}, 191*10673SKrishnendu.Sadhukhan@Sun.COM {NULL, 0, NULL, 0} 192*10673SKrishnendu.Sadhukhan@Sun.COM }; 193*10673SKrishnendu.Sadhukhan@Sun.COM 194*10673SKrishnendu.Sadhukhan@Sun.COM int optc; 195*10673SKrishnendu.Sadhukhan@Sun.COM int longind = 0; 196*10673SKrishnendu.Sadhukhan@Sun.COM int running = 1; 197*10673SKrishnendu.Sadhukhan@Sun.COM int unknown_option = FALSE; 198*10673SKrishnendu.Sadhukhan@Sun.COM int refresh_interval = 5; 199*10673SKrishnendu.Sadhukhan@Sun.COM int klog_level = 0; 200*10673SKrishnendu.Sadhukhan@Sun.COM int log_interval = 0; 201*10673SKrishnendu.Sadhukhan@Sun.COM long long last_logged = 0; 202*10673SKrishnendu.Sadhukhan@Sun.COM char *token = NULL; 203*10673SKrishnendu.Sadhukhan@Sun.COM int retval = 0; 204*10673SKrishnendu.Sadhukhan@Sun.COM int gpipe; 205*10673SKrishnendu.Sadhukhan@Sun.COM int err; 206*10673SKrishnendu.Sadhukhan@Sun.COM uint64_t collect_end; 207*10673SKrishnendu.Sadhukhan@Sun.COM uint64_t current_time; 208*10673SKrishnendu.Sadhukhan@Sun.COM uint64_t delta_time; 209*10673SKrishnendu.Sadhukhan@Sun.COM char logfile[PATH_MAX] = ""; 210*10673SKrishnendu.Sadhukhan@Sun.COM 211*10673SKrishnendu.Sadhukhan@Sun.COM lt_gpipe_init(); 212*10673SKrishnendu.Sadhukhan@Sun.COM (void) signal(SIGINT, signal_handler); 213*10673SKrishnendu.Sadhukhan@Sun.COM (void) signal(SIGTERM, signal_handler); 214*10673SKrishnendu.Sadhukhan@Sun.COM 215*10673SKrishnendu.Sadhukhan@Sun.COM /* Default global settings */ 216*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_enable_filter = 0; 217*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_sched = 0; 218*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_syncobj = 1; 219*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_low_overhead_mode = 0; 220*10673SKrishnendu.Sadhukhan@Sun.COM /* dtrace snapshot every 1 second */ 221*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_snap_interval = 1000; 222*10673SKrishnendu.Sadhukhan@Sun.COM #ifdef EMBED_CONFIGS 223*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name = NULL; 224*10673SKrishnendu.Sadhukhan@Sun.COM #else 225*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name = lt_strdup(DEFAULT_CONFIG_NAME); 226*10673SKrishnendu.Sadhukhan@Sun.COM #endif 227*10673SKrishnendu.Sadhukhan@Sun.COM 228*10673SKrishnendu.Sadhukhan@Sun.COM /* Parse command line arguments. */ 229*10673SKrishnendu.Sadhukhan@Sun.COM while ((optc = getopt_long(argc, argv, opt_string, 230*10673SKrishnendu.Sadhukhan@Sun.COM longopts, &longind)) != -1) { 231*10673SKrishnendu.Sadhukhan@Sun.COM switch (optc) { 232*10673SKrishnendu.Sadhukhan@Sun.COM case 'h': 233*10673SKrishnendu.Sadhukhan@Sun.COM print_usage(argv[0], TRUE); 234*10673SKrishnendu.Sadhukhan@Sun.COM goto end_none; 235*10673SKrishnendu.Sadhukhan@Sun.COM case 't': 236*10673SKrishnendu.Sadhukhan@Sun.COM if (to_int(optarg, &refresh_interval) != 0 || 237*10673SKrishnendu.Sadhukhan@Sun.COM refresh_interval < 1 || refresh_interval > 60) { 238*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 239*10673SKrishnendu.Sadhukhan@Sun.COM "Invalid refresh interval: %s\n", optarg); 240*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 241*10673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_INTERVAL, 242*10673SKrishnendu.Sadhukhan@Sun.COM refresh_interval)) { 243*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 244*10673SKrishnendu.Sadhukhan@Sun.COM } 245*10673SKrishnendu.Sadhukhan@Sun.COM 246*10673SKrishnendu.Sadhukhan@Sun.COM break; 247*10673SKrishnendu.Sadhukhan@Sun.COM case 'k': 248*10673SKrishnendu.Sadhukhan@Sun.COM if (to_int(optarg, &klog_level) != 0 || 249*10673SKrishnendu.Sadhukhan@Sun.COM lt_klog_set_log_level(klog_level) != 0) { 250*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 251*10673SKrishnendu.Sadhukhan@Sun.COM "Invalid log level: %s\n", optarg); 252*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 253*10673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_LOG_LEVEL, 254*10673SKrishnendu.Sadhukhan@Sun.COM refresh_interval)) { 255*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 256*10673SKrishnendu.Sadhukhan@Sun.COM } 257*10673SKrishnendu.Sadhukhan@Sun.COM 258*10673SKrishnendu.Sadhukhan@Sun.COM break; 259*10673SKrishnendu.Sadhukhan@Sun.COM case 'o': 260*10673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_LOG_FILE, optind)) { 261*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 262*10673SKrishnendu.Sadhukhan@Sun.COM } else if (strlen(optarg) >= sizeof (logfile)) { 263*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 264*10673SKrishnendu.Sadhukhan@Sun.COM "Log file name is too long: %s\n", 265*10673SKrishnendu.Sadhukhan@Sun.COM optarg); 266*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 267*10673SKrishnendu.Sadhukhan@Sun.COM } else { 268*10673SKrishnendu.Sadhukhan@Sun.COM (void) strncpy(logfile, optarg, 269*10673SKrishnendu.Sadhukhan@Sun.COM sizeof (logfile)); 270*10673SKrishnendu.Sadhukhan@Sun.COM } 271*10673SKrishnendu.Sadhukhan@Sun.COM 272*10673SKrishnendu.Sadhukhan@Sun.COM break; 273*10673SKrishnendu.Sadhukhan@Sun.COM case 'f': 274*10673SKrishnendu.Sadhukhan@Sun.COM for (token = strtok(optarg, ","); token != NULL; 275*10673SKrishnendu.Sadhukhan@Sun.COM token = strtok(NULL, ",")) { 276*10673SKrishnendu.Sadhukhan@Sun.COM int v = TRUE; 277*10673SKrishnendu.Sadhukhan@Sun.COM 278*10673SKrishnendu.Sadhukhan@Sun.COM if (strncmp(token, "no", 2) == 0) { 279*10673SKrishnendu.Sadhukhan@Sun.COM v = FALSE; 280*10673SKrishnendu.Sadhukhan@Sun.COM token = &token[2]; 281*10673SKrishnendu.Sadhukhan@Sun.COM } 282*10673SKrishnendu.Sadhukhan@Sun.COM 283*10673SKrishnendu.Sadhukhan@Sun.COM if (CMPOPT(token, "filter") == 0) { 284*10673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_FILTER, 285*10673SKrishnendu.Sadhukhan@Sun.COM v)) { 286*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 287*10673SKrishnendu.Sadhukhan@Sun.COM } else { 288*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_enable_filter 289*10673SKrishnendu.Sadhukhan@Sun.COM = v; 290*10673SKrishnendu.Sadhukhan@Sun.COM } 291*10673SKrishnendu.Sadhukhan@Sun.COM } else if (CMPOPT(token, "sched") == 0) { 292*10673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_SCHED, 293*10673SKrishnendu.Sadhukhan@Sun.COM v)) { 294*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 295*10673SKrishnendu.Sadhukhan@Sun.COM } else { 296*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_sched 297*10673SKrishnendu.Sadhukhan@Sun.COM = v; 298*10673SKrishnendu.Sadhukhan@Sun.COM } 299*10673SKrishnendu.Sadhukhan@Sun.COM } else if (CMPOPT(token, "sobj") == 0) { 300*10673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_SOBJ, 301*10673SKrishnendu.Sadhukhan@Sun.COM v)) { 302*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 303*10673SKrishnendu.Sadhukhan@Sun.COM } else { 304*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_syncobj 305*10673SKrishnendu.Sadhukhan@Sun.COM = v; 306*10673SKrishnendu.Sadhukhan@Sun.COM } 307*10673SKrishnendu.Sadhukhan@Sun.COM } else if (CMPOPT(token, "low") == 0) { 308*10673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_LOW, 309*10673SKrishnendu.Sadhukhan@Sun.COM v)) { 310*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 311*10673SKrishnendu.Sadhukhan@Sun.COM } else { 312*10673SKrishnendu.Sadhukhan@Sun.COM g_config. 313*10673SKrishnendu.Sadhukhan@Sun.COM lt_cfg_low_overhead_mode 314*10673SKrishnendu.Sadhukhan@Sun.COM = v; 315*10673SKrishnendu.Sadhukhan@Sun.COM } 316*10673SKrishnendu.Sadhukhan@Sun.COM } else { 317*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 318*10673SKrishnendu.Sadhukhan@Sun.COM "Unknown feature: %s\n", token); 319*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 320*10673SKrishnendu.Sadhukhan@Sun.COM } 321*10673SKrishnendu.Sadhukhan@Sun.COM } 322*10673SKrishnendu.Sadhukhan@Sun.COM 323*10673SKrishnendu.Sadhukhan@Sun.COM break; 324*10673SKrishnendu.Sadhukhan@Sun.COM case 'l': 325*10673SKrishnendu.Sadhukhan@Sun.COM if (to_int(optarg, &log_interval) != 0 || 326*10673SKrishnendu.Sadhukhan@Sun.COM log_interval < 60) { 327*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 328*10673SKrishnendu.Sadhukhan@Sun.COM "Invalid log interval: %s\n", optarg); 329*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 330*10673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_LOG_INTERVAL, 331*10673SKrishnendu.Sadhukhan@Sun.COM log_interval)) { 332*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 333*10673SKrishnendu.Sadhukhan@Sun.COM } 334*10673SKrishnendu.Sadhukhan@Sun.COM 335*10673SKrishnendu.Sadhukhan@Sun.COM break; 336*10673SKrishnendu.Sadhukhan@Sun.COM case 'c': 337*10673SKrishnendu.Sadhukhan@Sun.COM if (strlen(optarg) >= PATH_MAX) { 338*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error( 339*10673SKrishnendu.Sadhukhan@Sun.COM "Configuration name is too long.\n"); 340*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 341*10673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_CONFIG_FILE, 342*10673SKrishnendu.Sadhukhan@Sun.COM optind)) { 343*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 344*10673SKrishnendu.Sadhukhan@Sun.COM } else { 345*10673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name = 346*10673SKrishnendu.Sadhukhan@Sun.COM lt_strdup(optarg); 347*10673SKrishnendu.Sadhukhan@Sun.COM } 348*10673SKrishnendu.Sadhukhan@Sun.COM 349*10673SKrishnendu.Sadhukhan@Sun.COM break; 350*10673SKrishnendu.Sadhukhan@Sun.COM default: 351*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 352*10673SKrishnendu.Sadhukhan@Sun.COM break; 353*10673SKrishnendu.Sadhukhan@Sun.COM } 354*10673SKrishnendu.Sadhukhan@Sun.COM } 355*10673SKrishnendu.Sadhukhan@Sun.COM 356*10673SKrishnendu.Sadhukhan@Sun.COM if (!unknown_option && strlen(logfile) > 0) { 357*10673SKrishnendu.Sadhukhan@Sun.COM err = lt_klog_set_log_file(logfile); 358*10673SKrishnendu.Sadhukhan@Sun.COM 359*10673SKrishnendu.Sadhukhan@Sun.COM if (err == -1) { 360*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Log file name is too long: %s\n", 361*10673SKrishnendu.Sadhukhan@Sun.COM logfile); 362*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 363*10673SKrishnendu.Sadhukhan@Sun.COM } else if (err == -2) { 364*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Cannot write to log file: %s\n", 365*10673SKrishnendu.Sadhukhan@Sun.COM logfile); 366*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 367*10673SKrishnendu.Sadhukhan@Sun.COM } 368*10673SKrishnendu.Sadhukhan@Sun.COM } 369*10673SKrishnendu.Sadhukhan@Sun.COM 370*10673SKrishnendu.Sadhukhan@Sun.COM /* Throw error for invalid/junk arguments */ 371*10673SKrishnendu.Sadhukhan@Sun.COM if (optind < argc) { 372*10673SKrishnendu.Sadhukhan@Sun.COM int tmpind = optind; 373*10673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "Unknown option(s): "); 374*10673SKrishnendu.Sadhukhan@Sun.COM 375*10673SKrishnendu.Sadhukhan@Sun.COM while (tmpind < argc) { 376*10673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "%s ", argv[tmpind++]); 377*10673SKrishnendu.Sadhukhan@Sun.COM } 378*10673SKrishnendu.Sadhukhan@Sun.COM 379*10673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "\n"); 380*10673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE; 381*10673SKrishnendu.Sadhukhan@Sun.COM } 382*10673SKrishnendu.Sadhukhan@Sun.COM 383*10673SKrishnendu.Sadhukhan@Sun.COM if (unknown_option) { 384*10673SKrishnendu.Sadhukhan@Sun.COM print_usage(argv[0], FALSE); 385*10673SKrishnendu.Sadhukhan@Sun.COM retval = 1; 386*10673SKrishnendu.Sadhukhan@Sun.COM goto end_none; 387*10673SKrishnendu.Sadhukhan@Sun.COM } 388*10673SKrishnendu.Sadhukhan@Sun.COM 389*10673SKrishnendu.Sadhukhan@Sun.COM (void) printf("%s\n%s\n", TITLE, COPYRIGHT); 390*10673SKrishnendu.Sadhukhan@Sun.COM 391*10673SKrishnendu.Sadhukhan@Sun.COM /* 392*10673SKrishnendu.Sadhukhan@Sun.COM * Initialization 393*10673SKrishnendu.Sadhukhan@Sun.COM */ 394*10673SKrishnendu.Sadhukhan@Sun.COM lt_klog_init(); 395*10673SKrishnendu.Sadhukhan@Sun.COM 396*10673SKrishnendu.Sadhukhan@Sun.COM if (lt_table_init() != 0) { 397*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Unable to load configuration table.\n"); 398*10673SKrishnendu.Sadhukhan@Sun.COM retval = 1; 399*10673SKrishnendu.Sadhukhan@Sun.COM goto end_notable; 400*10673SKrishnendu.Sadhukhan@Sun.COM } 401*10673SKrishnendu.Sadhukhan@Sun.COM 402*10673SKrishnendu.Sadhukhan@Sun.COM if (lt_dtrace_init() != 0) { 403*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Unable to initialize dtrace.\n"); 404*10673SKrishnendu.Sadhukhan@Sun.COM retval = 1; 405*10673SKrishnendu.Sadhukhan@Sun.COM goto end_nodtrace; 406*10673SKrishnendu.Sadhukhan@Sun.COM } 407*10673SKrishnendu.Sadhukhan@Sun.COM 408*10673SKrishnendu.Sadhukhan@Sun.COM last_logged = lt_millisecond(); 409*10673SKrishnendu.Sadhukhan@Sun.COM 410*10673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Collecting data for %d seconds...\n", 411*10673SKrishnendu.Sadhukhan@Sun.COM refresh_interval); 412*10673SKrishnendu.Sadhukhan@Sun.COM 413*10673SKrishnendu.Sadhukhan@Sun.COM gpipe = lt_gpipe_readfd(); 414*10673SKrishnendu.Sadhukhan@Sun.COM collect_end = last_logged + refresh_interval * 1000; 415*10673SKrishnendu.Sadhukhan@Sun.COM for (;;) { 416*10673SKrishnendu.Sadhukhan@Sun.COM fd_set read_fd; 417*10673SKrishnendu.Sadhukhan@Sun.COM struct timeval timeout; 418*10673SKrishnendu.Sadhukhan@Sun.COM int tsleep = collect_end - lt_millisecond(); 419*10673SKrishnendu.Sadhukhan@Sun.COM 420*10673SKrishnendu.Sadhukhan@Sun.COM if (tsleep <= 0) { 421*10673SKrishnendu.Sadhukhan@Sun.COM break; 422*10673SKrishnendu.Sadhukhan@Sun.COM } 423*10673SKrishnendu.Sadhukhan@Sun.COM 424*10673SKrishnendu.Sadhukhan@Sun.COM if (tsleep > g_config.lt_cfg_snap_interval * 1000) { 425*10673SKrishnendu.Sadhukhan@Sun.COM tsleep = g_config.lt_cfg_snap_interval * 1000; 426*10673SKrishnendu.Sadhukhan@Sun.COM } 427*10673SKrishnendu.Sadhukhan@Sun.COM 428*10673SKrishnendu.Sadhukhan@Sun.COM timeout.tv_sec = tsleep / 1000; 429*10673SKrishnendu.Sadhukhan@Sun.COM timeout.tv_usec = (tsleep % 1000) * 1000; 430*10673SKrishnendu.Sadhukhan@Sun.COM 431*10673SKrishnendu.Sadhukhan@Sun.COM FD_ZERO(&read_fd); 432*10673SKrishnendu.Sadhukhan@Sun.COM FD_SET(gpipe, &read_fd); 433*10673SKrishnendu.Sadhukhan@Sun.COM 434*10673SKrishnendu.Sadhukhan@Sun.COM if (select(gpipe + 1, &read_fd, NULL, NULL, &timeout) > 0) { 435*10673SKrishnendu.Sadhukhan@Sun.COM goto end_ubreak; 436*10673SKrishnendu.Sadhukhan@Sun.COM } 437*10673SKrishnendu.Sadhukhan@Sun.COM 438*10673SKrishnendu.Sadhukhan@Sun.COM (void) lt_dtrace_work(0); 439*10673SKrishnendu.Sadhukhan@Sun.COM } 440*10673SKrishnendu.Sadhukhan@Sun.COM 441*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_init(); 442*10673SKrishnendu.Sadhukhan@Sun.COM 443*10673SKrishnendu.Sadhukhan@Sun.COM do { 444*10673SKrishnendu.Sadhukhan@Sun.COM current_time = lt_millisecond(); 445*10673SKrishnendu.Sadhukhan@Sun.COM 446*10673SKrishnendu.Sadhukhan@Sun.COM lt_stat_clear_all(); 447*10673SKrishnendu.Sadhukhan@Sun.COM (void) lt_dtrace_collect(); 448*10673SKrishnendu.Sadhukhan@Sun.COM 449*10673SKrishnendu.Sadhukhan@Sun.COM delta_time = current_time; 450*10673SKrishnendu.Sadhukhan@Sun.COM current_time = lt_millisecond(); 451*10673SKrishnendu.Sadhukhan@Sun.COM delta_time = current_time - delta_time; 452*10673SKrishnendu.Sadhukhan@Sun.COM 453*10673SKrishnendu.Sadhukhan@Sun.COM if (log_interval > 0 && 454*10673SKrishnendu.Sadhukhan@Sun.COM current_time - last_logged > log_interval * 1000) { 455*10673SKrishnendu.Sadhukhan@Sun.COM lt_klog_write(); 456*10673SKrishnendu.Sadhukhan@Sun.COM last_logged = current_time; 457*10673SKrishnendu.Sadhukhan@Sun.COM } 458*10673SKrishnendu.Sadhukhan@Sun.COM 459*10673SKrishnendu.Sadhukhan@Sun.COM running = lt_display_loop(refresh_interval * 1000 - 460*10673SKrishnendu.Sadhukhan@Sun.COM delta_time); 461*10673SKrishnendu.Sadhukhan@Sun.COM } while (running != 0); 462*10673SKrishnendu.Sadhukhan@Sun.COM 463*10673SKrishnendu.Sadhukhan@Sun.COM lt_klog_write(); 464*10673SKrishnendu.Sadhukhan@Sun.COM 465*10673SKrishnendu.Sadhukhan@Sun.COM /* Cleanup */ 466*10673SKrishnendu.Sadhukhan@Sun.COM lt_display_deinit(); 467*10673SKrishnendu.Sadhukhan@Sun.COM 468*10673SKrishnendu.Sadhukhan@Sun.COM end_ubreak: 469*10673SKrishnendu.Sadhukhan@Sun.COM lt_dtrace_deinit(); 470*10673SKrishnendu.Sadhukhan@Sun.COM lt_stat_free_all(); 471*10673SKrishnendu.Sadhukhan@Sun.COM 472*10673SKrishnendu.Sadhukhan@Sun.COM end_nodtrace: 473*10673SKrishnendu.Sadhukhan@Sun.COM lt_table_deinit(); 474*10673SKrishnendu.Sadhukhan@Sun.COM 475*10673SKrishnendu.Sadhukhan@Sun.COM end_notable: 476*10673SKrishnendu.Sadhukhan@Sun.COM lt_klog_deinit(); 477*10673SKrishnendu.Sadhukhan@Sun.COM 478*10673SKrishnendu.Sadhukhan@Sun.COM end_none: 479*10673SKrishnendu.Sadhukhan@Sun.COM lt_gpipe_deinit(); 480*10673SKrishnendu.Sadhukhan@Sun.COM 481*10673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_config_name != NULL) { 482*10673SKrishnendu.Sadhukhan@Sun.COM free(g_config.lt_cfg_config_name); 483*10673SKrishnendu.Sadhukhan@Sun.COM } 484*10673SKrishnendu.Sadhukhan@Sun.COM 485*10673SKrishnendu.Sadhukhan@Sun.COM return (retval); 486*10673SKrishnendu.Sadhukhan@Sun.COM } 487