xref: /onnv-gate/usr/src/cmd/latencytop/common/latencytop.c (revision 10673:b22eb20aa9ca)
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