110673SKrishnendu.Sadhukhan@Sun.COM /*
210673SKrishnendu.Sadhukhan@Sun.COM * CDDL HEADER START
310673SKrishnendu.Sadhukhan@Sun.COM *
410673SKrishnendu.Sadhukhan@Sun.COM * The contents of this file are subject to the terms of the
510673SKrishnendu.Sadhukhan@Sun.COM * Common Development and Distribution License (the "License").
610673SKrishnendu.Sadhukhan@Sun.COM * You may not use this file except in compliance with the License.
710673SKrishnendu.Sadhukhan@Sun.COM *
810673SKrishnendu.Sadhukhan@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910673SKrishnendu.Sadhukhan@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010673SKrishnendu.Sadhukhan@Sun.COM * See the License for the specific language governing permissions
1110673SKrishnendu.Sadhukhan@Sun.COM * and limitations under the License.
1210673SKrishnendu.Sadhukhan@Sun.COM *
1310673SKrishnendu.Sadhukhan@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410673SKrishnendu.Sadhukhan@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510673SKrishnendu.Sadhukhan@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610673SKrishnendu.Sadhukhan@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710673SKrishnendu.Sadhukhan@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810673SKrishnendu.Sadhukhan@Sun.COM *
1910673SKrishnendu.Sadhukhan@Sun.COM * CDDL HEADER END
2010673SKrishnendu.Sadhukhan@Sun.COM */
2110673SKrishnendu.Sadhukhan@Sun.COM /*
2210673SKrishnendu.Sadhukhan@Sun.COM * Copyright (c) 2008-2009, Intel Corporation.
2310673SKrishnendu.Sadhukhan@Sun.COM * All Rights Reserved.
2410673SKrishnendu.Sadhukhan@Sun.COM */
2510673SKrishnendu.Sadhukhan@Sun.COM
2610673SKrishnendu.Sadhukhan@Sun.COM #include <unistd.h>
2710673SKrishnendu.Sadhukhan@Sun.COM #include <getopt.h>
2810673SKrishnendu.Sadhukhan@Sun.COM #include <stdio.h>
2910673SKrishnendu.Sadhukhan@Sun.COM #include <string.h>
3010673SKrishnendu.Sadhukhan@Sun.COM #include <stdlib.h>
3110673SKrishnendu.Sadhukhan@Sun.COM #include <limits.h>
3210673SKrishnendu.Sadhukhan@Sun.COM #include <libgen.h>
3310673SKrishnendu.Sadhukhan@Sun.COM #include <signal.h>
3410673SKrishnendu.Sadhukhan@Sun.COM #include "latencytop.h"
3510673SKrishnendu.Sadhukhan@Sun.COM
3610673SKrishnendu.Sadhukhan@Sun.COM #define CMPOPT(a, b) strncmp((a), (b), sizeof (b))
3710673SKrishnendu.Sadhukhan@Sun.COM
3810883SKrishnendu.Sadhukhan@Sun.COM /*
3910883SKrishnendu.Sadhukhan@Sun.COM * This variable is used to check if "dynamic variable drop" in dtrace
4010883SKrishnendu.Sadhukhan@Sun.COM * has happened.
4110883SKrishnendu.Sadhukhan@Sun.COM */
4210883SKrishnendu.Sadhukhan@Sun.COM boolean_t lt_drop_detected = 0;
4310883SKrishnendu.Sadhukhan@Sun.COM
4410673SKrishnendu.Sadhukhan@Sun.COM lt_config_t g_config;
4510673SKrishnendu.Sadhukhan@Sun.COM
4610673SKrishnendu.Sadhukhan@Sun.COM typedef enum {
4710673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_INTERVAL,
4810673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_LOG_FILE,
4910673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_LOG_LEVEL,
5010673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_LOG_INTERVAL,
5110673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_CONFIG_FILE,
5210673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_FILTER,
5310673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_SCHED,
5410673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_SOBJ,
5510673SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_F_LOW,
56*11789SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT_SELECT,
57*11789SKrishnendu.Sadhukhan@Sun.COM LT_CMDOPT__LAST /* Must be the last one */
5810673SKrishnendu.Sadhukhan@Sun.COM } lt_cmd_option_id_t;
5910673SKrishnendu.Sadhukhan@Sun.COM
6010673SKrishnendu.Sadhukhan@Sun.COM /*
6110673SKrishnendu.Sadhukhan@Sun.COM * Check for duplicate command line options.
6210673SKrishnendu.Sadhukhan@Sun.COM * Returns TRUE if duplicate options with different values are found,
6310673SKrishnendu.Sadhukhan@Sun.COM * returns FALSE otherwise.
6410673SKrishnendu.Sadhukhan@Sun.COM */
6510673SKrishnendu.Sadhukhan@Sun.COM static int
check_opt_dup(lt_cmd_option_id_t id,uint64_t value)6610673SKrishnendu.Sadhukhan@Sun.COM check_opt_dup(lt_cmd_option_id_t id, uint64_t value) {
6710673SKrishnendu.Sadhukhan@Sun.COM
6810673SKrishnendu.Sadhukhan@Sun.COM static int opt_set[(int)LT_CMDOPT__LAST];
6910673SKrishnendu.Sadhukhan@Sun.COM static uint64_t opt_val[(int)LT_CMDOPT__LAST];
7010673SKrishnendu.Sadhukhan@Sun.COM
7110673SKrishnendu.Sadhukhan@Sun.COM const char *errmsg[] = {
7210673SKrishnendu.Sadhukhan@Sun.COM "-t is set more than once with different values.",
7310673SKrishnendu.Sadhukhan@Sun.COM "-o is set more than once.",
7410673SKrishnendu.Sadhukhan@Sun.COM "-k is set more than once with different values.",
7510673SKrishnendu.Sadhukhan@Sun.COM "-l is set more than once with different values.",
7610673SKrishnendu.Sadhukhan@Sun.COM "-c is set more than once.",
7710673SKrishnendu.Sadhukhan@Sun.COM "-f [no]filter is set more than once with different values.",
7810673SKrishnendu.Sadhukhan@Sun.COM "-f [no]sched is set more than once with different values.",
7910673SKrishnendu.Sadhukhan@Sun.COM "-f [no]sobj is set more than once with different values.",
8010673SKrishnendu.Sadhukhan@Sun.COM "-f [no]low is set more than once with different values.",
81*11789SKrishnendu.Sadhukhan@Sun.COM "-s is set more than once with different values."
8210673SKrishnendu.Sadhukhan@Sun.COM };
8310673SKrishnendu.Sadhukhan@Sun.COM
8410673SKrishnendu.Sadhukhan@Sun.COM g_assert(sizeof (errmsg)/sizeof (errmsg[0]) == (int)LT_CMDOPT__LAST);
8510673SKrishnendu.Sadhukhan@Sun.COM
8610673SKrishnendu.Sadhukhan@Sun.COM if (!opt_set[(int)id]) {
8710673SKrishnendu.Sadhukhan@Sun.COM opt_set[(int)id] = TRUE;
8810673SKrishnendu.Sadhukhan@Sun.COM opt_val[(int)id] = value;
8910673SKrishnendu.Sadhukhan@Sun.COM return (FALSE);
9010673SKrishnendu.Sadhukhan@Sun.COM }
9110673SKrishnendu.Sadhukhan@Sun.COM
9210673SKrishnendu.Sadhukhan@Sun.COM if (opt_val[(int)id] != value) {
9310673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "%s\n", errmsg[(int)id]);
9410673SKrishnendu.Sadhukhan@Sun.COM return (TRUE);
9510673SKrishnendu.Sadhukhan@Sun.COM }
9610673SKrishnendu.Sadhukhan@Sun.COM
9710673SKrishnendu.Sadhukhan@Sun.COM return (FALSE);
9810673SKrishnendu.Sadhukhan@Sun.COM }
9910673SKrishnendu.Sadhukhan@Sun.COM
10010673SKrishnendu.Sadhukhan@Sun.COM /*
10110673SKrishnendu.Sadhukhan@Sun.COM * Print command-line help message.
10210673SKrishnendu.Sadhukhan@Sun.COM */
10310673SKrishnendu.Sadhukhan@Sun.COM static void
print_usage(const char * execname,int long_help)10410673SKrishnendu.Sadhukhan@Sun.COM print_usage(const char *execname, int long_help)
10510673SKrishnendu.Sadhukhan@Sun.COM {
10610673SKrishnendu.Sadhukhan@Sun.COM char buffer[PATH_MAX];
10710673SKrishnendu.Sadhukhan@Sun.COM (void) snprintf(buffer, sizeof (buffer), "%s", execname);
10810673SKrishnendu.Sadhukhan@Sun.COM
10910673SKrishnendu.Sadhukhan@Sun.COM if (!long_help) {
11010673SKrishnendu.Sadhukhan@Sun.COM /* Print short help to stderr. */
11110673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "Usage: %s [option(s)], ",
11210673SKrishnendu.Sadhukhan@Sun.COM basename(buffer));
11310673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "use '%s -h' for details.\n",
11410673SKrishnendu.Sadhukhan@Sun.COM basename(buffer));
11510673SKrishnendu.Sadhukhan@Sun.COM return;
11610673SKrishnendu.Sadhukhan@Sun.COM }
11710673SKrishnendu.Sadhukhan@Sun.COM
11810673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Usage: %s [option(s)]\n", basename(buffer));
11910673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Options:\n"
12010673SKrishnendu.Sadhukhan@Sun.COM " -h, --help\n"
12110673SKrishnendu.Sadhukhan@Sun.COM " Print this help.\n"
12210673SKrishnendu.Sadhukhan@Sun.COM " -t, --interval TIME\n"
12310673SKrishnendu.Sadhukhan@Sun.COM " Set refresh interval to TIME. "
12410673SKrishnendu.Sadhukhan@Sun.COM "Valid range [1...60] seconds, default = 5\n"
12510673SKrishnendu.Sadhukhan@Sun.COM /*
12610673SKrishnendu.Sadhukhan@Sun.COM * Option "-c, --config FILE" is not user-visible for now.
12710673SKrishnendu.Sadhukhan@Sun.COM * When we have chance to properly document the format of translation
12810673SKrishnendu.Sadhukhan@Sun.COM * rules, we'll make it user-visible.
12910673SKrishnendu.Sadhukhan@Sun.COM */
13010673SKrishnendu.Sadhukhan@Sun.COM " -o, --output-log-file FILE\n"
13110673SKrishnendu.Sadhukhan@Sun.COM " Output kernel log to FILE. Default = "
13210673SKrishnendu.Sadhukhan@Sun.COM DEFAULT_KLOG_FILE "\n"
13310673SKrishnendu.Sadhukhan@Sun.COM " -k, --kernel-log-level LEVEL\n"
13410673SKrishnendu.Sadhukhan@Sun.COM " Set kernel log level to LEVEL.\n"
13510673SKrishnendu.Sadhukhan@Sun.COM " 0(default) = None, 1 = Unmapped, 2 = Mapped, 3 = All.\n"
13610673SKrishnendu.Sadhukhan@Sun.COM " -f, --feature [no]feature1,[no]feature2,...\n"
13710673SKrishnendu.Sadhukhan@Sun.COM " Enable/disable features in LatencyTOP.\n"
13810673SKrishnendu.Sadhukhan@Sun.COM " [no]filter:\n"
13910673SKrishnendu.Sadhukhan@Sun.COM " Filter large interruptible latencies, e.g. sleep.\n"
14010673SKrishnendu.Sadhukhan@Sun.COM " [no]sched:\n"
14110673SKrishnendu.Sadhukhan@Sun.COM " Monitors sched (PID=0).\n"
14210673SKrishnendu.Sadhukhan@Sun.COM " [no]sobj:\n"
14310673SKrishnendu.Sadhukhan@Sun.COM " Monitors synchronization objects.\n"
14410673SKrishnendu.Sadhukhan@Sun.COM " [no]low:\n"
14510673SKrishnendu.Sadhukhan@Sun.COM " Lower overhead by sampling small latencies.\n"
14610673SKrishnendu.Sadhukhan@Sun.COM " -l, --log-period TIME\n"
147*11789SKrishnendu.Sadhukhan@Sun.COM " Write and restart log every TIME seconds, TIME >= 60\n"
148*11789SKrishnendu.Sadhukhan@Sun.COM " -s --select [ pid=<pid> | pgid=<pgid> ]\n"
149*11789SKrishnendu.Sadhukhan@Sun.COM " Monitor only the given process or processes in the "
150*11789SKrishnendu.Sadhukhan@Sun.COM "given process group.\n");
15110673SKrishnendu.Sadhukhan@Sun.COM }
15210673SKrishnendu.Sadhukhan@Sun.COM
15310673SKrishnendu.Sadhukhan@Sun.COM /*
15410673SKrishnendu.Sadhukhan@Sun.COM * Properly exit latencytop when it receives SIGINT or SIGTERM.
15510673SKrishnendu.Sadhukhan@Sun.COM */
15610673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
15710673SKrishnendu.Sadhukhan@Sun.COM static void
signal_handler(int sig)15810673SKrishnendu.Sadhukhan@Sun.COM signal_handler(int sig)
15910673SKrishnendu.Sadhukhan@Sun.COM {
16010673SKrishnendu.Sadhukhan@Sun.COM lt_gpipe_break("q");
16110673SKrishnendu.Sadhukhan@Sun.COM }
16210673SKrishnendu.Sadhukhan@Sun.COM
16310673SKrishnendu.Sadhukhan@Sun.COM /*
16410673SKrishnendu.Sadhukhan@Sun.COM * Convert string to integer. It returns error if extra characters are found.
16510673SKrishnendu.Sadhukhan@Sun.COM */
16610673SKrishnendu.Sadhukhan@Sun.COM static int
to_int(const char * str,int * result)16710673SKrishnendu.Sadhukhan@Sun.COM to_int(const char *str, int *result)
16810673SKrishnendu.Sadhukhan@Sun.COM {
16910673SKrishnendu.Sadhukhan@Sun.COM char *tail = NULL;
17010673SKrishnendu.Sadhukhan@Sun.COM long ret;
17110673SKrishnendu.Sadhukhan@Sun.COM
17210673SKrishnendu.Sadhukhan@Sun.COM if (str == NULL || result == NULL) {
17310673SKrishnendu.Sadhukhan@Sun.COM return (-1);
17410673SKrishnendu.Sadhukhan@Sun.COM }
17510673SKrishnendu.Sadhukhan@Sun.COM
17610673SKrishnendu.Sadhukhan@Sun.COM ret = strtol(str, &tail, 10);
17710673SKrishnendu.Sadhukhan@Sun.COM
17810673SKrishnendu.Sadhukhan@Sun.COM if (tail != NULL && *tail != '\0') {
17910673SKrishnendu.Sadhukhan@Sun.COM return (-1);
18010673SKrishnendu.Sadhukhan@Sun.COM }
18110673SKrishnendu.Sadhukhan@Sun.COM
18210673SKrishnendu.Sadhukhan@Sun.COM *result = (int)ret;
18310673SKrishnendu.Sadhukhan@Sun.COM
18410673SKrishnendu.Sadhukhan@Sun.COM return (0);
18510673SKrishnendu.Sadhukhan@Sun.COM }
18610673SKrishnendu.Sadhukhan@Sun.COM
18710673SKrishnendu.Sadhukhan@Sun.COM /*
18810673SKrishnendu.Sadhukhan@Sun.COM * The main function.
18910673SKrishnendu.Sadhukhan@Sun.COM */
19010673SKrishnendu.Sadhukhan@Sun.COM int
main(int argc,char * argv[])19110673SKrishnendu.Sadhukhan@Sun.COM main(int argc, char *argv[])
19210673SKrishnendu.Sadhukhan@Sun.COM {
193*11789SKrishnendu.Sadhukhan@Sun.COM const char *opt_string = "t:o:k:hf:l:c:s:";
19410673SKrishnendu.Sadhukhan@Sun.COM struct option const longopts[] = {
19510673SKrishnendu.Sadhukhan@Sun.COM {"interval", required_argument, NULL, 't'},
19610673SKrishnendu.Sadhukhan@Sun.COM {"output-log-file", required_argument, NULL, 'o'},
19710673SKrishnendu.Sadhukhan@Sun.COM {"kernel-log-level", required_argument, NULL, 'k'},
19810673SKrishnendu.Sadhukhan@Sun.COM {"help", no_argument, NULL, 'h'},
19910673SKrishnendu.Sadhukhan@Sun.COM {"feature", required_argument, NULL, 'f'},
20010673SKrishnendu.Sadhukhan@Sun.COM {"log-period", required_argument, NULL, 'l'},
20110673SKrishnendu.Sadhukhan@Sun.COM {"config", required_argument, NULL, 'c'},
202*11789SKrishnendu.Sadhukhan@Sun.COM {"select", required_argument, NULL, 's'},
20310673SKrishnendu.Sadhukhan@Sun.COM {NULL, 0, NULL, 0}
20410673SKrishnendu.Sadhukhan@Sun.COM };
20510673SKrishnendu.Sadhukhan@Sun.COM
20610673SKrishnendu.Sadhukhan@Sun.COM int optc;
20710673SKrishnendu.Sadhukhan@Sun.COM int longind = 0;
20810673SKrishnendu.Sadhukhan@Sun.COM int running = 1;
20910673SKrishnendu.Sadhukhan@Sun.COM int unknown_option = FALSE;
21010673SKrishnendu.Sadhukhan@Sun.COM int refresh_interval = 5;
21110673SKrishnendu.Sadhukhan@Sun.COM int klog_level = 0;
21210673SKrishnendu.Sadhukhan@Sun.COM int log_interval = 0;
21310673SKrishnendu.Sadhukhan@Sun.COM long long last_logged = 0;
21410673SKrishnendu.Sadhukhan@Sun.COM char *token = NULL;
21510673SKrishnendu.Sadhukhan@Sun.COM int retval = 0;
21610673SKrishnendu.Sadhukhan@Sun.COM int gpipe;
21710673SKrishnendu.Sadhukhan@Sun.COM int err;
21810673SKrishnendu.Sadhukhan@Sun.COM uint64_t collect_end;
21910673SKrishnendu.Sadhukhan@Sun.COM uint64_t current_time;
22010673SKrishnendu.Sadhukhan@Sun.COM uint64_t delta_time;
22110673SKrishnendu.Sadhukhan@Sun.COM char logfile[PATH_MAX] = "";
222*11789SKrishnendu.Sadhukhan@Sun.COM int select_id;
223*11789SKrishnendu.Sadhukhan@Sun.COM int select_value;
224*11789SKrishnendu.Sadhukhan@Sun.COM char *select_str;
22510883SKrishnendu.Sadhukhan@Sun.COM boolean_t no_dtrace_cleanup = B_TRUE;
22610673SKrishnendu.Sadhukhan@Sun.COM
22710673SKrishnendu.Sadhukhan@Sun.COM lt_gpipe_init();
22810673SKrishnendu.Sadhukhan@Sun.COM (void) signal(SIGINT, signal_handler);
22910673SKrishnendu.Sadhukhan@Sun.COM (void) signal(SIGTERM, signal_handler);
23010673SKrishnendu.Sadhukhan@Sun.COM
23110673SKrishnendu.Sadhukhan@Sun.COM /* Default global settings */
23210673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_enable_filter = 0;
23310673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_sched = 0;
23410673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_syncobj = 1;
23510673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_low_overhead_mode = 0;
236*11789SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_pid = 0;
237*11789SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_pgid = 0;
23810673SKrishnendu.Sadhukhan@Sun.COM /* dtrace snapshot every 1 second */
23910673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_snap_interval = 1000;
24010673SKrishnendu.Sadhukhan@Sun.COM #ifdef EMBED_CONFIGS
24110673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name = NULL;
24210673SKrishnendu.Sadhukhan@Sun.COM #else
24310673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name = lt_strdup(DEFAULT_CONFIG_NAME);
24410673SKrishnendu.Sadhukhan@Sun.COM #endif
24510673SKrishnendu.Sadhukhan@Sun.COM
24610673SKrishnendu.Sadhukhan@Sun.COM /* Parse command line arguments. */
24710673SKrishnendu.Sadhukhan@Sun.COM while ((optc = getopt_long(argc, argv, opt_string,
24810673SKrishnendu.Sadhukhan@Sun.COM longopts, &longind)) != -1) {
24910673SKrishnendu.Sadhukhan@Sun.COM switch (optc) {
25010673SKrishnendu.Sadhukhan@Sun.COM case 'h':
25110673SKrishnendu.Sadhukhan@Sun.COM print_usage(argv[0], TRUE);
25210673SKrishnendu.Sadhukhan@Sun.COM goto end_none;
25310673SKrishnendu.Sadhukhan@Sun.COM case 't':
25410673SKrishnendu.Sadhukhan@Sun.COM if (to_int(optarg, &refresh_interval) != 0 ||
25510673SKrishnendu.Sadhukhan@Sun.COM refresh_interval < 1 || refresh_interval > 60) {
25610673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
25710673SKrishnendu.Sadhukhan@Sun.COM "Invalid refresh interval: %s\n", optarg);
25810673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
25910673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_INTERVAL,
26010673SKrishnendu.Sadhukhan@Sun.COM refresh_interval)) {
26110673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
26210673SKrishnendu.Sadhukhan@Sun.COM }
26310673SKrishnendu.Sadhukhan@Sun.COM
26410673SKrishnendu.Sadhukhan@Sun.COM break;
26510673SKrishnendu.Sadhukhan@Sun.COM case 'k':
26610673SKrishnendu.Sadhukhan@Sun.COM if (to_int(optarg, &klog_level) != 0 ||
26710673SKrishnendu.Sadhukhan@Sun.COM lt_klog_set_log_level(klog_level) != 0) {
26810673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
26910673SKrishnendu.Sadhukhan@Sun.COM "Invalid log level: %s\n", optarg);
27010673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
27110673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_LOG_LEVEL,
27210673SKrishnendu.Sadhukhan@Sun.COM refresh_interval)) {
27310673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
27410673SKrishnendu.Sadhukhan@Sun.COM }
27510673SKrishnendu.Sadhukhan@Sun.COM
27610673SKrishnendu.Sadhukhan@Sun.COM break;
27710673SKrishnendu.Sadhukhan@Sun.COM case 'o':
27810673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_LOG_FILE, optind)) {
27910673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
28010673SKrishnendu.Sadhukhan@Sun.COM } else if (strlen(optarg) >= sizeof (logfile)) {
28110673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
28210673SKrishnendu.Sadhukhan@Sun.COM "Log file name is too long: %s\n",
28310673SKrishnendu.Sadhukhan@Sun.COM optarg);
28410673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
28510673SKrishnendu.Sadhukhan@Sun.COM } else {
28610673SKrishnendu.Sadhukhan@Sun.COM (void) strncpy(logfile, optarg,
28710673SKrishnendu.Sadhukhan@Sun.COM sizeof (logfile));
28810673SKrishnendu.Sadhukhan@Sun.COM }
28910673SKrishnendu.Sadhukhan@Sun.COM
29010673SKrishnendu.Sadhukhan@Sun.COM break;
29110673SKrishnendu.Sadhukhan@Sun.COM case 'f':
29210673SKrishnendu.Sadhukhan@Sun.COM for (token = strtok(optarg, ","); token != NULL;
29310673SKrishnendu.Sadhukhan@Sun.COM token = strtok(NULL, ",")) {
29410673SKrishnendu.Sadhukhan@Sun.COM int v = TRUE;
29510673SKrishnendu.Sadhukhan@Sun.COM
29610673SKrishnendu.Sadhukhan@Sun.COM if (strncmp(token, "no", 2) == 0) {
29710673SKrishnendu.Sadhukhan@Sun.COM v = FALSE;
29810673SKrishnendu.Sadhukhan@Sun.COM token = &token[2];
29910673SKrishnendu.Sadhukhan@Sun.COM }
30010673SKrishnendu.Sadhukhan@Sun.COM
30110673SKrishnendu.Sadhukhan@Sun.COM if (CMPOPT(token, "filter") == 0) {
30210673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_FILTER,
30310673SKrishnendu.Sadhukhan@Sun.COM v)) {
30410673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
30510673SKrishnendu.Sadhukhan@Sun.COM } else {
30610673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_enable_filter
30710673SKrishnendu.Sadhukhan@Sun.COM = v;
30810673SKrishnendu.Sadhukhan@Sun.COM }
30910673SKrishnendu.Sadhukhan@Sun.COM } else if (CMPOPT(token, "sched") == 0) {
31010673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_SCHED,
31110673SKrishnendu.Sadhukhan@Sun.COM v)) {
31210673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
31310673SKrishnendu.Sadhukhan@Sun.COM } else {
31410673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_sched
31510673SKrishnendu.Sadhukhan@Sun.COM = v;
31610673SKrishnendu.Sadhukhan@Sun.COM }
31710673SKrishnendu.Sadhukhan@Sun.COM } else if (CMPOPT(token, "sobj") == 0) {
31810673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_SOBJ,
31910673SKrishnendu.Sadhukhan@Sun.COM v)) {
32010673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
32110673SKrishnendu.Sadhukhan@Sun.COM } else {
32210673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_syncobj
32310673SKrishnendu.Sadhukhan@Sun.COM = v;
32410673SKrishnendu.Sadhukhan@Sun.COM }
32510673SKrishnendu.Sadhukhan@Sun.COM } else if (CMPOPT(token, "low") == 0) {
32610673SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_F_LOW,
32710673SKrishnendu.Sadhukhan@Sun.COM v)) {
32810673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
32910673SKrishnendu.Sadhukhan@Sun.COM } else {
33010673SKrishnendu.Sadhukhan@Sun.COM g_config.
33110673SKrishnendu.Sadhukhan@Sun.COM lt_cfg_low_overhead_mode
33210673SKrishnendu.Sadhukhan@Sun.COM = v;
33310673SKrishnendu.Sadhukhan@Sun.COM }
33410673SKrishnendu.Sadhukhan@Sun.COM } else {
33510673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
33610673SKrishnendu.Sadhukhan@Sun.COM "Unknown feature: %s\n", token);
33710673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
33810673SKrishnendu.Sadhukhan@Sun.COM }
33910673SKrishnendu.Sadhukhan@Sun.COM }
34010673SKrishnendu.Sadhukhan@Sun.COM
34110673SKrishnendu.Sadhukhan@Sun.COM break;
34210673SKrishnendu.Sadhukhan@Sun.COM case 'l':
34310673SKrishnendu.Sadhukhan@Sun.COM if (to_int(optarg, &log_interval) != 0 ||
34410673SKrishnendu.Sadhukhan@Sun.COM log_interval < 60) {
34510673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
34610673SKrishnendu.Sadhukhan@Sun.COM "Invalid log interval: %s\n", optarg);
34710673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
34810673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_LOG_INTERVAL,
34910673SKrishnendu.Sadhukhan@Sun.COM log_interval)) {
35010673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
35110673SKrishnendu.Sadhukhan@Sun.COM }
35210673SKrishnendu.Sadhukhan@Sun.COM
35310673SKrishnendu.Sadhukhan@Sun.COM break;
35410673SKrishnendu.Sadhukhan@Sun.COM case 'c':
35510673SKrishnendu.Sadhukhan@Sun.COM if (strlen(optarg) >= PATH_MAX) {
35610673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
35710673SKrishnendu.Sadhukhan@Sun.COM "Configuration name is too long.\n");
35810673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
35910673SKrishnendu.Sadhukhan@Sun.COM } else if (check_opt_dup(LT_CMDOPT_CONFIG_FILE,
36010673SKrishnendu.Sadhukhan@Sun.COM optind)) {
36110673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
36210673SKrishnendu.Sadhukhan@Sun.COM } else {
36310673SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_config_name =
36410673SKrishnendu.Sadhukhan@Sun.COM lt_strdup(optarg);
36510673SKrishnendu.Sadhukhan@Sun.COM }
36610673SKrishnendu.Sadhukhan@Sun.COM
36710673SKrishnendu.Sadhukhan@Sun.COM break;
368*11789SKrishnendu.Sadhukhan@Sun.COM case 's':
369*11789SKrishnendu.Sadhukhan@Sun.COM if (strncmp(optarg, "pid=", 4) == 0) {
370*11789SKrishnendu.Sadhukhan@Sun.COM select_id = 0;
371*11789SKrishnendu.Sadhukhan@Sun.COM select_str = &optarg[4];
372*11789SKrishnendu.Sadhukhan@Sun.COM } else if (strncmp(optarg, "pgid=", 5) == 0) {
373*11789SKrishnendu.Sadhukhan@Sun.COM select_id = 1;
374*11789SKrishnendu.Sadhukhan@Sun.COM select_str = &optarg[5];
375*11789SKrishnendu.Sadhukhan@Sun.COM } else {
376*11789SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
377*11789SKrishnendu.Sadhukhan@Sun.COM "Invalid select option: %s\n", optarg);
378*11789SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
379*11789SKrishnendu.Sadhukhan@Sun.COM break;
380*11789SKrishnendu.Sadhukhan@Sun.COM }
381*11789SKrishnendu.Sadhukhan@Sun.COM
382*11789SKrishnendu.Sadhukhan@Sun.COM if (to_int(select_str, &select_value) != 0) {
383*11789SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
384*11789SKrishnendu.Sadhukhan@Sun.COM "Invalid select option: %s\n", optarg);
385*11789SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
386*11789SKrishnendu.Sadhukhan@Sun.COM break;
387*11789SKrishnendu.Sadhukhan@Sun.COM }
388*11789SKrishnendu.Sadhukhan@Sun.COM
389*11789SKrishnendu.Sadhukhan@Sun.COM if (select_value <= 0) {
390*11789SKrishnendu.Sadhukhan@Sun.COM lt_display_error(
391*11789SKrishnendu.Sadhukhan@Sun.COM "Process/process group ID must be "
392*11789SKrishnendu.Sadhukhan@Sun.COM "greater than 0: %s\n", optarg);
393*11789SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
394*11789SKrishnendu.Sadhukhan@Sun.COM break;
395*11789SKrishnendu.Sadhukhan@Sun.COM }
396*11789SKrishnendu.Sadhukhan@Sun.COM
397*11789SKrishnendu.Sadhukhan@Sun.COM if (check_opt_dup(LT_CMDOPT_SELECT,
398*11789SKrishnendu.Sadhukhan@Sun.COM (((uint64_t)select_id) << 32) | select_value)) {
399*11789SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
400*11789SKrishnendu.Sadhukhan@Sun.COM break;
401*11789SKrishnendu.Sadhukhan@Sun.COM }
402*11789SKrishnendu.Sadhukhan@Sun.COM
403*11789SKrishnendu.Sadhukhan@Sun.COM if (select_id == 0) {
404*11789SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_pid = select_value;
405*11789SKrishnendu.Sadhukhan@Sun.COM } else {
406*11789SKrishnendu.Sadhukhan@Sun.COM g_config.lt_cfg_trace_pgid = select_value;
407*11789SKrishnendu.Sadhukhan@Sun.COM }
408*11789SKrishnendu.Sadhukhan@Sun.COM break;
40910673SKrishnendu.Sadhukhan@Sun.COM default:
41010673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
41110673SKrishnendu.Sadhukhan@Sun.COM break;
41210673SKrishnendu.Sadhukhan@Sun.COM }
41310673SKrishnendu.Sadhukhan@Sun.COM }
41410673SKrishnendu.Sadhukhan@Sun.COM
41510673SKrishnendu.Sadhukhan@Sun.COM if (!unknown_option && strlen(logfile) > 0) {
41610673SKrishnendu.Sadhukhan@Sun.COM err = lt_klog_set_log_file(logfile);
41710673SKrishnendu.Sadhukhan@Sun.COM
41810673SKrishnendu.Sadhukhan@Sun.COM if (err == -1) {
41910673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Log file name is too long: %s\n",
42010673SKrishnendu.Sadhukhan@Sun.COM logfile);
42110673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
42210673SKrishnendu.Sadhukhan@Sun.COM } else if (err == -2) {
42310673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Cannot write to log file: %s\n",
42410673SKrishnendu.Sadhukhan@Sun.COM logfile);
42510673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
42610673SKrishnendu.Sadhukhan@Sun.COM }
42710673SKrishnendu.Sadhukhan@Sun.COM }
42810673SKrishnendu.Sadhukhan@Sun.COM
42910673SKrishnendu.Sadhukhan@Sun.COM /* Throw error for invalid/junk arguments */
43010673SKrishnendu.Sadhukhan@Sun.COM if (optind < argc) {
43110673SKrishnendu.Sadhukhan@Sun.COM int tmpind = optind;
43210673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "Unknown option(s): ");
43310673SKrishnendu.Sadhukhan@Sun.COM
43410673SKrishnendu.Sadhukhan@Sun.COM while (tmpind < argc) {
43510673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "%s ", argv[tmpind++]);
43610673SKrishnendu.Sadhukhan@Sun.COM }
43710673SKrishnendu.Sadhukhan@Sun.COM
43810673SKrishnendu.Sadhukhan@Sun.COM (void) fprintf(stderr, "\n");
43910673SKrishnendu.Sadhukhan@Sun.COM unknown_option = TRUE;
44010673SKrishnendu.Sadhukhan@Sun.COM }
44110673SKrishnendu.Sadhukhan@Sun.COM
44210673SKrishnendu.Sadhukhan@Sun.COM if (unknown_option) {
44310673SKrishnendu.Sadhukhan@Sun.COM print_usage(argv[0], FALSE);
44410673SKrishnendu.Sadhukhan@Sun.COM retval = 1;
44510673SKrishnendu.Sadhukhan@Sun.COM goto end_none;
44610673SKrishnendu.Sadhukhan@Sun.COM }
44710673SKrishnendu.Sadhukhan@Sun.COM
44810673SKrishnendu.Sadhukhan@Sun.COM (void) printf("%s\n%s\n", TITLE, COPYRIGHT);
44910673SKrishnendu.Sadhukhan@Sun.COM
45010673SKrishnendu.Sadhukhan@Sun.COM /*
45110673SKrishnendu.Sadhukhan@Sun.COM * Initialization
45210673SKrishnendu.Sadhukhan@Sun.COM */
45310673SKrishnendu.Sadhukhan@Sun.COM lt_klog_init();
45410673SKrishnendu.Sadhukhan@Sun.COM
45510673SKrishnendu.Sadhukhan@Sun.COM if (lt_table_init() != 0) {
45610673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Unable to load configuration table.\n");
45710673SKrishnendu.Sadhukhan@Sun.COM retval = 1;
45810673SKrishnendu.Sadhukhan@Sun.COM goto end_notable;
45910673SKrishnendu.Sadhukhan@Sun.COM }
46010673SKrishnendu.Sadhukhan@Sun.COM
46110673SKrishnendu.Sadhukhan@Sun.COM if (lt_dtrace_init() != 0) {
46210673SKrishnendu.Sadhukhan@Sun.COM lt_display_error("Unable to initialize dtrace.\n");
46310673SKrishnendu.Sadhukhan@Sun.COM retval = 1;
46410673SKrishnendu.Sadhukhan@Sun.COM goto end_nodtrace;
46510673SKrishnendu.Sadhukhan@Sun.COM }
46610673SKrishnendu.Sadhukhan@Sun.COM
46710673SKrishnendu.Sadhukhan@Sun.COM last_logged = lt_millisecond();
46810673SKrishnendu.Sadhukhan@Sun.COM
46910673SKrishnendu.Sadhukhan@Sun.COM (void) printf("Collecting data for %d seconds...\n",
47010673SKrishnendu.Sadhukhan@Sun.COM refresh_interval);
47110673SKrishnendu.Sadhukhan@Sun.COM
47210673SKrishnendu.Sadhukhan@Sun.COM gpipe = lt_gpipe_readfd();
47310673SKrishnendu.Sadhukhan@Sun.COM collect_end = last_logged + refresh_interval * 1000;
47410673SKrishnendu.Sadhukhan@Sun.COM for (;;) {
47510673SKrishnendu.Sadhukhan@Sun.COM fd_set read_fd;
47610673SKrishnendu.Sadhukhan@Sun.COM struct timeval timeout;
47710673SKrishnendu.Sadhukhan@Sun.COM int tsleep = collect_end - lt_millisecond();
47810673SKrishnendu.Sadhukhan@Sun.COM
47910673SKrishnendu.Sadhukhan@Sun.COM if (tsleep <= 0) {
48010673SKrishnendu.Sadhukhan@Sun.COM break;
48110673SKrishnendu.Sadhukhan@Sun.COM }
48210673SKrishnendu.Sadhukhan@Sun.COM
48310883SKrishnendu.Sadhukhan@Sun.COM /*
484*11789SKrishnendu.Sadhukhan@Sun.COM * Interval when we call dtrace_status() and collect
48510883SKrishnendu.Sadhukhan@Sun.COM * aggregated data.
48610883SKrishnendu.Sadhukhan@Sun.COM */
48710883SKrishnendu.Sadhukhan@Sun.COM if (tsleep > g_config.lt_cfg_snap_interval) {
48810883SKrishnendu.Sadhukhan@Sun.COM tsleep = g_config.lt_cfg_snap_interval;
48910673SKrishnendu.Sadhukhan@Sun.COM }
49010673SKrishnendu.Sadhukhan@Sun.COM
49110673SKrishnendu.Sadhukhan@Sun.COM timeout.tv_sec = tsleep / 1000;
49210673SKrishnendu.Sadhukhan@Sun.COM timeout.tv_usec = (tsleep % 1000) * 1000;
49310673SKrishnendu.Sadhukhan@Sun.COM
49410673SKrishnendu.Sadhukhan@Sun.COM FD_ZERO(&read_fd);
49510673SKrishnendu.Sadhukhan@Sun.COM FD_SET(gpipe, &read_fd);
49610673SKrishnendu.Sadhukhan@Sun.COM
49710673SKrishnendu.Sadhukhan@Sun.COM if (select(gpipe + 1, &read_fd, NULL, NULL, &timeout) > 0) {
49810673SKrishnendu.Sadhukhan@Sun.COM goto end_ubreak;
49910673SKrishnendu.Sadhukhan@Sun.COM }
50010673SKrishnendu.Sadhukhan@Sun.COM
50110673SKrishnendu.Sadhukhan@Sun.COM (void) lt_dtrace_work(0);
50210673SKrishnendu.Sadhukhan@Sun.COM }
50310673SKrishnendu.Sadhukhan@Sun.COM
50410673SKrishnendu.Sadhukhan@Sun.COM lt_display_init();
50510673SKrishnendu.Sadhukhan@Sun.COM
50610673SKrishnendu.Sadhukhan@Sun.COM do {
50710673SKrishnendu.Sadhukhan@Sun.COM current_time = lt_millisecond();
50810673SKrishnendu.Sadhukhan@Sun.COM
50910673SKrishnendu.Sadhukhan@Sun.COM lt_stat_clear_all();
51010673SKrishnendu.Sadhukhan@Sun.COM (void) lt_dtrace_collect();
51110673SKrishnendu.Sadhukhan@Sun.COM
51210673SKrishnendu.Sadhukhan@Sun.COM delta_time = current_time;
51310673SKrishnendu.Sadhukhan@Sun.COM current_time = lt_millisecond();
51410673SKrishnendu.Sadhukhan@Sun.COM delta_time = current_time - delta_time;
51510673SKrishnendu.Sadhukhan@Sun.COM
51610673SKrishnendu.Sadhukhan@Sun.COM if (log_interval > 0 &&
51710673SKrishnendu.Sadhukhan@Sun.COM current_time - last_logged > log_interval * 1000) {
51810673SKrishnendu.Sadhukhan@Sun.COM lt_klog_write();
51910673SKrishnendu.Sadhukhan@Sun.COM last_logged = current_time;
52010673SKrishnendu.Sadhukhan@Sun.COM }
52110673SKrishnendu.Sadhukhan@Sun.COM
52210673SKrishnendu.Sadhukhan@Sun.COM running = lt_display_loop(refresh_interval * 1000 -
52310673SKrishnendu.Sadhukhan@Sun.COM delta_time);
52410883SKrishnendu.Sadhukhan@Sun.COM
52510883SKrishnendu.Sadhukhan@Sun.COM /*
52610883SKrishnendu.Sadhukhan@Sun.COM * This is to avoid dynamic variable drop
52710883SKrishnendu.Sadhukhan@Sun.COM * in DTrace.
52810883SKrishnendu.Sadhukhan@Sun.COM */
52910883SKrishnendu.Sadhukhan@Sun.COM if (lt_drop_detected == B_TRUE) {
53010883SKrishnendu.Sadhukhan@Sun.COM if (lt_dtrace_deinit() != 0) {
53110883SKrishnendu.Sadhukhan@Sun.COM no_dtrace_cleanup = B_FALSE;
53210883SKrishnendu.Sadhukhan@Sun.COM retval = 1;
53310883SKrishnendu.Sadhukhan@Sun.COM break;
53410883SKrishnendu.Sadhukhan@Sun.COM }
53510883SKrishnendu.Sadhukhan@Sun.COM
53610883SKrishnendu.Sadhukhan@Sun.COM lt_drop_detected = B_FALSE;
53710883SKrishnendu.Sadhukhan@Sun.COM if (lt_dtrace_init() != 0) {
53810883SKrishnendu.Sadhukhan@Sun.COM retval = 1;
53910883SKrishnendu.Sadhukhan@Sun.COM break;
54010883SKrishnendu.Sadhukhan@Sun.COM }
54110883SKrishnendu.Sadhukhan@Sun.COM }
54210673SKrishnendu.Sadhukhan@Sun.COM } while (running != 0);
54310673SKrishnendu.Sadhukhan@Sun.COM
54410673SKrishnendu.Sadhukhan@Sun.COM lt_klog_write();
54510673SKrishnendu.Sadhukhan@Sun.COM
54610673SKrishnendu.Sadhukhan@Sun.COM /* Cleanup */
54710673SKrishnendu.Sadhukhan@Sun.COM lt_display_deinit();
54810673SKrishnendu.Sadhukhan@Sun.COM
54910673SKrishnendu.Sadhukhan@Sun.COM end_ubreak:
55010883SKrishnendu.Sadhukhan@Sun.COM if (no_dtrace_cleanup == B_FALSE || lt_dtrace_deinit() != 0)
55110883SKrishnendu.Sadhukhan@Sun.COM retval = 1;
55210883SKrishnendu.Sadhukhan@Sun.COM
55310673SKrishnendu.Sadhukhan@Sun.COM lt_stat_free_all();
55410673SKrishnendu.Sadhukhan@Sun.COM
55510673SKrishnendu.Sadhukhan@Sun.COM end_nodtrace:
55610673SKrishnendu.Sadhukhan@Sun.COM lt_table_deinit();
55710673SKrishnendu.Sadhukhan@Sun.COM
55810673SKrishnendu.Sadhukhan@Sun.COM end_notable:
55910673SKrishnendu.Sadhukhan@Sun.COM lt_klog_deinit();
56010673SKrishnendu.Sadhukhan@Sun.COM
56110673SKrishnendu.Sadhukhan@Sun.COM end_none:
56210673SKrishnendu.Sadhukhan@Sun.COM lt_gpipe_deinit();
56310673SKrishnendu.Sadhukhan@Sun.COM
56410673SKrishnendu.Sadhukhan@Sun.COM if (g_config.lt_cfg_config_name != NULL) {
56510673SKrishnendu.Sadhukhan@Sun.COM free(g_config.lt_cfg_config_name);
56610673SKrishnendu.Sadhukhan@Sun.COM }
56710673SKrishnendu.Sadhukhan@Sun.COM
56810673SKrishnendu.Sadhukhan@Sun.COM return (retval);
56910673SKrishnendu.Sadhukhan@Sun.COM }
570