diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-05-23 05:09:19 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-05-23 05:09:19 -0400 |
commit | c392c4c6dccf7c64c113b473c7eceedf25eddd51 (patch) | |
tree | 0fe27295bd81e5da4d6d8520a17c1711774c1246 | |
parent | 841bca1393d315d79077f272c2918423e36dc364 (diff) | |
parent | 46e3e055ce69a00d735e458445ab1d24718ff751 (diff) |
Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
-rw-r--r-- | tools/perf/builtin-annotate.c | 61 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 13 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 10 | ||||
-rw-r--r-- | tools/perf/util/newt.c | 61 | ||||
-rw-r--r-- | tools/perf/util/util.h | 15 |
5 files changed, 116 insertions, 44 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 77bcc9b130f5..08278eda31a5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -277,7 +277,7 @@ static void hist_entry__print_hits(struct hist_entry *self) | |||
277 | printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); | 277 | printf("%*s: %Lu\n", BITS_PER_LONG / 2, "h->sum", h->sum); |
278 | } | 278 | } |
279 | 279 | ||
280 | static void annotate_sym(struct hist_entry *he) | 280 | static int hist_entry__tty_annotate(struct hist_entry *he) |
281 | { | 281 | { |
282 | struct map *map = he->ms.map; | 282 | struct map *map = he->ms.map; |
283 | struct dso *dso = map->dso; | 283 | struct dso *dso = map->dso; |
@@ -288,7 +288,7 @@ static void annotate_sym(struct hist_entry *he) | |||
288 | struct objdump_line *pos, *n; | 288 | struct objdump_line *pos, *n; |
289 | 289 | ||
290 | if (hist_entry__annotate(he, &head) < 0) | 290 | if (hist_entry__annotate(he, &head) < 0) |
291 | return; | 291 | return -1; |
292 | 292 | ||
293 | if (full_paths) | 293 | if (full_paths) |
294 | d_filename = filename; | 294 | d_filename = filename; |
@@ -317,30 +317,59 @@ static void annotate_sym(struct hist_entry *he) | |||
317 | 317 | ||
318 | if (print_line) | 318 | if (print_line) |
319 | free_source_line(he, len); | 319 | free_source_line(he, len); |
320 | |||
321 | return 0; | ||
320 | } | 322 | } |
321 | 323 | ||
322 | static void hists__find_annotations(struct hists *self) | 324 | static void hists__find_annotations(struct hists *self) |
323 | { | 325 | { |
324 | struct rb_node *nd; | 326 | struct rb_node *first = rb_first(&self->entries), *nd = first; |
327 | int key = KEY_RIGHT; | ||
325 | 328 | ||
326 | for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) { | 329 | while (nd) { |
327 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); | 330 | struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); |
328 | struct sym_priv *priv; | 331 | struct sym_priv *priv; |
329 | 332 | ||
330 | if (he->ms.sym == NULL) | 333 | if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) |
331 | continue; | 334 | goto find_next; |
332 | 335 | ||
333 | priv = symbol__priv(he->ms.sym); | 336 | priv = symbol__priv(he->ms.sym); |
334 | if (priv->hist == NULL) | 337 | if (priv->hist == NULL) { |
338 | find_next: | ||
339 | if (key == KEY_LEFT) | ||
340 | nd = rb_prev(nd); | ||
341 | else | ||
342 | nd = rb_next(nd); | ||
335 | continue; | 343 | continue; |
344 | } | ||
336 | 345 | ||
337 | annotate_sym(he); | 346 | if (use_browser) { |
338 | /* | 347 | key = hist_entry__tui_annotate(he); |
339 | * Since we have a hist_entry per IP for the same symbol, free | 348 | if (is_exit_key(key)) |
340 | * he->ms.sym->hist to signal we already processed this symbol. | 349 | break; |
341 | */ | 350 | switch (key) { |
342 | free(priv->hist); | 351 | case KEY_RIGHT: |
343 | priv->hist = NULL; | 352 | case '\t': |
353 | nd = rb_next(nd); | ||
354 | break; | ||
355 | case KEY_LEFT: | ||
356 | if (nd == first) | ||
357 | continue; | ||
358 | nd = rb_prev(nd); | ||
359 | default: | ||
360 | break; | ||
361 | } | ||
362 | } else { | ||
363 | hist_entry__tty_annotate(he); | ||
364 | nd = rb_next(nd); | ||
365 | /* | ||
366 | * Since we have a hist_entry per IP for the same | ||
367 | * symbol, free he->ms.sym->hist to signal we already | ||
368 | * processed this symbol. | ||
369 | */ | ||
370 | free(priv->hist); | ||
371 | priv->hist = NULL; | ||
372 | } | ||
344 | } | 373 | } |
345 | } | 374 | } |
346 | 375 | ||
@@ -416,6 +445,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
416 | { | 445 | { |
417 | argc = parse_options(argc, argv, options, annotate_usage, 0); | 446 | argc = parse_options(argc, argv, options, annotate_usage, 0); |
418 | 447 | ||
448 | setup_browser(); | ||
449 | |||
419 | symbol_conf.priv_size = sizeof(struct sym_priv); | 450 | symbol_conf.priv_size = sizeof(struct sym_priv); |
420 | symbol_conf.try_vmlinux_path = true; | 451 | symbol_conf.try_vmlinux_path = true; |
421 | 452 | ||
@@ -435,8 +466,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) | |||
435 | sym_hist_filter = argv[0]; | 466 | sym_hist_filter = argv[0]; |
436 | } | 467 | } |
437 | 468 | ||
438 | setup_pager(); | ||
439 | |||
440 | if (field_sep && *field_sep == '.') { | 469 | if (field_sep && *field_sep == '.') { |
441 | pr_err("'.' is the only non valid --field-separator argument\n"); | 470 | pr_err("'.' is the only non valid --field-separator argument\n"); |
442 | return -1; | 471 | return -1; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 009ad76b0879..682a6d88862c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -992,14 +992,14 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) | |||
992 | char *filename = dso__build_id_filename(dso, NULL, 0); | 992 | char *filename = dso__build_id_filename(dso, NULL, 0); |
993 | char command[PATH_MAX * 2]; | 993 | char command[PATH_MAX * 2]; |
994 | FILE *file; | 994 | FILE *file; |
995 | int err = -1; | 995 | int err = 0; |
996 | u64 len; | 996 | u64 len; |
997 | 997 | ||
998 | if (filename == NULL) { | 998 | if (filename == NULL) { |
999 | if (dso->has_build_id) { | 999 | if (dso->has_build_id) { |
1000 | pr_err("Can't annotate %s: not enough memory\n", | 1000 | pr_err("Can't annotate %s: not enough memory\n", |
1001 | sym->name); | 1001 | sym->name); |
1002 | return -1; | 1002 | return -ENOMEM; |
1003 | } | 1003 | } |
1004 | /* | 1004 | /* |
1005 | * If we don't have build-ids, well, lets hope that this | 1005 | * If we don't have build-ids, well, lets hope that this |
@@ -1009,14 +1009,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) | |||
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | if (dso->origin == DSO__ORIG_KERNEL) { | 1011 | if (dso->origin == DSO__ORIG_KERNEL) { |
1012 | if (dso->annotate_warned) { | 1012 | if (dso->annotate_warned) |
1013 | err = 0; | ||
1014 | goto out_free_filename; | 1013 | goto out_free_filename; |
1015 | } | 1014 | err = -ENOENT; |
1016 | dso->annotate_warned = 1; | 1015 | dso->annotate_warned = 1; |
1017 | pr_err("Can't annotate %s: No vmlinux file was found in the " | 1016 | pr_err("Can't annotate %s: No vmlinux file was found in the " |
1018 | "path:\n", sym->name); | 1017 | "path\n", sym->name); |
1019 | vmlinux_path__fprintf(stderr); | ||
1020 | goto out_free_filename; | 1018 | goto out_free_filename; |
1021 | } | 1019 | } |
1022 | 1020 | ||
@@ -1046,7 +1044,6 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head) | |||
1046 | break; | 1044 | break; |
1047 | 1045 | ||
1048 | pclose(file); | 1046 | pclose(file); |
1049 | err = 0; | ||
1050 | out_free_filename: | 1047 | out_free_filename: |
1051 | if (dso->has_build_id) | 1048 | if (dso->has_build_id) |
1052 | free(filename); | 1049 | free(filename); |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 6f17dcd8412c..2d5203fedb20 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -102,8 +102,18 @@ static inline int hists__browse(struct hists *self __used, | |||
102 | { | 102 | { |
103 | return 0; | 103 | return 0; |
104 | } | 104 | } |
105 | static inline int hist_entry__tui_annotate(struct hist_entry *self __used) | ||
106 | { | ||
107 | return 0; | ||
108 | } | ||
109 | #define KEY_LEFT -1 | ||
110 | #define KEY_RIGHT -2 | ||
105 | #else | 111 | #else |
112 | #include <newt.h> | ||
106 | int hists__browse(struct hists *self, const char *helpline, | 113 | int hists__browse(struct hists *self, const char *helpline, |
107 | const char *input_name); | 114 | const char *input_name); |
115 | int hist_entry__tui_annotate(struct hist_entry *self); | ||
116 | #define KEY_LEFT NEWT_KEY_LEFT | ||
117 | #define KEY_RIGHT NEWT_KEY_RIGHT | ||
108 | #endif | 118 | #endif |
109 | #endif /* __PERF_HIST_H */ | 119 | #endif /* __PERF_HIST_H */ |
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index 0b45658f7497..ffd04720b754 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
@@ -235,6 +235,15 @@ static bool dialog_yesno(const char *msg) | |||
235 | return newtWinChoice(NULL, yes, no, (char *)msg) == 1; | 235 | return newtWinChoice(NULL, yes, no, (char *)msg) == 1; |
236 | } | 236 | } |
237 | 237 | ||
238 | static void ui__error_window(const char *fmt, ...) | ||
239 | { | ||
240 | va_list ap; | ||
241 | |||
242 | va_start(ap, fmt); | ||
243 | newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap); | ||
244 | va_end(ap); | ||
245 | } | ||
246 | |||
238 | #define HE_COLORSET_TOP 50 | 247 | #define HE_COLORSET_TOP 50 |
239 | #define HE_COLORSET_MEDIUM 51 | 248 | #define HE_COLORSET_MEDIUM 51 |
240 | #define HE_COLORSET_NORMAL 52 | 249 | #define HE_COLORSET_NORMAL 52 |
@@ -386,6 +395,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
386 | newtFormAddHotKey(self->form, ' '); | 395 | newtFormAddHotKey(self->form, ' '); |
387 | newtFormAddHotKey(self->form, NEWT_KEY_HOME); | 396 | newtFormAddHotKey(self->form, NEWT_KEY_HOME); |
388 | newtFormAddHotKey(self->form, NEWT_KEY_END); | 397 | newtFormAddHotKey(self->form, NEWT_KEY_END); |
398 | newtFormAddHotKey(self->form, NEWT_KEY_TAB); | ||
399 | newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); | ||
389 | 400 | ||
390 | if (ui_browser__refresh_entries(self) < 0) | 401 | if (ui_browser__refresh_entries(self) < 0) |
391 | return -1; | 402 | return -1; |
@@ -398,6 +409,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
398 | 409 | ||
399 | if (es->reason != NEWT_EXIT_HOTKEY) | 410 | if (es->reason != NEWT_EXIT_HOTKEY) |
400 | break; | 411 | break; |
412 | if (is_exit_key(es->u.key)) | ||
413 | return es->u.key; | ||
401 | switch (es->u.key) { | 414 | switch (es->u.key) { |
402 | case NEWT_KEY_DOWN: | 415 | case NEWT_KEY_DOWN: |
403 | if (self->index == self->nr_entries - 1) | 416 | if (self->index == self->nr_entries - 1) |
@@ -471,12 +484,10 @@ static int ui_browser__run(struct ui_browser *self, const char *title, | |||
471 | } | 484 | } |
472 | } | 485 | } |
473 | break; | 486 | break; |
474 | case NEWT_KEY_ESCAPE: | 487 | case NEWT_KEY_RIGHT: |
475 | case NEWT_KEY_LEFT: | 488 | case NEWT_KEY_LEFT: |
476 | case CTRL('c'): | 489 | case NEWT_KEY_TAB: |
477 | case 'Q': | 490 | return es->u.key; |
478 | case 'q': | ||
479 | return 0; | ||
480 | default: | 491 | default: |
481 | continue; | 492 | continue; |
482 | } | 493 | } |
@@ -668,18 +679,24 @@ static size_t hist_entry__append_browser(struct hist_entry *self, | |||
668 | return ret; | 679 | return ret; |
669 | } | 680 | } |
670 | 681 | ||
671 | static void hist_entry__annotate_browser(struct hist_entry *self) | 682 | int hist_entry__tui_annotate(struct hist_entry *self) |
672 | { | 683 | { |
673 | struct ui_browser browser; | 684 | struct ui_browser browser; |
674 | struct newtExitStruct es; | 685 | struct newtExitStruct es; |
675 | struct objdump_line *pos, *n; | 686 | struct objdump_line *pos, *n; |
676 | LIST_HEAD(head); | 687 | LIST_HEAD(head); |
688 | int ret; | ||
677 | 689 | ||
678 | if (self->ms.sym == NULL) | 690 | if (self->ms.sym == NULL) |
679 | return; | 691 | return -1; |
680 | 692 | ||
681 | if (hist_entry__annotate(self, &head) < 0) | 693 | if (self->ms.map->dso->annotate_warned) |
682 | return; | 694 | return -1; |
695 | |||
696 | if (hist_entry__annotate(self, &head) < 0) { | ||
697 | ui__error_window(browser__last_msg); | ||
698 | return -1; | ||
699 | } | ||
683 | 700 | ||
684 | ui_helpline__push("Press <- or ESC to exit"); | 701 | ui_helpline__push("Press <- or ESC to exit"); |
685 | 702 | ||
@@ -694,7 +711,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) | |||
694 | } | 711 | } |
695 | 712 | ||
696 | browser.width += 18; /* Percentage */ | 713 | browser.width += 18; /* Percentage */ |
697 | ui_browser__run(&browser, self->ms.sym->name, &es); | 714 | ret = ui_browser__run(&browser, self->ms.sym->name, &es); |
698 | newtFormDestroy(browser.form); | 715 | newtFormDestroy(browser.form); |
699 | newtPopWindow(); | 716 | newtPopWindow(); |
700 | list_for_each_entry_safe(pos, n, &head, node) { | 717 | list_for_each_entry_safe(pos, n, &head, node) { |
@@ -702,6 +719,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self) | |||
702 | objdump_line__free(pos); | 719 | objdump_line__free(pos); |
703 | } | 720 | } |
704 | ui_helpline__pop(); | 721 | ui_helpline__pop(); |
722 | return ret; | ||
705 | } | 723 | } |
706 | 724 | ||
707 | static const void *newt__symbol_tree_get_current(newtComponent self) | 725 | static const void *newt__symbol_tree_get_current(newtComponent self) |
@@ -914,6 +932,9 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na | |||
914 | 932 | ||
915 | switch (toupper(es.u.key)) { | 933 | switch (toupper(es.u.key)) { |
916 | case 'A': | 934 | case 'A': |
935 | if (browser->selection->map == NULL && | ||
936 | browser->selection->map->dso->annotate_warned) | ||
937 | continue; | ||
917 | goto do_annotate; | 938 | goto do_annotate; |
918 | case 'D': | 939 | case 'D': |
919 | goto zoom_dso; | 940 | goto zoom_dso; |
@@ -932,14 +953,14 @@ do_help: | |||
932 | continue; | 953 | continue; |
933 | default:; | 954 | default:; |
934 | } | 955 | } |
935 | if (toupper(es.u.key) == 'Q' || | 956 | if (is_exit_key(es.u.key)) { |
936 | es.u.key == CTRL('c')) | 957 | if (es.u.key == NEWT_KEY_ESCAPE) { |
937 | break; | 958 | if (dialog_yesno("Do you really want to exit?")) |
938 | if (es.u.key == NEWT_KEY_ESCAPE) { | 959 | break; |
939 | if (dialog_yesno("Do you really want to exit?")) | 960 | else |
961 | continue; | ||
962 | } else | ||
940 | break; | 963 | break; |
941 | else | ||
942 | continue; | ||
943 | } | 964 | } |
944 | 965 | ||
945 | if (es.u.key == NEWT_KEY_LEFT) { | 966 | if (es.u.key == NEWT_KEY_LEFT) { |
@@ -957,6 +978,7 @@ do_help: | |||
957 | } | 978 | } |
958 | 979 | ||
959 | if (browser->selection->sym != NULL && | 980 | if (browser->selection->sym != NULL && |
981 | !browser->selection->map->dso->annotate_warned && | ||
960 | asprintf(&options[nr_options], "Annotate %s", | 982 | asprintf(&options[nr_options], "Annotate %s", |
961 | browser->selection->sym->name) > 0) | 983 | browser->selection->sym->name) > 0) |
962 | annotate = nr_options++; | 984 | annotate = nr_options++; |
@@ -991,6 +1013,7 @@ do_help: | |||
991 | struct hist_entry *he; | 1013 | struct hist_entry *he; |
992 | do_annotate: | 1014 | do_annotate: |
993 | if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { | 1015 | if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { |
1016 | browser->selection->map->dso->annotate_warned = 1; | ||
994 | ui_helpline__puts("No vmlinux file found, can't " | 1017 | ui_helpline__puts("No vmlinux file found, can't " |
995 | "annotate with just a " | 1018 | "annotate with just a " |
996 | "kallsyms file"); | 1019 | "kallsyms file"); |
@@ -1001,7 +1024,7 @@ do_annotate: | |||
1001 | if (he == NULL) | 1024 | if (he == NULL) |
1002 | continue; | 1025 | continue; |
1003 | 1026 | ||
1004 | hist_entry__annotate_browser(he); | 1027 | hist_entry__tui_annotate(he); |
1005 | } else if (choice == zoom_dso) { | 1028 | } else if (choice == zoom_dso) { |
1006 | zoom_dso: | 1029 | zoom_dso: |
1007 | if (dso_filter) { | 1030 | if (dso_filter) { |
@@ -1069,7 +1092,7 @@ void setup_browser(void) | |||
1069 | { | 1092 | { |
1070 | struct newtPercentTreeColors *c = &defaultPercentTreeColors; | 1093 | struct newtPercentTreeColors *c = &defaultPercentTreeColors; |
1071 | 1094 | ||
1072 | if (!isatty(1) || !use_browser) { | 1095 | if (!isatty(1) || !use_browser || dump_trace) { |
1073 | setup_pager(); | 1096 | setup_pager(); |
1074 | return; | 1097 | return; |
1075 | } | 1098 | } |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 45b9655f3a5c..4e8b6b0c551c 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -81,7 +81,7 @@ | |||
81 | #include <inttypes.h> | 81 | #include <inttypes.h> |
82 | #include "../../../include/linux/magic.h" | 82 | #include "../../../include/linux/magic.h" |
83 | #include "types.h" | 83 | #include "types.h" |
84 | 84 | #include <sys/ttydefaults.h> | |
85 | 85 | ||
86 | #ifndef NO_ICONV | 86 | #ifndef NO_ICONV |
87 | #include <iconv.h> | 87 | #include <iconv.h> |
@@ -263,6 +263,19 @@ bool strglobmatch(const char *str, const char *pat); | |||
263 | bool strlazymatch(const char *str, const char *pat); | 263 | bool strlazymatch(const char *str, const char *pat); |
264 | unsigned long convert_unit(unsigned long value, char *unit); | 264 | unsigned long convert_unit(unsigned long value, char *unit); |
265 | 265 | ||
266 | #ifndef ESC | ||
267 | #define ESC 27 | ||
268 | #endif | ||
269 | |||
270 | static inline bool is_exit_key(int key) | ||
271 | { | ||
272 | char up; | ||
273 | if (key == CTRL('c') || key == ESC) | ||
274 | return true; | ||
275 | up = toupper(key); | ||
276 | return up == 'Q'; | ||
277 | } | ||
278 | |||
266 | #define _STR(x) #x | 279 | #define _STR(x) #x |
267 | #define STR(x) _STR(x) | 280 | #define STR(x) _STR(x) |
268 | 281 | ||