summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorKrishnendu Sadhukhan - Sun Microsystems <Krishnendu.Sadhukhan@Sun.COM>2010-02-26 21:09:12 -0800
committerKrishnendu Sadhukhan - Sun Microsystems <Krishnendu.Sadhukhan@Sun.COM>2010-02-26 21:09:12 -0800
commita9c12afde877c596eed286ac3f1d518246e5cd1e (patch)
treee29a7bbc2efecc597117e476429e67a50c668aa5 /usr/src
parent87974390c959ee024ced157c12358eda9533afbe (diff)
downloadillumos-joyent-a9c12afde877c596eed286ac3f1d518246e5cd1e.tar.gz
6888464 Add a command-line option to track only a given process in LatencyTOP
Contributed by Lejun Zhu <lejun.zhu@intel.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/latencytop/common/display.c50
-rw-r--r--usr/src/cmd/latencytop/common/dwrapper.c25
-rw-r--r--usr/src/cmd/latencytop/common/latencytop.c60
-rw-r--r--usr/src/cmd/latencytop/common/latencytop.d19
-rw-r--r--usr/src/cmd/latencytop/common/latencytop.h2
5 files changed, 138 insertions, 18 deletions
diff --git a/usr/src/cmd/latencytop/common/display.c b/usr/src/cmd/latencytop/common/display.c
index edc2c20ae1..723f9873a7 100644
--- a/usr/src/cmd/latencytop/common/display.c
+++ b/usr/src/cmd/latencytop/common/display.c
@@ -272,6 +272,31 @@ print_current_mode()
}
/*
+ * Print process window bar when the list is empty.
+ */
+static void
+print_empty_process_bar()
+{
+ char header[256];
+
+ if (!display_initialized) {
+ return;
+ }
+
+ (void) werase(process_window);
+ (void) wattron(process_window, A_REVERSE);
+ (void) snprintf(header, sizeof (header),
+ "No process/thread data is available");
+ fill_space_right(header, screen_width, sizeof (header));
+ (void) mvwprintw(process_window, 0, 0, "%s", header);
+
+ print_current_mode();
+ (void) wattroff(process_window, A_REVERSE);
+
+ (void) wrefresh(process_window);
+}
+
+/*
* Print per-process statistics in process pane.
* This is called when mode of operation is process.
*/
@@ -521,7 +546,7 @@ print_hint(const char *hint)
"Press 'r' to refresh immediately.",
"Press 't' to toggle Process/Thread display mode.",
"Press 'h' for help.",
- "Use 'c', 'a', 'm', 'p' to change sort criteria."
+ "Use 'c', 'a', 'm', 'p' to change sort criteria.",
"Use '1', '2', '3' to switch between windows."
};
const uint64_t update_interval = 5000; /* 5 seconds */
@@ -565,7 +590,6 @@ get_plist(pid_t **plist, id_t **tlist, int *list_len, int *list_index)
if (!thread_mode) {
/* Per-process mode */
*list_len = lt_stat_proc_list_create(plist, NULL);
-
/* Search for previously selected PID */
for (*list_index = 0; *list_index < *list_len &&
(*plist)[*list_index] != selected_pid;
@@ -785,16 +809,20 @@ lt_display_loop(int duration)
get_plist(&plist, &tlist, &list_len, &list_index);
for (;;) {
- if (list_len != 0 && need_refresh && !show_help) {
- if (!thread_mode) {
- print_taskbar_process(plist, list_len,
- list_index);
- print_process(plist[list_index]);
+ if (need_refresh && !show_help) {
+ if (list_len != 0) {
+ if (!thread_mode) {
+ print_taskbar_process(plist, list_len,
+ list_index);
+ print_process(plist[list_index]);
+ } else {
+ print_taskbar_thread(plist, tlist,
+ list_len, list_index);
+ print_thread(plist[list_index],
+ tlist[list_index]);
+ }
} else {
- print_taskbar_thread(plist, tlist,
- list_len, list_index);
- print_thread(plist[list_index],
- tlist[list_index]);
+ print_empty_process_bar();
}
}
diff --git a/usr/src/cmd/latencytop/common/dwrapper.c b/usr/src/cmd/latencytop/common/dwrapper.c
index f634065e38..851c581af7 100644
--- a/usr/src/cmd/latencytop/common/dwrapper.c
+++ b/usr/src/cmd/latencytop/common/dwrapper.c
@@ -402,6 +402,7 @@ lt_dtrace_init(void)
dtrace_proginfo_t info;
int err;
FILE *fp_script = NULL;
+ char tmp[64];
pid_self = getpid();
@@ -439,7 +440,27 @@ lt_dtrace_init(void)
if ((err = dtrace_setopt(g_dtp, "define",
"ENABLE_SCHED")) != 0) {
lt_display_error(
- "Failed to set option ENABLE_SYNCOBJ.\n");
+ "Failed to set option ENABLE_SCHED.\n");
+ return (err);
+ }
+ }
+
+ if (g_config.lt_cfg_trace_pid != 0) {
+ (void) snprintf(tmp, sizeof (tmp), "TRACE_PID=%u",
+ g_config.lt_cfg_trace_pid);
+ if ((err = dtrace_setopt(g_dtp, "define", tmp)) != 0) {
+ lt_display_error(
+ "Failed to set option TRACE_PID.\n");
+ return (err);
+ }
+ }
+
+ if (g_config.lt_cfg_trace_pgid != 0) {
+ (void) snprintf(tmp, sizeof (tmp), "TRACE_PGID=%u",
+ g_config.lt_cfg_trace_pgid);
+ if ((err = dtrace_setopt(g_dtp, "define", tmp)) != 0) {
+ lt_display_error(
+ "Failed to set option TRACE_PGID.\n");
return (err);
}
}
@@ -448,7 +469,7 @@ lt_dtrace_init(void)
if ((err = dtrace_setopt(g_dtp, "define",
"ENABLE_LOW_OVERHEAD")) != 0) {
lt_display_error(
- "Failed to set option ENABLE_SYNCOBJ.\n");
+ "Failed to set option ENABLE_LOW_OVERHEAD.\n");
return (err);
}
}
diff --git a/usr/src/cmd/latencytop/common/latencytop.c b/usr/src/cmd/latencytop/common/latencytop.c
index 154dffb699..65778798bd 100644
--- a/usr/src/cmd/latencytop/common/latencytop.c
+++ b/usr/src/cmd/latencytop/common/latencytop.c
@@ -53,7 +53,8 @@ typedef enum {
LT_CMDOPT_F_SCHED,
LT_CMDOPT_F_SOBJ,
LT_CMDOPT_F_LOW,
- LT_CMDOPT__LAST /* Must be last one */
+ LT_CMDOPT_SELECT,
+ LT_CMDOPT__LAST /* Must be the last one */
} lt_cmd_option_id_t;
/*
@@ -77,6 +78,7 @@ check_opt_dup(lt_cmd_option_id_t id, uint64_t value) {
"-f [no]sched is set more than once with different values.",
"-f [no]sobj is set more than once with different values.",
"-f [no]low is set more than once with different values.",
+ "-s is set more than once with different values."
};
g_assert(sizeof (errmsg)/sizeof (errmsg[0]) == (int)LT_CMDOPT__LAST);
@@ -142,7 +144,10 @@ print_usage(const char *execname, int long_help)
" [no]low:\n"
" Lower overhead by sampling small latencies.\n"
" -l, --log-period TIME\n"
- " Write and restart log every TIME seconds, TIME >= 60\n");
+ " Write and restart log every TIME seconds, TIME >= 60\n"
+ " -s --select [ pid=<pid> | pgid=<pgid> ]\n"
+ " Monitor only the given process or processes in the "
+ "given process group.\n");
}
/*
@@ -185,7 +190,7 @@ to_int(const char *str, int *result)
int
main(int argc, char *argv[])
{
- const char *opt_string = "t:o:k:hf:l:c:";
+ const char *opt_string = "t:o:k:hf:l:c:s:";
struct option const longopts[] = {
{"interval", required_argument, NULL, 't'},
{"output-log-file", required_argument, NULL, 'o'},
@@ -194,6 +199,7 @@ main(int argc, char *argv[])
{"feature", required_argument, NULL, 'f'},
{"log-period", required_argument, NULL, 'l'},
{"config", required_argument, NULL, 'c'},
+ {"select", required_argument, NULL, 's'},
{NULL, 0, NULL, 0}
};
@@ -213,6 +219,9 @@ main(int argc, char *argv[])
uint64_t current_time;
uint64_t delta_time;
char logfile[PATH_MAX] = "";
+ int select_id;
+ int select_value;
+ char *select_str;
boolean_t no_dtrace_cleanup = B_TRUE;
lt_gpipe_init();
@@ -224,6 +233,8 @@ main(int argc, char *argv[])
g_config.lt_cfg_trace_sched = 0;
g_config.lt_cfg_trace_syncobj = 1;
g_config.lt_cfg_low_overhead_mode = 0;
+ g_config.lt_cfg_trace_pid = 0;
+ g_config.lt_cfg_trace_pgid = 0;
/* dtrace snapshot every 1 second */
g_config.lt_cfg_snap_interval = 1000;
#ifdef EMBED_CONFIGS
@@ -354,6 +365,47 @@ main(int argc, char *argv[])
}
break;
+ case 's':
+ if (strncmp(optarg, "pid=", 4) == 0) {
+ select_id = 0;
+ select_str = &optarg[4];
+ } else if (strncmp(optarg, "pgid=", 5) == 0) {
+ select_id = 1;
+ select_str = &optarg[5];
+ } else {
+ lt_display_error(
+ "Invalid select option: %s\n", optarg);
+ unknown_option = TRUE;
+ break;
+ }
+
+ if (to_int(select_str, &select_value) != 0) {
+ lt_display_error(
+ "Invalid select option: %s\n", optarg);
+ unknown_option = TRUE;
+ break;
+ }
+
+ if (select_value <= 0) {
+ lt_display_error(
+ "Process/process group ID must be "
+ "greater than 0: %s\n", optarg);
+ unknown_option = TRUE;
+ break;
+ }
+
+ if (check_opt_dup(LT_CMDOPT_SELECT,
+ (((uint64_t)select_id) << 32) | select_value)) {
+ unknown_option = TRUE;
+ break;
+ }
+
+ if (select_id == 0) {
+ g_config.lt_cfg_trace_pid = select_value;
+ } else {
+ g_config.lt_cfg_trace_pgid = select_value;
+ }
+ break;
default:
unknown_option = TRUE;
break;
@@ -429,7 +481,7 @@ main(int argc, char *argv[])
}
/*
- * Interval when we call dtrace_status() and collect
+ * Interval when we call dtrace_status() and collect
* aggregated data.
*/
if (tsleep > g_config.lt_cfg_snap_interval) {
diff --git a/usr/src/cmd/latencytop/common/latencytop.d b/usr/src/cmd/latencytop/common/latencytop.d
index 95381b12de..c6686fa3b5 100644
--- a/usr/src/cmd/latencytop/common/latencytop.d
+++ b/usr/src/cmd/latencytop/common/latencytop.d
@@ -39,12 +39,29 @@
#pragma D option zdefs
#if defined(ENABLE_SCHED)
+#if defined(TRACE_PID)
+#define TRACE_FILTER / pid == 0 || pid == TRACE_PID /
+#define TRACE_FILTER_COND(a) / (pid == 0 || pid == TRACE_PID) && (a) /
+#elif defined(TRACE_PGID)
+#define TRACE_FILTER / pid == 0 || curpsinfo->pr_pgid == TRACE_PGID /
+#define TRACE_FILTER_COND(a)
+ / (pid == 0 || curpsinfo->pr_pgid == TRACE_PGID) && (a) /
+#else
#define TRACE_FILTER
#define TRACE_FILTER_COND(a) / (a) /
+#endif
+#else /* ENABLE_SCHED */
+#if defined(TRACE_PID)
+#define TRACE_FILTER / pid == TRACE_PID /
+#define TRACE_FILTER_COND(a) / (pid == TRACE_PID) && (a) /
+#elif defined(TRACE_PGID)
+#define TRACE_FILTER / curpsinfo->pr_pgid == TRACE_PGID /
+#define TRACE_FILTER_COND(a) / (curpsinfo->pr_pgid == TRACE_PGID) && (a) /
#else
#define TRACE_FILTER / pid != 0 /
-#define TRACE_FILTER_COND(a) / pid != 0 && (a) /
+#define TRACE_FILTER_COND(a) / (pid != 0) && (a) /
#endif
+#endif /* ENABLE_SCHED */
/* Threshold to filter WAKEABLE latencies. */
#define FILTER_THRESHOLD 5000000
diff --git a/usr/src/cmd/latencytop/common/latencytop.h b/usr/src/cmd/latencytop/common/latencytop.h
index ee77dee3b1..d1cd3483c3 100644
--- a/usr/src/cmd/latencytop/common/latencytop.h
+++ b/usr/src/cmd/latencytop/common/latencytop.h
@@ -148,6 +148,8 @@ typedef struct {
int lt_cfg_low_overhead_mode;
int lt_cfg_snap_interval;
char *lt_cfg_config_name;
+ unsigned int lt_cfg_trace_pid;
+ unsigned int lt_cfg_trace_pgid;
} lt_config_t;
extern lt_config_t g_config; /* The global settings */