xref: /onnv-gate/usr/src/cmd/latencytop/common/display.c (revision 11789:6c7658a179ca)
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 <stdio.h>
2710673SKrishnendu.Sadhukhan@Sun.COM #include <stdlib.h>
2810673SKrishnendu.Sadhukhan@Sun.COM #include <unistd.h>
2910673SKrishnendu.Sadhukhan@Sun.COM #include <string.h>
3010673SKrishnendu.Sadhukhan@Sun.COM #include <sys/types.h>
3110673SKrishnendu.Sadhukhan@Sun.COM #include <sys/time.h>
3210673SKrishnendu.Sadhukhan@Sun.COM #include <dirent.h>
3310673SKrishnendu.Sadhukhan@Sun.COM #include <curses.h>
3410673SKrishnendu.Sadhukhan@Sun.COM #include <time.h>
3510673SKrishnendu.Sadhukhan@Sun.COM #include <wchar.h>
3610673SKrishnendu.Sadhukhan@Sun.COM #include <ctype.h>
3710673SKrishnendu.Sadhukhan@Sun.COM #include <stdarg.h>
3810673SKrishnendu.Sadhukhan@Sun.COM #include <signal.h>
3910673SKrishnendu.Sadhukhan@Sun.COM 
4010673SKrishnendu.Sadhukhan@Sun.COM #include "latencytop.h"
4110673SKrishnendu.Sadhukhan@Sun.COM 
4210673SKrishnendu.Sadhukhan@Sun.COM #define	LT_WINDOW_X			80
4310673SKrishnendu.Sadhukhan@Sun.COM #define	LT_WINDOW_Y			24
4410673SKrishnendu.Sadhukhan@Sun.COM 
4510673SKrishnendu.Sadhukhan@Sun.COM #define	LT_COLOR_DEFAULT		1
4610673SKrishnendu.Sadhukhan@Sun.COM #define	LT_COLOR_HEADER			2
4710673SKrishnendu.Sadhukhan@Sun.COM 
4810673SKrishnendu.Sadhukhan@Sun.COM /* Windows created by libcurses */
4910673SKrishnendu.Sadhukhan@Sun.COM static WINDOW	*titlebar = NULL;
5010673SKrishnendu.Sadhukhan@Sun.COM static WINDOW	*captionbar = NULL;
5110673SKrishnendu.Sadhukhan@Sun.COM static WINDOW	*sysglobal_window = NULL;
5210673SKrishnendu.Sadhukhan@Sun.COM static WINDOW	*taskbar = NULL;
5310673SKrishnendu.Sadhukhan@Sun.COM static WINDOW	*process_window = NULL;
5410673SKrishnendu.Sadhukhan@Sun.COM static WINDOW	*hintbar = NULL;
5510673SKrishnendu.Sadhukhan@Sun.COM /* Screen dimension */
5610673SKrishnendu.Sadhukhan@Sun.COM static int	screen_width = 1, screen_height = 1;
5710673SKrishnendu.Sadhukhan@Sun.COM /* Is display initialized, i.e. are window pointers set up. */
5810673SKrishnendu.Sadhukhan@Sun.COM static int	display_initialized = FALSE;
5910673SKrishnendu.Sadhukhan@Sun.COM /* Is initscr() called */
6010673SKrishnendu.Sadhukhan@Sun.COM static int	curses_inited = FALSE;
6110673SKrishnendu.Sadhukhan@Sun.COM 
6210673SKrishnendu.Sadhukhan@Sun.COM /* To handle user key presses */
6310673SKrishnendu.Sadhukhan@Sun.COM static pid_t selected_pid = INVALID_PID;
6410673SKrishnendu.Sadhukhan@Sun.COM static id_t selected_tid = INVALID_TID;
6510673SKrishnendu.Sadhukhan@Sun.COM static lt_sort_t sort_type = LT_SORT_TOTAL;
6610673SKrishnendu.Sadhukhan@Sun.COM static int thread_mode = FALSE;
6710673SKrishnendu.Sadhukhan@Sun.COM /* Type of list being displayed */
6810673SKrishnendu.Sadhukhan@Sun.COM static int current_list_type = LT_LIST_CAUSE;
6910673SKrishnendu.Sadhukhan@Sun.COM static int show_help = FALSE;
7010673SKrishnendu.Sadhukhan@Sun.COM 
7110673SKrishnendu.Sadhukhan@Sun.COM /* Help functions that append/prepend a blank to the given string */
7210673SKrishnendu.Sadhukhan@Sun.COM #define	fill_space_right(a, b, c)	fill_space((a), (b), (c), TRUE)
7310673SKrishnendu.Sadhukhan@Sun.COM #define	fill_space_left(a, b, c)	fill_space((a), (b), (c), FALSE)
7410673SKrishnendu.Sadhukhan@Sun.COM 
7510673SKrishnendu.Sadhukhan@Sun.COM static void
fill_space(char * buffer,int len,int buffer_limit,int is_right)7610673SKrishnendu.Sadhukhan@Sun.COM fill_space(char *buffer, int len, int buffer_limit, int is_right)
7710673SKrishnendu.Sadhukhan@Sun.COM {
7810673SKrishnendu.Sadhukhan@Sun.COM 	int i = 0;
7910673SKrishnendu.Sadhukhan@Sun.COM 	int tofill;
8010673SKrishnendu.Sadhukhan@Sun.COM 
8110673SKrishnendu.Sadhukhan@Sun.COM 	if (len >= buffer_limit) {
8210673SKrishnendu.Sadhukhan@Sun.COM 		len = buffer_limit - 1;
8310673SKrishnendu.Sadhukhan@Sun.COM 	}
8410673SKrishnendu.Sadhukhan@Sun.COM 
8510673SKrishnendu.Sadhukhan@Sun.COM 	i = strlen(buffer);
8610673SKrishnendu.Sadhukhan@Sun.COM 
8710673SKrishnendu.Sadhukhan@Sun.COM 	if (i >= len) {
8810673SKrishnendu.Sadhukhan@Sun.COM 		return;
8910673SKrishnendu.Sadhukhan@Sun.COM 	}
9010673SKrishnendu.Sadhukhan@Sun.COM 
9110673SKrishnendu.Sadhukhan@Sun.COM 	tofill = len - i;
9210673SKrishnendu.Sadhukhan@Sun.COM 
9310673SKrishnendu.Sadhukhan@Sun.COM 	if (is_right) {
9410673SKrishnendu.Sadhukhan@Sun.COM 		(void) memset(&buffer[i], ' ', tofill);
9510673SKrishnendu.Sadhukhan@Sun.COM 		buffer[len] = '\0';
9610673SKrishnendu.Sadhukhan@Sun.COM 	} else {
9710673SKrishnendu.Sadhukhan@Sun.COM 		(void) memmove(&buffer[tofill], buffer, i+1);
9810673SKrishnendu.Sadhukhan@Sun.COM 		(void) memset(buffer, ' ', tofill);
9910673SKrishnendu.Sadhukhan@Sun.COM 	}
10010673SKrishnendu.Sadhukhan@Sun.COM }
10110673SKrishnendu.Sadhukhan@Sun.COM 
10210673SKrishnendu.Sadhukhan@Sun.COM /* Convert the nanosecond value to a human readable string */
10310673SKrishnendu.Sadhukhan@Sun.COM static const char *
get_time_string(double nanoseconds,char * buffer,int len,int fill_width)10410673SKrishnendu.Sadhukhan@Sun.COM get_time_string(double nanoseconds, char *buffer, int len, int fill_width)
10510673SKrishnendu.Sadhukhan@Sun.COM {
10610673SKrishnendu.Sadhukhan@Sun.COM 	const double ONE_USEC = 1000.0;
10710673SKrishnendu.Sadhukhan@Sun.COM 	const double ONE_MSEC = 1000000.0;
10810673SKrishnendu.Sadhukhan@Sun.COM 	const double ONE_SEC  = 1000000000.0;
10910673SKrishnendu.Sadhukhan@Sun.COM 
11010673SKrishnendu.Sadhukhan@Sun.COM 	if (nanoseconds < (ONE_USEC - .5)) {
11110673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(buffer, len, "%3.1f nsec", nanoseconds);
11210673SKrishnendu.Sadhukhan@Sun.COM 	} else if (nanoseconds < (ONE_MSEC - .5 * ONE_USEC)) {
11310673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(buffer, len,
11410673SKrishnendu.Sadhukhan@Sun.COM 		    "%3.1f usec", nanoseconds / ONE_USEC);
11510673SKrishnendu.Sadhukhan@Sun.COM 	} else if (nanoseconds < (ONE_SEC - .5 * ONE_MSEC)) {
11610673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(buffer, len,
11710673SKrishnendu.Sadhukhan@Sun.COM 		    "%3.1f msec", nanoseconds / ONE_MSEC);
11810673SKrishnendu.Sadhukhan@Sun.COM 	} else if (nanoseconds < 999.5 * ONE_SEC) {
11910673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(buffer, len,
12010673SKrishnendu.Sadhukhan@Sun.COM 		    "%3.1f  sec", nanoseconds / ONE_SEC);
12110673SKrishnendu.Sadhukhan@Sun.COM 	} else {
12210673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(buffer, len,
12310673SKrishnendu.Sadhukhan@Sun.COM 		    "%.0e sec", nanoseconds / ONE_SEC);
12410673SKrishnendu.Sadhukhan@Sun.COM 	}
12510673SKrishnendu.Sadhukhan@Sun.COM 
12610673SKrishnendu.Sadhukhan@Sun.COM 	fill_space_left(buffer, fill_width, len);
12710673SKrishnendu.Sadhukhan@Sun.COM 	return (buffer);
12810673SKrishnendu.Sadhukhan@Sun.COM }
12910673SKrishnendu.Sadhukhan@Sun.COM 
13010673SKrishnendu.Sadhukhan@Sun.COM /* Used in print_statistics below */
13110673SKrishnendu.Sadhukhan@Sun.COM #define	WIDTH_REASON_STRING	36
13210673SKrishnendu.Sadhukhan@Sun.COM #define	WIDTH_COUNT		12
13310673SKrishnendu.Sadhukhan@Sun.COM #define	WIDTH_AVG		12
13410673SKrishnendu.Sadhukhan@Sun.COM #define	WIDTH_MAX		12
13510673SKrishnendu.Sadhukhan@Sun.COM #define	WIDTH_PCT		8
13610673SKrishnendu.Sadhukhan@Sun.COM #define	BEGIN_COUNT		WIDTH_REASON_STRING
13710673SKrishnendu.Sadhukhan@Sun.COM #define	BEGIN_AVG		(BEGIN_COUNT + WIDTH_COUNT)
13810673SKrishnendu.Sadhukhan@Sun.COM #define	BEGIN_MAX		(BEGIN_AVG + WIDTH_AVG)
13910673SKrishnendu.Sadhukhan@Sun.COM #define	BEGIN_PCT		(BEGIN_MAX + WIDTH_MAX)
14010673SKrishnendu.Sadhukhan@Sun.COM 
14110673SKrishnendu.Sadhukhan@Sun.COM /*
14210673SKrishnendu.Sadhukhan@Sun.COM  * Print statistics in global/process pane. Called by print_sysglobal
14310673SKrishnendu.Sadhukhan@Sun.COM  * print_process.
14410673SKrishnendu.Sadhukhan@Sun.COM  *
14510673SKrishnendu.Sadhukhan@Sun.COM  * Parameters:
14610673SKrishnendu.Sadhukhan@Sun.COM  *		window - the global or process statistics window.
14710673SKrishnendu.Sadhukhan@Sun.COM  *		begin_line - where to start printing.
14810673SKrishnendu.Sadhukhan@Sun.COM  *		count - how many lines should be printed.
14910673SKrishnendu.Sadhukhan@Sun.COM  *		list - a stat_list.
15010673SKrishnendu.Sadhukhan@Sun.COM  */
15110673SKrishnendu.Sadhukhan@Sun.COM static void
print_statistics(WINDOW * window,int begin_line,int nlines,void * list)15210673SKrishnendu.Sadhukhan@Sun.COM print_statistics(WINDOW * window, int begin_line, int nlines, void *list)
15310673SKrishnendu.Sadhukhan@Sun.COM {
15410673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t total;
15510673SKrishnendu.Sadhukhan@Sun.COM 	int i = 0;
15610673SKrishnendu.Sadhukhan@Sun.COM 
15710673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
15810673SKrishnendu.Sadhukhan@Sun.COM 		return;
15910673SKrishnendu.Sadhukhan@Sun.COM 	}
16010673SKrishnendu.Sadhukhan@Sun.COM 
16110673SKrishnendu.Sadhukhan@Sun.COM 	total = lt_stat_list_get_gtotal(list);
16210673SKrishnendu.Sadhukhan@Sun.COM 
16310673SKrishnendu.Sadhukhan@Sun.COM 	if (total == 0) {
16410673SKrishnendu.Sadhukhan@Sun.COM 		return;
16510673SKrishnendu.Sadhukhan@Sun.COM 	}
16610673SKrishnendu.Sadhukhan@Sun.COM 
16710673SKrishnendu.Sadhukhan@Sun.COM 	while (i < nlines && lt_stat_list_has_item(list, i)) {
16810673SKrishnendu.Sadhukhan@Sun.COM 
16910673SKrishnendu.Sadhukhan@Sun.COM 		char tmp[WIDTH_REASON_STRING];
17010673SKrishnendu.Sadhukhan@Sun.COM 		const char *reason = lt_stat_list_get_reason(list, i);
17110673SKrishnendu.Sadhukhan@Sun.COM 		uint64_t count = lt_stat_list_get_count(list, i);
17210673SKrishnendu.Sadhukhan@Sun.COM 
17310673SKrishnendu.Sadhukhan@Sun.COM 		if (count == 0) {
17410673SKrishnendu.Sadhukhan@Sun.COM 			continue;
17510673SKrishnendu.Sadhukhan@Sun.COM 		}
17610673SKrishnendu.Sadhukhan@Sun.COM 
17710673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(tmp, sizeof (tmp), "%s", reason);
17810673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(window, i + begin_line, 0, "%s", tmp);
17910673SKrishnendu.Sadhukhan@Sun.COM 
18010673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(tmp, sizeof (tmp), "%llu", count);
18110673SKrishnendu.Sadhukhan@Sun.COM 		fill_space_left(tmp, WIDTH_COUNT, sizeof (tmp));
18210673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(window, i + begin_line, BEGIN_COUNT,
18310673SKrishnendu.Sadhukhan@Sun.COM 		    "%s", tmp);
18410673SKrishnendu.Sadhukhan@Sun.COM 
18510673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(window, i + begin_line, BEGIN_AVG,
18610673SKrishnendu.Sadhukhan@Sun.COM 		    "%s", get_time_string(
18710673SKrishnendu.Sadhukhan@Sun.COM 		    (double)lt_stat_list_get_sum(list, i) / count,
18810673SKrishnendu.Sadhukhan@Sun.COM 		    tmp, sizeof (tmp), WIDTH_AVG));
18910673SKrishnendu.Sadhukhan@Sun.COM 
19010673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(window, i + begin_line, BEGIN_MAX,
19110673SKrishnendu.Sadhukhan@Sun.COM 		    "%s", get_time_string(
19210673SKrishnendu.Sadhukhan@Sun.COM 		    (double)lt_stat_list_get_max(list, i),
19310673SKrishnendu.Sadhukhan@Sun.COM 		    tmp, sizeof (tmp), WIDTH_MAX));
19410673SKrishnendu.Sadhukhan@Sun.COM 
19510673SKrishnendu.Sadhukhan@Sun.COM 		if (LT_LIST_SPECIALS != current_list_type) {
19610673SKrishnendu.Sadhukhan@Sun.COM 			(void) snprintf(tmp, sizeof (tmp), "%.1f %%",
19710673SKrishnendu.Sadhukhan@Sun.COM 			    (double)lt_stat_list_get_sum(list, i)
19810673SKrishnendu.Sadhukhan@Sun.COM 			    / total * 100.0);
19910673SKrishnendu.Sadhukhan@Sun.COM 		} else {
20010673SKrishnendu.Sadhukhan@Sun.COM 			(void) snprintf(tmp, sizeof (tmp), "--- ");
20110673SKrishnendu.Sadhukhan@Sun.COM 		}
20210673SKrishnendu.Sadhukhan@Sun.COM 
20310673SKrishnendu.Sadhukhan@Sun.COM 		fill_space_left(tmp, WIDTH_PCT, sizeof (tmp));
20410673SKrishnendu.Sadhukhan@Sun.COM 
20510673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(window, i + begin_line, BEGIN_PCT,
20610673SKrishnendu.Sadhukhan@Sun.COM 		    "%s", tmp);
20710673SKrishnendu.Sadhukhan@Sun.COM 		i++;
20810673SKrishnendu.Sadhukhan@Sun.COM 	}
20910673SKrishnendu.Sadhukhan@Sun.COM }
21010673SKrishnendu.Sadhukhan@Sun.COM 
21110673SKrishnendu.Sadhukhan@Sun.COM /*
21210673SKrishnendu.Sadhukhan@Sun.COM  * Print statistics in global pane.
21310673SKrishnendu.Sadhukhan@Sun.COM  */
21410673SKrishnendu.Sadhukhan@Sun.COM static void
print_sysglobal(void)21510673SKrishnendu.Sadhukhan@Sun.COM print_sysglobal(void)
21610673SKrishnendu.Sadhukhan@Sun.COM {
21710673SKrishnendu.Sadhukhan@Sun.COM 	void *list;
21810673SKrishnendu.Sadhukhan@Sun.COM 	char header[256];
21910673SKrishnendu.Sadhukhan@Sun.COM 
22010673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
22110673SKrishnendu.Sadhukhan@Sun.COM 		return;
22210673SKrishnendu.Sadhukhan@Sun.COM 	}
22310673SKrishnendu.Sadhukhan@Sun.COM 
22410673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(sysglobal_window);
22510673SKrishnendu.Sadhukhan@Sun.COM 
22610673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattron(sysglobal_window, A_REVERSE);
22710673SKrishnendu.Sadhukhan@Sun.COM 	(void) snprintf(header, sizeof (header),
22810673SKrishnendu.Sadhukhan@Sun.COM 	    "%s", "System wide latencies");
22910673SKrishnendu.Sadhukhan@Sun.COM 	fill_space_right(header, screen_width, sizeof (header));
23010673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(sysglobal_window, 0, 0, "%s", header);
23110673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattroff(sysglobal_window, A_REVERSE);
23210673SKrishnendu.Sadhukhan@Sun.COM 
23310673SKrishnendu.Sadhukhan@Sun.COM 	list = lt_stat_list_create(current_list_type,
23410673SKrishnendu.Sadhukhan@Sun.COM 	    LT_LEVEL_GLOBAL, 0, 0, 10, sort_type);
23510673SKrishnendu.Sadhukhan@Sun.COM 	print_statistics(sysglobal_window, 1, 10, list);
23610673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_list_free(list);
23710673SKrishnendu.Sadhukhan@Sun.COM 
23810673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(sysglobal_window);
23910673SKrishnendu.Sadhukhan@Sun.COM }
24010673SKrishnendu.Sadhukhan@Sun.COM 
24110673SKrishnendu.Sadhukhan@Sun.COM /*
24210673SKrishnendu.Sadhukhan@Sun.COM  * Prints current operation mode. Mode is combination of:
24310673SKrishnendu.Sadhukhan@Sun.COM  *
24410673SKrishnendu.Sadhukhan@Sun.COM  * 	"Process or Thread", and "1 or 2 or 3".
24510673SKrishnendu.Sadhukhan@Sun.COM  */
24610673SKrishnendu.Sadhukhan@Sun.COM static void
print_current_mode()24710673SKrishnendu.Sadhukhan@Sun.COM print_current_mode()
24810673SKrishnendu.Sadhukhan@Sun.COM {
24910673SKrishnendu.Sadhukhan@Sun.COM 	char type;
25010673SKrishnendu.Sadhukhan@Sun.COM 
25110673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
25210673SKrishnendu.Sadhukhan@Sun.COM 		return;
25310673SKrishnendu.Sadhukhan@Sun.COM 	}
25410673SKrishnendu.Sadhukhan@Sun.COM 
25510673SKrishnendu.Sadhukhan@Sun.COM 	switch (current_list_type) {
25610673SKrishnendu.Sadhukhan@Sun.COM 	case LT_LIST_CAUSE:
25710673SKrishnendu.Sadhukhan@Sun.COM 		type = '1';
25810673SKrishnendu.Sadhukhan@Sun.COM 		break;
25910673SKrishnendu.Sadhukhan@Sun.COM 	case LT_LIST_SPECIALS:
26010673SKrishnendu.Sadhukhan@Sun.COM 		type = '2';
26110673SKrishnendu.Sadhukhan@Sun.COM 		break;
26210673SKrishnendu.Sadhukhan@Sun.COM 	case LT_LIST_SOBJ:
26310673SKrishnendu.Sadhukhan@Sun.COM 		type = '3';
26410673SKrishnendu.Sadhukhan@Sun.COM 		break;
26510673SKrishnendu.Sadhukhan@Sun.COM 	default:
26610673SKrishnendu.Sadhukhan@Sun.COM 		type = '?';
26710673SKrishnendu.Sadhukhan@Sun.COM 		break;
26810673SKrishnendu.Sadhukhan@Sun.COM 	}
26910673SKrishnendu.Sadhukhan@Sun.COM 
27010673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(process_window, 0, screen_width - 8, "View: %c%c",
27110673SKrishnendu.Sadhukhan@Sun.COM 	    type, thread_mode ? 'T' : 'P');
27210673SKrishnendu.Sadhukhan@Sun.COM }
27310673SKrishnendu.Sadhukhan@Sun.COM 
27410673SKrishnendu.Sadhukhan@Sun.COM /*
275*11789SKrishnendu.Sadhukhan@Sun.COM  * Print process window bar when the list is empty.
276*11789SKrishnendu.Sadhukhan@Sun.COM  */
277*11789SKrishnendu.Sadhukhan@Sun.COM static void
print_empty_process_bar()278*11789SKrishnendu.Sadhukhan@Sun.COM print_empty_process_bar()
279*11789SKrishnendu.Sadhukhan@Sun.COM {
280*11789SKrishnendu.Sadhukhan@Sun.COM 	char header[256];
281*11789SKrishnendu.Sadhukhan@Sun.COM 
282*11789SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
283*11789SKrishnendu.Sadhukhan@Sun.COM 		return;
284*11789SKrishnendu.Sadhukhan@Sun.COM 	}
285*11789SKrishnendu.Sadhukhan@Sun.COM 
286*11789SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(process_window);
287*11789SKrishnendu.Sadhukhan@Sun.COM 	(void) wattron(process_window, A_REVERSE);
288*11789SKrishnendu.Sadhukhan@Sun.COM 	(void) snprintf(header, sizeof (header),
289*11789SKrishnendu.Sadhukhan@Sun.COM 	    "No process/thread data is available");
290*11789SKrishnendu.Sadhukhan@Sun.COM 	fill_space_right(header, screen_width, sizeof (header));
291*11789SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(process_window, 0, 0, "%s", header);
292*11789SKrishnendu.Sadhukhan@Sun.COM 
293*11789SKrishnendu.Sadhukhan@Sun.COM 	print_current_mode();
294*11789SKrishnendu.Sadhukhan@Sun.COM 	(void) wattroff(process_window, A_REVERSE);
295*11789SKrishnendu.Sadhukhan@Sun.COM 
296*11789SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(process_window);
297*11789SKrishnendu.Sadhukhan@Sun.COM }
298*11789SKrishnendu.Sadhukhan@Sun.COM 
299*11789SKrishnendu.Sadhukhan@Sun.COM /*
30010673SKrishnendu.Sadhukhan@Sun.COM  * Print per-process statistics in process pane.
30110673SKrishnendu.Sadhukhan@Sun.COM  * This is called when mode of operation is process.
30210673SKrishnendu.Sadhukhan@Sun.COM  */
30310673SKrishnendu.Sadhukhan@Sun.COM static void
print_process(unsigned int pid)30410673SKrishnendu.Sadhukhan@Sun.COM print_process(unsigned int pid)
30510673SKrishnendu.Sadhukhan@Sun.COM {
30610673SKrishnendu.Sadhukhan@Sun.COM 	void *list;
30710673SKrishnendu.Sadhukhan@Sun.COM 	char header[256];
30810673SKrishnendu.Sadhukhan@Sun.COM 	char tmp[30];
30910673SKrishnendu.Sadhukhan@Sun.COM 
31010673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
31110673SKrishnendu.Sadhukhan@Sun.COM 		return;
31210673SKrishnendu.Sadhukhan@Sun.COM 	}
31310673SKrishnendu.Sadhukhan@Sun.COM 
31410673SKrishnendu.Sadhukhan@Sun.COM 	list = lt_stat_list_create(current_list_type, LT_LEVEL_PROCESS,
31510673SKrishnendu.Sadhukhan@Sun.COM 	    pid, 0, 8, sort_type);
31610673SKrishnendu.Sadhukhan@Sun.COM 
31710673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(process_window);
31810673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattron(process_window, A_REVERSE);
31910673SKrishnendu.Sadhukhan@Sun.COM 	(void) snprintf(header, sizeof (header), "Process %s (%i), %d threads",
32010673SKrishnendu.Sadhukhan@Sun.COM 	    lt_stat_proc_get_name(pid), pid, lt_stat_proc_get_nthreads(pid));
32110673SKrishnendu.Sadhukhan@Sun.COM 	fill_space_right(header, screen_width, sizeof (header));
32210673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(process_window, 0, 0, "%s", header);
32310673SKrishnendu.Sadhukhan@Sun.COM 
32410673SKrishnendu.Sadhukhan@Sun.COM 	if (current_list_type != LT_LIST_SPECIALS) {
32510673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(process_window, 0, 48, "Total: %s",
32610673SKrishnendu.Sadhukhan@Sun.COM 		    get_time_string((double)lt_stat_list_get_gtotal(list),
32710673SKrishnendu.Sadhukhan@Sun.COM 		    tmp, sizeof (tmp), 12));
32810673SKrishnendu.Sadhukhan@Sun.COM 	}
32910673SKrishnendu.Sadhukhan@Sun.COM 
33010673SKrishnendu.Sadhukhan@Sun.COM 	print_current_mode();
33110673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattroff(process_window, A_REVERSE);
33210673SKrishnendu.Sadhukhan@Sun.COM 	print_statistics(process_window, 1, 8, list);
33310673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_list_free(list);
33410673SKrishnendu.Sadhukhan@Sun.COM 
33510673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(process_window);
33610673SKrishnendu.Sadhukhan@Sun.COM }
33710673SKrishnendu.Sadhukhan@Sun.COM 
33810673SKrishnendu.Sadhukhan@Sun.COM /*
33910673SKrishnendu.Sadhukhan@Sun.COM  * Display the list of processes that are tracked, in task bar.
34010673SKrishnendu.Sadhukhan@Sun.COM  * This one is called when mode of operation is process.
34110673SKrishnendu.Sadhukhan@Sun.COM  */
34210673SKrishnendu.Sadhukhan@Sun.COM static void
print_taskbar_process(pid_t * pidlist,int pidlist_len,int pidlist_index)34310673SKrishnendu.Sadhukhan@Sun.COM print_taskbar_process(pid_t *pidlist, int pidlist_len, int pidlist_index)
34410673SKrishnendu.Sadhukhan@Sun.COM {
34510673SKrishnendu.Sadhukhan@Sun.COM 	const int ITEM_WIDTH = 8;
34610673SKrishnendu.Sadhukhan@Sun.COM 
34710673SKrishnendu.Sadhukhan@Sun.COM 	int number_item;
34810673SKrishnendu.Sadhukhan@Sun.COM 	int i;
34910673SKrishnendu.Sadhukhan@Sun.COM 	int xpos = 0;
35010673SKrishnendu.Sadhukhan@Sun.COM 
35110673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
35210673SKrishnendu.Sadhukhan@Sun.COM 		return;
35310673SKrishnendu.Sadhukhan@Sun.COM 	}
35410673SKrishnendu.Sadhukhan@Sun.COM 
35510673SKrishnendu.Sadhukhan@Sun.COM 	number_item = (screen_width / ITEM_WIDTH) - 1;
35610673SKrishnendu.Sadhukhan@Sun.COM 	i = pidlist_index - (pidlist_index % number_item);
35710673SKrishnendu.Sadhukhan@Sun.COM 
35810673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(taskbar);
35910673SKrishnendu.Sadhukhan@Sun.COM 
36010673SKrishnendu.Sadhukhan@Sun.COM 	if (i != 0) {
36110673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(taskbar, 0, xpos, "<-");
36210673SKrishnendu.Sadhukhan@Sun.COM 	}
36310673SKrishnendu.Sadhukhan@Sun.COM 
36410673SKrishnendu.Sadhukhan@Sun.COM 	xpos = ITEM_WIDTH / 2;
36510673SKrishnendu.Sadhukhan@Sun.COM 
36610673SKrishnendu.Sadhukhan@Sun.COM 	while (xpos + ITEM_WIDTH <= screen_width && i < pidlist_len) {
36710673SKrishnendu.Sadhukhan@Sun.COM 		char str[ITEM_WIDTH+1];
36810673SKrishnendu.Sadhukhan@Sun.COM 		int slen;
36910673SKrishnendu.Sadhukhan@Sun.COM 		const char *pname = lt_stat_proc_get_name(pidlist[i]);
37010673SKrishnendu.Sadhukhan@Sun.COM 
37110673SKrishnendu.Sadhukhan@Sun.COM 		if (pname && pname[0]) {
37210673SKrishnendu.Sadhukhan@Sun.COM 			(void) snprintf(str, sizeof (str) - 1, "%s", pname);
37310673SKrishnendu.Sadhukhan@Sun.COM 		} else {
37410673SKrishnendu.Sadhukhan@Sun.COM 			(void) snprintf(str, sizeof (str) - 1,
37510673SKrishnendu.Sadhukhan@Sun.COM 			    "<%d>", pidlist[i]);
37610673SKrishnendu.Sadhukhan@Sun.COM 		}
37710673SKrishnendu.Sadhukhan@Sun.COM 
37810673SKrishnendu.Sadhukhan@Sun.COM 		slen = strlen(str);
37910673SKrishnendu.Sadhukhan@Sun.COM 
38010673SKrishnendu.Sadhukhan@Sun.COM 		if (slen < ITEM_WIDTH) {
38110673SKrishnendu.Sadhukhan@Sun.COM 			(void) memset(&str[slen], ' ', ITEM_WIDTH - slen);
38210673SKrishnendu.Sadhukhan@Sun.COM 		}
38310673SKrishnendu.Sadhukhan@Sun.COM 
38410673SKrishnendu.Sadhukhan@Sun.COM 		str[sizeof (str) - 1] = '\0';
38510673SKrishnendu.Sadhukhan@Sun.COM 
38610673SKrishnendu.Sadhukhan@Sun.COM 		if (i == pidlist_index) {
38710673SKrishnendu.Sadhukhan@Sun.COM 			(void) wattron(taskbar, A_REVERSE);
38810673SKrishnendu.Sadhukhan@Sun.COM 		}
38910673SKrishnendu.Sadhukhan@Sun.COM 
39010673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(taskbar, 0, xpos, "%s", str);
39110673SKrishnendu.Sadhukhan@Sun.COM 
39210673SKrishnendu.Sadhukhan@Sun.COM 		if (i == pidlist_index) {
39310673SKrishnendu.Sadhukhan@Sun.COM 			(void) wattroff(taskbar, A_REVERSE);
39410673SKrishnendu.Sadhukhan@Sun.COM 		}
39510673SKrishnendu.Sadhukhan@Sun.COM 
39610673SKrishnendu.Sadhukhan@Sun.COM 		xpos += ITEM_WIDTH;
39710673SKrishnendu.Sadhukhan@Sun.COM 		i++;
39810673SKrishnendu.Sadhukhan@Sun.COM 	}
39910673SKrishnendu.Sadhukhan@Sun.COM 
40010673SKrishnendu.Sadhukhan@Sun.COM 	if (i != pidlist_len) {
40110673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(taskbar, 0, screen_width - 2, "->");
40210673SKrishnendu.Sadhukhan@Sun.COM 	}
40310673SKrishnendu.Sadhukhan@Sun.COM 
40410673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(taskbar);
40510673SKrishnendu.Sadhukhan@Sun.COM }
40610673SKrishnendu.Sadhukhan@Sun.COM 
40710673SKrishnendu.Sadhukhan@Sun.COM /*
40810673SKrishnendu.Sadhukhan@Sun.COM  * Display the list of processes that are tracked, in task bar.
40910673SKrishnendu.Sadhukhan@Sun.COM  * This one is called when mode of operation is thread.
41010673SKrishnendu.Sadhukhan@Sun.COM  */
41110673SKrishnendu.Sadhukhan@Sun.COM static void
print_taskbar_thread(pid_t * pidlist,id_t * tidlist,int list_len,int list_index)41210673SKrishnendu.Sadhukhan@Sun.COM print_taskbar_thread(pid_t *pidlist, id_t *tidlist, int list_len,
41310673SKrishnendu.Sadhukhan@Sun.COM     int list_index)
41410673SKrishnendu.Sadhukhan@Sun.COM {
41510673SKrishnendu.Sadhukhan@Sun.COM 	const int ITEM_WIDTH = 12;
41610673SKrishnendu.Sadhukhan@Sun.COM 
41710673SKrishnendu.Sadhukhan@Sun.COM 	int number_item;
41810673SKrishnendu.Sadhukhan@Sun.COM 	int i;
41910673SKrishnendu.Sadhukhan@Sun.COM 	int xpos = 0;
42010673SKrishnendu.Sadhukhan@Sun.COM 	const char *pname = NULL;
42110673SKrishnendu.Sadhukhan@Sun.COM 	pid_t last_pid = INVALID_PID;
42210673SKrishnendu.Sadhukhan@Sun.COM 
42310673SKrishnendu.Sadhukhan@Sun.COM 
42410673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
42510673SKrishnendu.Sadhukhan@Sun.COM 		return;
42610673SKrishnendu.Sadhukhan@Sun.COM 	}
42710673SKrishnendu.Sadhukhan@Sun.COM 
42810673SKrishnendu.Sadhukhan@Sun.COM 	number_item = (screen_width - 8) / ITEM_WIDTH;
42910673SKrishnendu.Sadhukhan@Sun.COM 	i = list_index - (list_index % number_item);
43010673SKrishnendu.Sadhukhan@Sun.COM 
43110673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(taskbar);
43210673SKrishnendu.Sadhukhan@Sun.COM 
43310673SKrishnendu.Sadhukhan@Sun.COM 	if (i != 0) {
43410673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(taskbar, 0, xpos, "<-");
43510673SKrishnendu.Sadhukhan@Sun.COM 	}
43610673SKrishnendu.Sadhukhan@Sun.COM 
43710673SKrishnendu.Sadhukhan@Sun.COM 	xpos = 4;
43810673SKrishnendu.Sadhukhan@Sun.COM 
43910673SKrishnendu.Sadhukhan@Sun.COM 	while (xpos + ITEM_WIDTH <= screen_width && i < list_len) {
44010673SKrishnendu.Sadhukhan@Sun.COM 		char str[ITEM_WIDTH+1];
44110673SKrishnendu.Sadhukhan@Sun.COM 		int slen, tlen;
44210673SKrishnendu.Sadhukhan@Sun.COM 
44310673SKrishnendu.Sadhukhan@Sun.COM 		if (pidlist[i] != last_pid) {
44410673SKrishnendu.Sadhukhan@Sun.COM 			pname = lt_stat_proc_get_name(pidlist[i]);
44510673SKrishnendu.Sadhukhan@Sun.COM 			last_pid = pidlist[i];
44610673SKrishnendu.Sadhukhan@Sun.COM 		}
44710673SKrishnendu.Sadhukhan@Sun.COM 
44810673SKrishnendu.Sadhukhan@Sun.COM 		/*
44910673SKrishnendu.Sadhukhan@Sun.COM 		 * Calculate length of thread's ID; use shorter process name
45010673SKrishnendu.Sadhukhan@Sun.COM 		 * in order to save space on the screen.
45110673SKrishnendu.Sadhukhan@Sun.COM 		 */
45210673SKrishnendu.Sadhukhan@Sun.COM 		tlen = snprintf(NULL, 0, "_%d", tidlist[i]);
45310673SKrishnendu.Sadhukhan@Sun.COM 
45410673SKrishnendu.Sadhukhan@Sun.COM 		if (pname && pname[0]) {
45510673SKrishnendu.Sadhukhan@Sun.COM 			(void) snprintf(str, sizeof (str) - tlen - 1,
45610673SKrishnendu.Sadhukhan@Sun.COM 			    "%s", pname);
45710673SKrishnendu.Sadhukhan@Sun.COM 		} else {
45810673SKrishnendu.Sadhukhan@Sun.COM 			(void) snprintf(str, sizeof (str) - tlen - 1,
45910673SKrishnendu.Sadhukhan@Sun.COM 			    "<%d>", pidlist[i]);
46010673SKrishnendu.Sadhukhan@Sun.COM 		}
46110673SKrishnendu.Sadhukhan@Sun.COM 
46210673SKrishnendu.Sadhukhan@Sun.COM 		slen = strlen(str);
46310673SKrishnendu.Sadhukhan@Sun.COM 
46410673SKrishnendu.Sadhukhan@Sun.COM 		(void) snprintf(&str[slen], sizeof (str) - slen,
46510673SKrishnendu.Sadhukhan@Sun.COM 		    "_%d", tidlist[i]);
46610673SKrishnendu.Sadhukhan@Sun.COM 
46710673SKrishnendu.Sadhukhan@Sun.COM 		slen += tlen;
46810673SKrishnendu.Sadhukhan@Sun.COM 
46910673SKrishnendu.Sadhukhan@Sun.COM 		if (slen < ITEM_WIDTH) {
47010673SKrishnendu.Sadhukhan@Sun.COM 			(void) memset(&str[slen], ' ', ITEM_WIDTH - slen);
47110673SKrishnendu.Sadhukhan@Sun.COM 		}
47210673SKrishnendu.Sadhukhan@Sun.COM 
47310673SKrishnendu.Sadhukhan@Sun.COM 		str[sizeof (str) - 1] = '\0';
47410673SKrishnendu.Sadhukhan@Sun.COM 
47510673SKrishnendu.Sadhukhan@Sun.COM 		if (i == list_index) {
47610673SKrishnendu.Sadhukhan@Sun.COM 			(void) wattron(taskbar, A_REVERSE);
47710673SKrishnendu.Sadhukhan@Sun.COM 		}
47810673SKrishnendu.Sadhukhan@Sun.COM 
47910673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(taskbar, 0, xpos, "%s", str);
48010673SKrishnendu.Sadhukhan@Sun.COM 
48110673SKrishnendu.Sadhukhan@Sun.COM 		if (i == list_index) {
48210673SKrishnendu.Sadhukhan@Sun.COM 			(void) wattroff(taskbar, A_REVERSE);
48310673SKrishnendu.Sadhukhan@Sun.COM 		}
48410673SKrishnendu.Sadhukhan@Sun.COM 
48510673SKrishnendu.Sadhukhan@Sun.COM 		xpos += ITEM_WIDTH;
48610673SKrishnendu.Sadhukhan@Sun.COM 		i++;
48710673SKrishnendu.Sadhukhan@Sun.COM 	}
48810673SKrishnendu.Sadhukhan@Sun.COM 
48910673SKrishnendu.Sadhukhan@Sun.COM 	if (i != list_len) {
49010673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(taskbar, 0, screen_width - 2, "->");
49110673SKrishnendu.Sadhukhan@Sun.COM 	}
49210673SKrishnendu.Sadhukhan@Sun.COM 
49310673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(taskbar);
49410673SKrishnendu.Sadhukhan@Sun.COM }
49510673SKrishnendu.Sadhukhan@Sun.COM 
49610673SKrishnendu.Sadhukhan@Sun.COM /*
49710673SKrishnendu.Sadhukhan@Sun.COM  * Print per-thread statistics in process pane.
49810673SKrishnendu.Sadhukhan@Sun.COM  * This is called when mode of operation is thread.
49910673SKrishnendu.Sadhukhan@Sun.COM  */
50010673SKrishnendu.Sadhukhan@Sun.COM static void
print_thread(pid_t pid,id_t tid)50110673SKrishnendu.Sadhukhan@Sun.COM print_thread(pid_t pid, id_t tid)
50210673SKrishnendu.Sadhukhan@Sun.COM {
50310673SKrishnendu.Sadhukhan@Sun.COM 	void *list;
50410673SKrishnendu.Sadhukhan@Sun.COM 	char header[256];
50510673SKrishnendu.Sadhukhan@Sun.COM 	char tmp[30];
50610673SKrishnendu.Sadhukhan@Sun.COM 
50710673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
50810673SKrishnendu.Sadhukhan@Sun.COM 		return;
50910673SKrishnendu.Sadhukhan@Sun.COM 	}
51010673SKrishnendu.Sadhukhan@Sun.COM 
51110673SKrishnendu.Sadhukhan@Sun.COM 	list = lt_stat_list_create(current_list_type, LT_LEVEL_THREAD,
51210673SKrishnendu.Sadhukhan@Sun.COM 	    pid, tid, 8, sort_type);
51310673SKrishnendu.Sadhukhan@Sun.COM 
51410673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(process_window);
51510673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattron(process_window, A_REVERSE);
51610673SKrishnendu.Sadhukhan@Sun.COM 	(void) snprintf(header, sizeof (header),
51710673SKrishnendu.Sadhukhan@Sun.COM 	    "Process %s (%i), LWP %d",
51810673SKrishnendu.Sadhukhan@Sun.COM 	    lt_stat_proc_get_name(pid), pid, tid);
51910673SKrishnendu.Sadhukhan@Sun.COM 	fill_space_right(header, screen_width, sizeof (header));
52010673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(process_window, 0, 0, "%s", header);
52110673SKrishnendu.Sadhukhan@Sun.COM 
52210673SKrishnendu.Sadhukhan@Sun.COM 	if (current_list_type != LT_LIST_SPECIALS) {
52310673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(process_window, 0, 48, "Total: %s",
52410673SKrishnendu.Sadhukhan@Sun.COM 		    get_time_string(
52510673SKrishnendu.Sadhukhan@Sun.COM 		    (double)lt_stat_list_get_gtotal(list),
52610673SKrishnendu.Sadhukhan@Sun.COM 		    tmp, sizeof (tmp), 12));
52710673SKrishnendu.Sadhukhan@Sun.COM 	}
52810673SKrishnendu.Sadhukhan@Sun.COM 
52910673SKrishnendu.Sadhukhan@Sun.COM 	print_current_mode();
53010673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattroff(process_window, A_REVERSE);
53110673SKrishnendu.Sadhukhan@Sun.COM 	print_statistics(process_window, 1, 8, list);
53210673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_list_free(list);
53310673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(process_window);
53410673SKrishnendu.Sadhukhan@Sun.COM }
53510673SKrishnendu.Sadhukhan@Sun.COM 
53610673SKrishnendu.Sadhukhan@Sun.COM /*
53710673SKrishnendu.Sadhukhan@Sun.COM  * Update hint string at the bottom line. The message to print is stored in
53810673SKrishnendu.Sadhukhan@Sun.COM  * hint. If hint is NULL, the function will display its own message.
53910673SKrishnendu.Sadhukhan@Sun.COM  */
54010673SKrishnendu.Sadhukhan@Sun.COM static void
print_hint(const char * hint)54110673SKrishnendu.Sadhukhan@Sun.COM print_hint(const char *hint)
54210673SKrishnendu.Sadhukhan@Sun.COM {
54310673SKrishnendu.Sadhukhan@Sun.COM 	const char *HINTS[] =    {
54410673SKrishnendu.Sadhukhan@Sun.COM 		"Press '<' or '>' to switch between processes.",
54510673SKrishnendu.Sadhukhan@Sun.COM 		"Press 'q' to exit.",
54610673SKrishnendu.Sadhukhan@Sun.COM 		"Press 'r' to refresh immediately.",
54710673SKrishnendu.Sadhukhan@Sun.COM 		"Press 't' to toggle Process/Thread display mode.",
54810673SKrishnendu.Sadhukhan@Sun.COM 		"Press 'h' for help.",
549*11789SKrishnendu.Sadhukhan@Sun.COM 		"Use 'c', 'a', 'm', 'p' to change sort criteria.",
55010673SKrishnendu.Sadhukhan@Sun.COM 		"Use '1', '2', '3' to switch between windows."
55110673SKrishnendu.Sadhukhan@Sun.COM 	};
55210673SKrishnendu.Sadhukhan@Sun.COM 	const uint64_t update_interval = 5000; /* 5 seconds */
55310673SKrishnendu.Sadhukhan@Sun.COM 
55410673SKrishnendu.Sadhukhan@Sun.COM 	static int index = 0;
55510673SKrishnendu.Sadhukhan@Sun.COM 	static uint64_t next_hint = 0;
55610673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t now = lt_millisecond();
55710673SKrishnendu.Sadhukhan@Sun.COM 
55810673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
55910673SKrishnendu.Sadhukhan@Sun.COM 		return;
56010673SKrishnendu.Sadhukhan@Sun.COM 	}
56110673SKrishnendu.Sadhukhan@Sun.COM 
56210673SKrishnendu.Sadhukhan@Sun.COM 	if (hint == NULL) {
56310673SKrishnendu.Sadhukhan@Sun.COM 		if (now < next_hint) {
56410673SKrishnendu.Sadhukhan@Sun.COM 			return;
56510673SKrishnendu.Sadhukhan@Sun.COM 		}
56610673SKrishnendu.Sadhukhan@Sun.COM 
56710673SKrishnendu.Sadhukhan@Sun.COM 		hint = HINTS[index];
56810673SKrishnendu.Sadhukhan@Sun.COM 		index = (index + 1) % (sizeof (HINTS) / sizeof (HINTS[0]));
56910673SKrishnendu.Sadhukhan@Sun.COM 		next_hint = now + update_interval;
57010673SKrishnendu.Sadhukhan@Sun.COM 	} else {
57110673SKrishnendu.Sadhukhan@Sun.COM 		/*
57210673SKrishnendu.Sadhukhan@Sun.COM 		 * Important messages are displayed at least every 2 cycles.
57310673SKrishnendu.Sadhukhan@Sun.COM 		 */
57410673SKrishnendu.Sadhukhan@Sun.COM 		next_hint = now + update_interval * 2;
57510673SKrishnendu.Sadhukhan@Sun.COM 	}
57610673SKrishnendu.Sadhukhan@Sun.COM 
57710673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(hintbar);
57810673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(hintbar, 0, (screen_width - strlen(hint)) / 2,
57910673SKrishnendu.Sadhukhan@Sun.COM 	    "%s", hint);
58010673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(hintbar);
58110673SKrishnendu.Sadhukhan@Sun.COM }
58210673SKrishnendu.Sadhukhan@Sun.COM 
58310673SKrishnendu.Sadhukhan@Sun.COM /*
58410673SKrishnendu.Sadhukhan@Sun.COM  * Create a PID list or a PID/TID list (if operation mode is thread) from
58510673SKrishnendu.Sadhukhan@Sun.COM  * available statistics.
58610673SKrishnendu.Sadhukhan@Sun.COM  */
58710673SKrishnendu.Sadhukhan@Sun.COM static void
get_plist(pid_t ** plist,id_t ** tlist,int * list_len,int * list_index)58810673SKrishnendu.Sadhukhan@Sun.COM get_plist(pid_t **plist, id_t **tlist, int *list_len, int *list_index)
58910673SKrishnendu.Sadhukhan@Sun.COM {
59010673SKrishnendu.Sadhukhan@Sun.COM 	if (!thread_mode) {
59110673SKrishnendu.Sadhukhan@Sun.COM 		/* Per-process mode */
59210673SKrishnendu.Sadhukhan@Sun.COM 		*list_len = lt_stat_proc_list_create(plist, NULL);
59310673SKrishnendu.Sadhukhan@Sun.COM 		/* Search for previously selected PID */
59410673SKrishnendu.Sadhukhan@Sun.COM 		for (*list_index = 0; *list_index < *list_len &&
59510673SKrishnendu.Sadhukhan@Sun.COM 		    (*plist)[*list_index] != selected_pid;
59610673SKrishnendu.Sadhukhan@Sun.COM 		    ++*list_index) {
59710673SKrishnendu.Sadhukhan@Sun.COM 		}
59810673SKrishnendu.Sadhukhan@Sun.COM 
59910673SKrishnendu.Sadhukhan@Sun.COM 		if (*list_index >= *list_len) {
60010673SKrishnendu.Sadhukhan@Sun.COM 			/*
60110673SKrishnendu.Sadhukhan@Sun.COM 			 * The previously selected pid is gone.
60210673SKrishnendu.Sadhukhan@Sun.COM 			 * Select the first one.
60310673SKrishnendu.Sadhukhan@Sun.COM 			 */
60410673SKrishnendu.Sadhukhan@Sun.COM 			*list_index = 0;
60510673SKrishnendu.Sadhukhan@Sun.COM 		}
60610673SKrishnendu.Sadhukhan@Sun.COM 	} else {
60710673SKrishnendu.Sadhukhan@Sun.COM 		/* Per-thread mode */
60810673SKrishnendu.Sadhukhan@Sun.COM 		*list_len = lt_stat_proc_list_create(plist, tlist);
60910673SKrishnendu.Sadhukhan@Sun.COM 
61010673SKrishnendu.Sadhukhan@Sun.COM 		/* Search for previously selected PID & TID */
61110673SKrishnendu.Sadhukhan@Sun.COM 		for (*list_index = 0; *list_index < *list_len;
61210673SKrishnendu.Sadhukhan@Sun.COM 		    ++*list_index) {
61310673SKrishnendu.Sadhukhan@Sun.COM 			if ((*plist)[*list_index] == selected_pid &&
61410673SKrishnendu.Sadhukhan@Sun.COM 			    (*tlist)[*list_index] == selected_tid) {
61510673SKrishnendu.Sadhukhan@Sun.COM 				break;
61610673SKrishnendu.Sadhukhan@Sun.COM 			}
61710673SKrishnendu.Sadhukhan@Sun.COM 		}
61810673SKrishnendu.Sadhukhan@Sun.COM 
61910673SKrishnendu.Sadhukhan@Sun.COM 		if (*list_index >= *list_len) {
62010673SKrishnendu.Sadhukhan@Sun.COM 			/*
62110673SKrishnendu.Sadhukhan@Sun.COM 			 * The previously selected pid/tid is gone.
62210673SKrishnendu.Sadhukhan@Sun.COM 			 * Select the first one.
62310673SKrishnendu.Sadhukhan@Sun.COM 			 */
62410673SKrishnendu.Sadhukhan@Sun.COM 			for (*list_index = 0;
62510673SKrishnendu.Sadhukhan@Sun.COM 			    *list_index < *list_len &&
62610673SKrishnendu.Sadhukhan@Sun.COM 			    (*plist)[*list_index] != selected_pid;
62710673SKrishnendu.Sadhukhan@Sun.COM 			    ++*list_index) {
62810673SKrishnendu.Sadhukhan@Sun.COM 			}
62910673SKrishnendu.Sadhukhan@Sun.COM 		}
63010673SKrishnendu.Sadhukhan@Sun.COM 
63110673SKrishnendu.Sadhukhan@Sun.COM 		if (*list_index >= *list_len) {
63210673SKrishnendu.Sadhukhan@Sun.COM 			/*
63310673SKrishnendu.Sadhukhan@Sun.COM 			 * The previously selected pid is gone.
63410673SKrishnendu.Sadhukhan@Sun.COM 			 * Select the first one
63510673SKrishnendu.Sadhukhan@Sun.COM 			 */
63610673SKrishnendu.Sadhukhan@Sun.COM 			*list_index = 0;
63710673SKrishnendu.Sadhukhan@Sun.COM 		}
63810673SKrishnendu.Sadhukhan@Sun.COM 	}
63910673SKrishnendu.Sadhukhan@Sun.COM }
64010673SKrishnendu.Sadhukhan@Sun.COM 
64110673SKrishnendu.Sadhukhan@Sun.COM /* Print help message when user presses 'h' hot key */
64210673SKrishnendu.Sadhukhan@Sun.COM static void
print_help(void)64310673SKrishnendu.Sadhukhan@Sun.COM print_help(void)
64410673SKrishnendu.Sadhukhan@Sun.COM {
64510673SKrishnendu.Sadhukhan@Sun.COM 	const char *HELP[] =    {
64610673SKrishnendu.Sadhukhan@Sun.COM 		TITLE,
64710673SKrishnendu.Sadhukhan@Sun.COM 		COPYRIGHT,
64810673SKrishnendu.Sadhukhan@Sun.COM 		"",
64910673SKrishnendu.Sadhukhan@Sun.COM 		"These single-character commands are available:",
65010673SKrishnendu.Sadhukhan@Sun.COM 		"<       - Move to previous process/thread.",
65110673SKrishnendu.Sadhukhan@Sun.COM 		">       - Move to next process/thread.",
65210673SKrishnendu.Sadhukhan@Sun.COM 		"q       - Exit.",
65310673SKrishnendu.Sadhukhan@Sun.COM 		"r       - Refresh.",
65410673SKrishnendu.Sadhukhan@Sun.COM 		"t       - Toggle process/thread mode.",
65510673SKrishnendu.Sadhukhan@Sun.COM 		"c       - Sort by count.",
65610673SKrishnendu.Sadhukhan@Sun.COM 		"a       - Sort by average.",
65710673SKrishnendu.Sadhukhan@Sun.COM 		"m       - Sort by maximum.",
65810673SKrishnendu.Sadhukhan@Sun.COM 		"p       - Sort by percent.",
65910673SKrishnendu.Sadhukhan@Sun.COM 		"1       - Show list by causes.",
66010673SKrishnendu.Sadhukhan@Sun.COM 		"2       - Show list of special entries.",
66110673SKrishnendu.Sadhukhan@Sun.COM 		"3       - Show list by synchronization objects.",
66210673SKrishnendu.Sadhukhan@Sun.COM 		"h       - Show this help.",
66310673SKrishnendu.Sadhukhan@Sun.COM 		"",
66410673SKrishnendu.Sadhukhan@Sun.COM 		"Press any key to continue..."
66510673SKrishnendu.Sadhukhan@Sun.COM 	};
66610673SKrishnendu.Sadhukhan@Sun.COM 	int i;
66710673SKrishnendu.Sadhukhan@Sun.COM 
66810673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
66910673SKrishnendu.Sadhukhan@Sun.COM 		return;
67010673SKrishnendu.Sadhukhan@Sun.COM 	}
67110673SKrishnendu.Sadhukhan@Sun.COM 
67210673SKrishnendu.Sadhukhan@Sun.COM 	for (i = 0; i < sizeof (HELP) / sizeof (HELP[0]); ++i) {
67310673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(stdscr, i, 0, "%s", HELP[i]);
67410673SKrishnendu.Sadhukhan@Sun.COM 	}
67510673SKrishnendu.Sadhukhan@Sun.COM 
67610673SKrishnendu.Sadhukhan@Sun.COM 	(void) refresh();
67710673SKrishnendu.Sadhukhan@Sun.COM }
67810673SKrishnendu.Sadhukhan@Sun.COM 
67910673SKrishnendu.Sadhukhan@Sun.COM /*
68010673SKrishnendu.Sadhukhan@Sun.COM  * Print title on screen
68110673SKrishnendu.Sadhukhan@Sun.COM  */
68210673SKrishnendu.Sadhukhan@Sun.COM static void
print_title(void)68310673SKrishnendu.Sadhukhan@Sun.COM print_title(void)
68410673SKrishnendu.Sadhukhan@Sun.COM {
68510673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
68610673SKrishnendu.Sadhukhan@Sun.COM 		return;
68710673SKrishnendu.Sadhukhan@Sun.COM 	}
68810673SKrishnendu.Sadhukhan@Sun.COM 
68910673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattrset(titlebar, COLOR_PAIR(LT_COLOR_HEADER));
69010673SKrishnendu.Sadhukhan@Sun.COM 	(void) wbkgd(titlebar, COLOR_PAIR(LT_COLOR_HEADER));
69110673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(titlebar);
69210673SKrishnendu.Sadhukhan@Sun.COM 
69310673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(titlebar, 0, (screen_width - strlen(TITLE)) / 2,
69410673SKrishnendu.Sadhukhan@Sun.COM 	    "%s", TITLE);
69510673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(titlebar);
69610673SKrishnendu.Sadhukhan@Sun.COM 
69710673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(captionbar);
69810673SKrishnendu.Sadhukhan@Sun.COM 	(void) mvwprintw(captionbar, 0, 0, "%s",
69910673SKrishnendu.Sadhukhan@Sun.COM 	    "               Cause                    "
70010673SKrishnendu.Sadhukhan@Sun.COM 	    "Count      Average     Maximum   Percent");
70110673SKrishnendu.Sadhukhan@Sun.COM 	(void) wrefresh(captionbar);
70210673SKrishnendu.Sadhukhan@Sun.COM 
70310673SKrishnendu.Sadhukhan@Sun.COM 	(void) wattrset(hintbar, COLOR_PAIR(LT_COLOR_HEADER));
70410673SKrishnendu.Sadhukhan@Sun.COM 	(void) wbkgd(hintbar, COLOR_PAIR(LT_COLOR_HEADER));
70510673SKrishnendu.Sadhukhan@Sun.COM }
70610673SKrishnendu.Sadhukhan@Sun.COM 
70710673SKrishnendu.Sadhukhan@Sun.COM /*
70810673SKrishnendu.Sadhukhan@Sun.COM  * Handle signal from terminal resize
70910673SKrishnendu.Sadhukhan@Sun.COM  */
71010673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
71110673SKrishnendu.Sadhukhan@Sun.COM static void
on_resize(int sig)71210673SKrishnendu.Sadhukhan@Sun.COM on_resize(int sig)
71310673SKrishnendu.Sadhukhan@Sun.COM {
71410673SKrishnendu.Sadhukhan@Sun.COM 	lt_gpipe_break("r");
71510673SKrishnendu.Sadhukhan@Sun.COM }
71610673SKrishnendu.Sadhukhan@Sun.COM 
71710673SKrishnendu.Sadhukhan@Sun.COM /*
71810673SKrishnendu.Sadhukhan@Sun.COM  * Initialize display. Display will be cleared when this function returns.
71910673SKrishnendu.Sadhukhan@Sun.COM  */
72010673SKrishnendu.Sadhukhan@Sun.COM void
lt_display_init(void)72110673SKrishnendu.Sadhukhan@Sun.COM lt_display_init(void)
72210673SKrishnendu.Sadhukhan@Sun.COM {
72310673SKrishnendu.Sadhukhan@Sun.COM 	if (display_initialized) {
72410673SKrishnendu.Sadhukhan@Sun.COM 		return;
72510673SKrishnendu.Sadhukhan@Sun.COM 	}
72610673SKrishnendu.Sadhukhan@Sun.COM 
72710673SKrishnendu.Sadhukhan@Sun.COM 	/* Window resize signal */
72810673SKrishnendu.Sadhukhan@Sun.COM 	(void) signal(SIGWINCH, on_resize);
72910673SKrishnendu.Sadhukhan@Sun.COM 
73010673SKrishnendu.Sadhukhan@Sun.COM 	/* Initialize curses library */
73110673SKrishnendu.Sadhukhan@Sun.COM 	(void) initscr();
73210673SKrishnendu.Sadhukhan@Sun.COM 	(void) start_color();
73310673SKrishnendu.Sadhukhan@Sun.COM 	(void) keypad(stdscr, TRUE);
73410673SKrishnendu.Sadhukhan@Sun.COM 	(void) nonl();
73510673SKrishnendu.Sadhukhan@Sun.COM 	(void) cbreak();
73610673SKrishnendu.Sadhukhan@Sun.COM 	(void) noecho();
73710673SKrishnendu.Sadhukhan@Sun.COM 	(void) curs_set(0);
73810673SKrishnendu.Sadhukhan@Sun.COM 
73910673SKrishnendu.Sadhukhan@Sun.COM 	/* Set up color pairs */
74010673SKrishnendu.Sadhukhan@Sun.COM 	(void) init_pair(LT_COLOR_DEFAULT, COLOR_WHITE, COLOR_BLACK);
74110673SKrishnendu.Sadhukhan@Sun.COM 	(void) init_pair(LT_COLOR_HEADER, COLOR_BLACK, COLOR_WHITE);
74210673SKrishnendu.Sadhukhan@Sun.COM 
74310673SKrishnendu.Sadhukhan@Sun.COM 	curses_inited = TRUE;
74410673SKrishnendu.Sadhukhan@Sun.COM 	getmaxyx(stdscr, screen_height, screen_width);
74510673SKrishnendu.Sadhukhan@Sun.COM 
74610673SKrishnendu.Sadhukhan@Sun.COM 	if (screen_width < LT_WINDOW_X || screen_height < LT_WINDOW_Y) {
74710673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(stdscr, 0, 0, "Terminal size is too small.");
74810673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(stdscr, 1, 0,
74910673SKrishnendu.Sadhukhan@Sun.COM 		    "Please resize it to 80x24 or larger.");
75010673SKrishnendu.Sadhukhan@Sun.COM 		(void) mvwprintw(stdscr, 2, 0, "Press q to quit.");
75110673SKrishnendu.Sadhukhan@Sun.COM 		(void) refresh();
75210673SKrishnendu.Sadhukhan@Sun.COM 		return;
75310673SKrishnendu.Sadhukhan@Sun.COM 	}
75410673SKrishnendu.Sadhukhan@Sun.COM 
75510673SKrishnendu.Sadhukhan@Sun.COM 	/* Set up all window panes */
75610673SKrishnendu.Sadhukhan@Sun.COM 	titlebar = subwin(stdscr, 1, screen_width, 0, 0);
75710673SKrishnendu.Sadhukhan@Sun.COM 	captionbar = subwin(stdscr, 1, screen_width, 1, 0);
75810673SKrishnendu.Sadhukhan@Sun.COM 	sysglobal_window = subwin(stdscr, screen_height / 2 - 1,
75910673SKrishnendu.Sadhukhan@Sun.COM 	    screen_width, 2, 0);
76010673SKrishnendu.Sadhukhan@Sun.COM 	process_window = subwin(stdscr, screen_height / 2 - 3,
76110673SKrishnendu.Sadhukhan@Sun.COM 	    screen_width, screen_height / 2 + 1, 0);
76210673SKrishnendu.Sadhukhan@Sun.COM 	taskbar = subwin(stdscr, 1, screen_width, screen_height - 2, 0);
76310673SKrishnendu.Sadhukhan@Sun.COM 	hintbar = subwin(stdscr, 1, screen_width, screen_height - 1, 0);
76410673SKrishnendu.Sadhukhan@Sun.COM 	(void) werase(stdscr);
76510673SKrishnendu.Sadhukhan@Sun.COM 	(void) refresh();
76610673SKrishnendu.Sadhukhan@Sun.COM 
76710673SKrishnendu.Sadhukhan@Sun.COM 	display_initialized = TRUE;
76810673SKrishnendu.Sadhukhan@Sun.COM 
76910673SKrishnendu.Sadhukhan@Sun.COM 	print_title();
77010673SKrishnendu.Sadhukhan@Sun.COM }
77110673SKrishnendu.Sadhukhan@Sun.COM 
77210673SKrishnendu.Sadhukhan@Sun.COM /*
77310673SKrishnendu.Sadhukhan@Sun.COM  * The event loop for display. It displays data on screen and handles hotkey
77410673SKrishnendu.Sadhukhan@Sun.COM  * presses.
77510673SKrishnendu.Sadhukhan@Sun.COM  *
77610673SKrishnendu.Sadhukhan@Sun.COM  * Parameter :
77710673SKrishnendu.Sadhukhan@Sun.COM  *		duration - returns after 'duration'
77810673SKrishnendu.Sadhukhan@Sun.COM  *
77910673SKrishnendu.Sadhukhan@Sun.COM  * The function also returns if user presses 'q', 'Ctrl+C' or 'r'.
78010673SKrishnendu.Sadhukhan@Sun.COM  *
78110673SKrishnendu.Sadhukhan@Sun.COM  * Return value:
78210673SKrishnendu.Sadhukhan@Sun.COM  *		0 - main() exits
78310673SKrishnendu.Sadhukhan@Sun.COM  *		1 - main() calls it again
78410673SKrishnendu.Sadhukhan@Sun.COM  */
78510673SKrishnendu.Sadhukhan@Sun.COM int
lt_display_loop(int duration)78610673SKrishnendu.Sadhukhan@Sun.COM lt_display_loop(int duration)
78710673SKrishnendu.Sadhukhan@Sun.COM {
78810673SKrishnendu.Sadhukhan@Sun.COM 	uint64_t start;
78910673SKrishnendu.Sadhukhan@Sun.COM 	int remaining;
79010673SKrishnendu.Sadhukhan@Sun.COM 	struct timeval timeout;
79110673SKrishnendu.Sadhukhan@Sun.COM 	fd_set read_fd;
79210673SKrishnendu.Sadhukhan@Sun.COM 	int need_refresh = TRUE;
79310673SKrishnendu.Sadhukhan@Sun.COM 	pid_t *plist = NULL;
79410673SKrishnendu.Sadhukhan@Sun.COM 	id_t *tlist = NULL;
79510673SKrishnendu.Sadhukhan@Sun.COM 	int list_len = 0;
79610673SKrishnendu.Sadhukhan@Sun.COM 	int list_index = 0;
79710673SKrishnendu.Sadhukhan@Sun.COM 	int retval = 1;
79810673SKrishnendu.Sadhukhan@Sun.COM 	int next_snap;
79910673SKrishnendu.Sadhukhan@Sun.COM 	int gpipe;
80010673SKrishnendu.Sadhukhan@Sun.COM 
80110673SKrishnendu.Sadhukhan@Sun.COM 	start = lt_millisecond();
80210673SKrishnendu.Sadhukhan@Sun.COM 	gpipe = lt_gpipe_readfd();
80310673SKrishnendu.Sadhukhan@Sun.COM 
80410673SKrishnendu.Sadhukhan@Sun.COM 	if (!show_help) {
80510673SKrishnendu.Sadhukhan@Sun.COM 		print_hint(NULL);
80610673SKrishnendu.Sadhukhan@Sun.COM 		print_sysglobal();
80710673SKrishnendu.Sadhukhan@Sun.COM 	}
80810673SKrishnendu.Sadhukhan@Sun.COM 
80910673SKrishnendu.Sadhukhan@Sun.COM 	get_plist(&plist, &tlist, &list_len, &list_index);
81010673SKrishnendu.Sadhukhan@Sun.COM 
81110673SKrishnendu.Sadhukhan@Sun.COM 	for (;;) {
812*11789SKrishnendu.Sadhukhan@Sun.COM 		if (need_refresh && !show_help) {
813*11789SKrishnendu.Sadhukhan@Sun.COM 			if (list_len != 0) {
814*11789SKrishnendu.Sadhukhan@Sun.COM 				if (!thread_mode) {
815*11789SKrishnendu.Sadhukhan@Sun.COM 					print_taskbar_process(plist, list_len,
816*11789SKrishnendu.Sadhukhan@Sun.COM 					    list_index);
817*11789SKrishnendu.Sadhukhan@Sun.COM 					print_process(plist[list_index]);
818*11789SKrishnendu.Sadhukhan@Sun.COM 				} else {
819*11789SKrishnendu.Sadhukhan@Sun.COM 					print_taskbar_thread(plist, tlist,
820*11789SKrishnendu.Sadhukhan@Sun.COM 					    list_len, list_index);
821*11789SKrishnendu.Sadhukhan@Sun.COM 					print_thread(plist[list_index],
822*11789SKrishnendu.Sadhukhan@Sun.COM 					    tlist[list_index]);
823*11789SKrishnendu.Sadhukhan@Sun.COM 				}
82410673SKrishnendu.Sadhukhan@Sun.COM 			} else {
825*11789SKrishnendu.Sadhukhan@Sun.COM 				print_empty_process_bar();
82610673SKrishnendu.Sadhukhan@Sun.COM 			}
82710673SKrishnendu.Sadhukhan@Sun.COM 		}
82810673SKrishnendu.Sadhukhan@Sun.COM 
82910673SKrishnendu.Sadhukhan@Sun.COM 		need_refresh = TRUE;	/* Usually we need refresh. */
83010673SKrishnendu.Sadhukhan@Sun.COM 		remaining = duration - (int)(lt_millisecond() - start);
83110673SKrishnendu.Sadhukhan@Sun.COM 
83210673SKrishnendu.Sadhukhan@Sun.COM 		if (remaining <= 0) {
83310673SKrishnendu.Sadhukhan@Sun.COM 			break;
83410673SKrishnendu.Sadhukhan@Sun.COM 		}
83510673SKrishnendu.Sadhukhan@Sun.COM 
83610673SKrishnendu.Sadhukhan@Sun.COM 		/* Embedded dtrace snap action here. */
83710673SKrishnendu.Sadhukhan@Sun.COM 		next_snap = lt_dtrace_work(0);
83810673SKrishnendu.Sadhukhan@Sun.COM 
83910673SKrishnendu.Sadhukhan@Sun.COM 		if (next_snap == 0) {
84010673SKrishnendu.Sadhukhan@Sun.COM 			/*
84110673SKrishnendu.Sadhukhan@Sun.COM 			 * Just did a snap, check time for the next one.
84210673SKrishnendu.Sadhukhan@Sun.COM 			 */
84310673SKrishnendu.Sadhukhan@Sun.COM 			next_snap = lt_dtrace_work(0);
84410673SKrishnendu.Sadhukhan@Sun.COM 		}
84510673SKrishnendu.Sadhukhan@Sun.COM 
84610673SKrishnendu.Sadhukhan@Sun.COM 		if (next_snap > 0 && remaining > next_snap) {
84710673SKrishnendu.Sadhukhan@Sun.COM 			remaining = next_snap;
84810673SKrishnendu.Sadhukhan@Sun.COM 		}
84910673SKrishnendu.Sadhukhan@Sun.COM 
85010673SKrishnendu.Sadhukhan@Sun.COM 		timeout.tv_sec = remaining / 1000;
85110673SKrishnendu.Sadhukhan@Sun.COM 		timeout.tv_usec = (remaining % 1000) * 1000;
85210673SKrishnendu.Sadhukhan@Sun.COM 
85310673SKrishnendu.Sadhukhan@Sun.COM 		FD_ZERO(&read_fd);
85410673SKrishnendu.Sadhukhan@Sun.COM 		FD_SET(0, &read_fd);
85510673SKrishnendu.Sadhukhan@Sun.COM 		FD_SET(gpipe, &read_fd);
85610673SKrishnendu.Sadhukhan@Sun.COM 
85710673SKrishnendu.Sadhukhan@Sun.COM 		/* Wait for keyboard input, or signal from gpipe */
85810673SKrishnendu.Sadhukhan@Sun.COM 		if (select(gpipe + 1, &read_fd, NULL, NULL, &timeout) > 0) {
85910673SKrishnendu.Sadhukhan@Sun.COM 			int k = 0;
86010673SKrishnendu.Sadhukhan@Sun.COM 
86110673SKrishnendu.Sadhukhan@Sun.COM 			if (FD_ISSET(gpipe, &read_fd)) {
86210673SKrishnendu.Sadhukhan@Sun.COM 				/* Data from pipe has priority */
86310673SKrishnendu.Sadhukhan@Sun.COM 				char ch;
86410673SKrishnendu.Sadhukhan@Sun.COM 				(void) read(gpipe, &ch, 1);
86510673SKrishnendu.Sadhukhan@Sun.COM 				k = ch; /* Need this for big-endianness */
86610673SKrishnendu.Sadhukhan@Sun.COM 			} else {
86710673SKrishnendu.Sadhukhan@Sun.COM 				k = getch();
86810673SKrishnendu.Sadhukhan@Sun.COM 			}
86910673SKrishnendu.Sadhukhan@Sun.COM 
87010673SKrishnendu.Sadhukhan@Sun.COM 			/*
87110673SKrishnendu.Sadhukhan@Sun.COM 			 * Check if we need to update the hint line whenever we
87210673SKrishnendu.Sadhukhan@Sun.COM 			 * get a chance.
87310673SKrishnendu.Sadhukhan@Sun.COM 			 * NOTE: current implementation depends on
87410673SKrishnendu.Sadhukhan@Sun.COM 			 * g_config.lt_cfg_snap_interval, but it's OK because it
87510673SKrishnendu.Sadhukhan@Sun.COM 			 * doesn't have to be precise.
87610673SKrishnendu.Sadhukhan@Sun.COM 			 */
87710673SKrishnendu.Sadhukhan@Sun.COM 			print_hint(NULL);
87810673SKrishnendu.Sadhukhan@Sun.COM 			/*
87910673SKrishnendu.Sadhukhan@Sun.COM 			 * If help is on display right now, and a key press
88010673SKrishnendu.Sadhukhan@Sun.COM 			 * happens, we need to clear the help and continue.
88110673SKrishnendu.Sadhukhan@Sun.COM 			 */
88210673SKrishnendu.Sadhukhan@Sun.COM 			if (show_help) {
88310673SKrishnendu.Sadhukhan@Sun.COM 				(void) werase(stdscr);
88410673SKrishnendu.Sadhukhan@Sun.COM 				(void) refresh();
88510673SKrishnendu.Sadhukhan@Sun.COM 				print_title();
88610673SKrishnendu.Sadhukhan@Sun.COM 				print_sysglobal();
88710673SKrishnendu.Sadhukhan@Sun.COM 				show_help = FALSE;
88810673SKrishnendu.Sadhukhan@Sun.COM 				/* Drop this key and continue */
88910673SKrishnendu.Sadhukhan@Sun.COM 				continue;
89010673SKrishnendu.Sadhukhan@Sun.COM 			}
89110673SKrishnendu.Sadhukhan@Sun.COM 
89210673SKrishnendu.Sadhukhan@Sun.COM 			switch (k) {
89310673SKrishnendu.Sadhukhan@Sun.COM 			case 'Q':
89410673SKrishnendu.Sadhukhan@Sun.COM 			case 'q':
89510673SKrishnendu.Sadhukhan@Sun.COM 				retval = 0;
89610673SKrishnendu.Sadhukhan@Sun.COM 				goto quit;
89710673SKrishnendu.Sadhukhan@Sun.COM 			case 'R':
89810673SKrishnendu.Sadhukhan@Sun.COM 			case 'r':
89910673SKrishnendu.Sadhukhan@Sun.COM 				lt_display_deinit();
90010673SKrishnendu.Sadhukhan@Sun.COM 				lt_display_init();
90110673SKrishnendu.Sadhukhan@Sun.COM 				goto quit;
90210673SKrishnendu.Sadhukhan@Sun.COM 			case 'H':
90310673SKrishnendu.Sadhukhan@Sun.COM 			case 'h':
90410673SKrishnendu.Sadhukhan@Sun.COM 				show_help = TRUE;
90510673SKrishnendu.Sadhukhan@Sun.COM 				(void) werase(stdscr);
90610673SKrishnendu.Sadhukhan@Sun.COM 				(void) refresh();
90710673SKrishnendu.Sadhukhan@Sun.COM 				print_help();
90810673SKrishnendu.Sadhukhan@Sun.COM 				break;
90910673SKrishnendu.Sadhukhan@Sun.COM 			case ',':
91010673SKrishnendu.Sadhukhan@Sun.COM 			case '<':
91110673SKrishnendu.Sadhukhan@Sun.COM 			case KEY_LEFT:
91210673SKrishnendu.Sadhukhan@Sun.COM 				--list_index;
91310673SKrishnendu.Sadhukhan@Sun.COM 
91410673SKrishnendu.Sadhukhan@Sun.COM 				if (list_index < 0) {
91510673SKrishnendu.Sadhukhan@Sun.COM 					list_index = 0;
91610673SKrishnendu.Sadhukhan@Sun.COM 				}
91710673SKrishnendu.Sadhukhan@Sun.COM 
91810673SKrishnendu.Sadhukhan@Sun.COM 				break;
91910673SKrishnendu.Sadhukhan@Sun.COM 			case '.':
92010673SKrishnendu.Sadhukhan@Sun.COM 			case '>':
92110673SKrishnendu.Sadhukhan@Sun.COM 			case KEY_RIGHT:
92210673SKrishnendu.Sadhukhan@Sun.COM 				++list_index;
92310673SKrishnendu.Sadhukhan@Sun.COM 
92410673SKrishnendu.Sadhukhan@Sun.COM 				if (list_index >= list_len) {
92510673SKrishnendu.Sadhukhan@Sun.COM 					list_index = list_len - 1;
92610673SKrishnendu.Sadhukhan@Sun.COM 				}
92710673SKrishnendu.Sadhukhan@Sun.COM 
92810673SKrishnendu.Sadhukhan@Sun.COM 				break;
92910673SKrishnendu.Sadhukhan@Sun.COM 			case 'a':
93010673SKrishnendu.Sadhukhan@Sun.COM 			case 'A':
93110673SKrishnendu.Sadhukhan@Sun.COM 				sort_type = LT_SORT_AVG;
93210673SKrishnendu.Sadhukhan@Sun.COM 				print_sysglobal();
93310673SKrishnendu.Sadhukhan@Sun.COM 				break;
93410673SKrishnendu.Sadhukhan@Sun.COM 			case 'p':
93510673SKrishnendu.Sadhukhan@Sun.COM 			case 'P':
93610673SKrishnendu.Sadhukhan@Sun.COM 				sort_type = LT_SORT_TOTAL;
93710673SKrishnendu.Sadhukhan@Sun.COM 				print_sysglobal();
93810673SKrishnendu.Sadhukhan@Sun.COM 				break;
93910673SKrishnendu.Sadhukhan@Sun.COM 			case 'm':
94010673SKrishnendu.Sadhukhan@Sun.COM 			case 'M':
94110673SKrishnendu.Sadhukhan@Sun.COM 				sort_type = LT_SORT_MAX;
94210673SKrishnendu.Sadhukhan@Sun.COM 				print_sysglobal();
94310673SKrishnendu.Sadhukhan@Sun.COM 				break;
94410673SKrishnendu.Sadhukhan@Sun.COM 			case 'c':
94510673SKrishnendu.Sadhukhan@Sun.COM 			case 'C':
94610673SKrishnendu.Sadhukhan@Sun.COM 				sort_type = LT_SORT_COUNT;
94710673SKrishnendu.Sadhukhan@Sun.COM 				print_sysglobal();
94810673SKrishnendu.Sadhukhan@Sun.COM 				break;
94910673SKrishnendu.Sadhukhan@Sun.COM 			case 't':
95010673SKrishnendu.Sadhukhan@Sun.COM 			case 'T':
95110673SKrishnendu.Sadhukhan@Sun.COM 				if (plist != NULL) {
95210673SKrishnendu.Sadhukhan@Sun.COM 					selected_pid = plist[list_index];
95310673SKrishnendu.Sadhukhan@Sun.COM 				}
95410673SKrishnendu.Sadhukhan@Sun.COM 
95510673SKrishnendu.Sadhukhan@Sun.COM 				selected_tid = INVALID_TID;
95610673SKrishnendu.Sadhukhan@Sun.COM 				thread_mode = !thread_mode;
95710673SKrishnendu.Sadhukhan@Sun.COM 				get_plist(&plist, &tlist,
95810673SKrishnendu.Sadhukhan@Sun.COM 				    &list_len, &list_index);
95910673SKrishnendu.Sadhukhan@Sun.COM 				break;
96010673SKrishnendu.Sadhukhan@Sun.COM 			case '1':
96110673SKrishnendu.Sadhukhan@Sun.COM 			case '!':
96210673SKrishnendu.Sadhukhan@Sun.COM 				current_list_type = LT_LIST_CAUSE;
96310673SKrishnendu.Sadhukhan@Sun.COM 				print_sysglobal();
96410673SKrishnendu.Sadhukhan@Sun.COM 				break;
96510673SKrishnendu.Sadhukhan@Sun.COM 			case '2':
96610673SKrishnendu.Sadhukhan@Sun.COM 			case '@':
96710673SKrishnendu.Sadhukhan@Sun.COM 				if (g_config.lt_cfg_low_overhead_mode) {
96810673SKrishnendu.Sadhukhan@Sun.COM 					lt_display_error("Switching mode is "
96910673SKrishnendu.Sadhukhan@Sun.COM 					    "not available for '-f low'.");
97010673SKrishnendu.Sadhukhan@Sun.COM 				} else {
97110673SKrishnendu.Sadhukhan@Sun.COM 					current_list_type = LT_LIST_SPECIALS;
97210673SKrishnendu.Sadhukhan@Sun.COM 					print_sysglobal();
97310673SKrishnendu.Sadhukhan@Sun.COM 				}
97410673SKrishnendu.Sadhukhan@Sun.COM 
97510673SKrishnendu.Sadhukhan@Sun.COM 				break;
97610673SKrishnendu.Sadhukhan@Sun.COM 			case '3':
97710673SKrishnendu.Sadhukhan@Sun.COM 			case '#':
97810673SKrishnendu.Sadhukhan@Sun.COM 				if (g_config.lt_cfg_trace_syncobj) {
97910673SKrishnendu.Sadhukhan@Sun.COM 					current_list_type = LT_LIST_SOBJ;
98010673SKrishnendu.Sadhukhan@Sun.COM 					print_sysglobal();
98110673SKrishnendu.Sadhukhan@Sun.COM 				} else if (g_config.lt_cfg_low_overhead_mode) {
98210673SKrishnendu.Sadhukhan@Sun.COM 					lt_display_error("Switching mode is "
98310673SKrishnendu.Sadhukhan@Sun.COM 					    "not available for '-f low'.");
98410673SKrishnendu.Sadhukhan@Sun.COM 				} else {
98510673SKrishnendu.Sadhukhan@Sun.COM 					lt_display_error("Tracing "
98610673SKrishnendu.Sadhukhan@Sun.COM 					    "synchronization objects is "
98710673SKrishnendu.Sadhukhan@Sun.COM 					    "disabled.");
98810673SKrishnendu.Sadhukhan@Sun.COM 				}
98910673SKrishnendu.Sadhukhan@Sun.COM 
99010673SKrishnendu.Sadhukhan@Sun.COM 				break;
99110673SKrishnendu.Sadhukhan@Sun.COM 			default:
99210673SKrishnendu.Sadhukhan@Sun.COM 				/* Wake up for nothing; no refresh is needed */
99310673SKrishnendu.Sadhukhan@Sun.COM 				need_refresh = FALSE;
99410673SKrishnendu.Sadhukhan@Sun.COM 				break;
99510673SKrishnendu.Sadhukhan@Sun.COM 			}
99610673SKrishnendu.Sadhukhan@Sun.COM 		} else {
99710673SKrishnendu.Sadhukhan@Sun.COM 			need_refresh = FALSE;
99810673SKrishnendu.Sadhukhan@Sun.COM 		}
99910673SKrishnendu.Sadhukhan@Sun.COM 	}
100010673SKrishnendu.Sadhukhan@Sun.COM 
100110673SKrishnendu.Sadhukhan@Sun.COM quit:
100210673SKrishnendu.Sadhukhan@Sun.COM 	if (plist != NULL) {
100310673SKrishnendu.Sadhukhan@Sun.COM 		selected_pid = plist[list_index];
100410673SKrishnendu.Sadhukhan@Sun.COM 	}
100510673SKrishnendu.Sadhukhan@Sun.COM 
100610673SKrishnendu.Sadhukhan@Sun.COM 	if (tlist != NULL) {
100710673SKrishnendu.Sadhukhan@Sun.COM 		selected_tid = tlist[list_index];
100810673SKrishnendu.Sadhukhan@Sun.COM 	}
100910673SKrishnendu.Sadhukhan@Sun.COM 
101010673SKrishnendu.Sadhukhan@Sun.COM 	lt_stat_proc_list_free(plist, tlist);
101110673SKrishnendu.Sadhukhan@Sun.COM 
101210673SKrishnendu.Sadhukhan@Sun.COM 	return (retval);
101310673SKrishnendu.Sadhukhan@Sun.COM }
101410673SKrishnendu.Sadhukhan@Sun.COM 
101510673SKrishnendu.Sadhukhan@Sun.COM /*
101610673SKrishnendu.Sadhukhan@Sun.COM  * Clean up display.
101710673SKrishnendu.Sadhukhan@Sun.COM  */
101810673SKrishnendu.Sadhukhan@Sun.COM void
lt_display_deinit(void)101910673SKrishnendu.Sadhukhan@Sun.COM lt_display_deinit(void)
102010673SKrishnendu.Sadhukhan@Sun.COM {
102110673SKrishnendu.Sadhukhan@Sun.COM 	if (curses_inited) {
102210673SKrishnendu.Sadhukhan@Sun.COM 		(void) clear();
102310673SKrishnendu.Sadhukhan@Sun.COM 		(void) refresh();
102410673SKrishnendu.Sadhukhan@Sun.COM 		(void) endwin();
102510673SKrishnendu.Sadhukhan@Sun.COM 	}
102610673SKrishnendu.Sadhukhan@Sun.COM 
102710673SKrishnendu.Sadhukhan@Sun.COM 	titlebar = NULL;
102810673SKrishnendu.Sadhukhan@Sun.COM 	captionbar = NULL;
102910673SKrishnendu.Sadhukhan@Sun.COM 	sysglobal_window = NULL;
103010673SKrishnendu.Sadhukhan@Sun.COM 	taskbar = NULL;
103110673SKrishnendu.Sadhukhan@Sun.COM 	process_window = NULL;
103210673SKrishnendu.Sadhukhan@Sun.COM 	hintbar = NULL;
103310673SKrishnendu.Sadhukhan@Sun.COM 	screen_width = 1;
103410673SKrishnendu.Sadhukhan@Sun.COM 	screen_height = 1;
103510673SKrishnendu.Sadhukhan@Sun.COM 
103610673SKrishnendu.Sadhukhan@Sun.COM 	display_initialized = FALSE;
103710673SKrishnendu.Sadhukhan@Sun.COM 	curses_inited = FALSE;
103810673SKrishnendu.Sadhukhan@Sun.COM }
103910673SKrishnendu.Sadhukhan@Sun.COM 
104010673SKrishnendu.Sadhukhan@Sun.COM /*
104110673SKrishnendu.Sadhukhan@Sun.COM  * Print message when display error happens.
104210673SKrishnendu.Sadhukhan@Sun.COM  */
104310673SKrishnendu.Sadhukhan@Sun.COM /* ARGSUSED */
104410673SKrishnendu.Sadhukhan@Sun.COM void
lt_display_error(const char * fmt,...)104510673SKrishnendu.Sadhukhan@Sun.COM lt_display_error(const char *fmt, ...)
104610673SKrishnendu.Sadhukhan@Sun.COM {
104710673SKrishnendu.Sadhukhan@Sun.COM 	va_list vl;
104810673SKrishnendu.Sadhukhan@Sun.COM 	char tmp[81];
104910673SKrishnendu.Sadhukhan@Sun.COM 	int l;
105010673SKrishnendu.Sadhukhan@Sun.COM 
105110673SKrishnendu.Sadhukhan@Sun.COM 	va_start(vl, fmt);
105210673SKrishnendu.Sadhukhan@Sun.COM 	(void) vsnprintf(tmp, sizeof (tmp), fmt, vl);
105310673SKrishnendu.Sadhukhan@Sun.COM 	va_end(vl);
105410673SKrishnendu.Sadhukhan@Sun.COM 
105510673SKrishnendu.Sadhukhan@Sun.COM 	l = strlen(tmp);
105610673SKrishnendu.Sadhukhan@Sun.COM 
105710673SKrishnendu.Sadhukhan@Sun.COM 	while (l > 0 && (tmp[l - 1] == '\n' || tmp[l - 1] == '\r')) {
105810673SKrishnendu.Sadhukhan@Sun.COM 		tmp[l - 1] = '\0';
105910673SKrishnendu.Sadhukhan@Sun.COM 		--l;
106010673SKrishnendu.Sadhukhan@Sun.COM 	}
106110673SKrishnendu.Sadhukhan@Sun.COM 
106210673SKrishnendu.Sadhukhan@Sun.COM 	if (!display_initialized) {
106310673SKrishnendu.Sadhukhan@Sun.COM 		(void) fprintf(stderr, "%s\n", tmp);
106410673SKrishnendu.Sadhukhan@Sun.COM 	} else if (!show_help) {
106510673SKrishnendu.Sadhukhan@Sun.COM 		print_hint(tmp);
106610673SKrishnendu.Sadhukhan@Sun.COM 	}
106710673SKrishnendu.Sadhukhan@Sun.COM 
106810673SKrishnendu.Sadhukhan@Sun.COM }
1069