diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-02-22 10:02:07 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-02-22 10:02:07 -0500 |
commit | c97cf42219b7b6037d2f96c27a5f114f2383f828 (patch) | |
tree | 2180e3eae063a217d1681074a813eed42ad91a86 /tools/perf/builtin-top.c | |
parent | 8635bf6ea3402154eec64763e6ed14972013c1c1 (diff) |
perf top: Live TUI Annotation
Now one has just to press the right key, 'a' or Enter on the main 'perf
top --tui' screen to live annotate the symbol under the cursor.
The annotate window starts centered on the hottest line (the one with
most samples so far) then TAB and shift+TAB can be used to go to the
prev/next hot line.
Pressing 'H' at any point will center again the screen on the hottest
line.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c9fd66d4a082..f88a2630e1fc 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -92,7 +92,6 @@ static bool dump_symtab = false; | |||
92 | static struct winsize winsize; | 92 | static struct winsize winsize; |
93 | 93 | ||
94 | static const char *sym_filter = NULL; | 94 | static const char *sym_filter = NULL; |
95 | struct sym_entry *sym_filter_entry = NULL; | ||
96 | struct sym_entry *sym_filter_entry_sched = NULL; | 95 | struct sym_entry *sym_filter_entry_sched = NULL; |
97 | static int sym_pcnt_filter = 5; | 96 | static int sym_pcnt_filter = 5; |
98 | 97 | ||
@@ -168,18 +167,19 @@ static int parse_source(struct sym_entry *syme) | |||
168 | pthread_mutex_lock(¬es->lock); | 167 | pthread_mutex_lock(¬es->lock); |
169 | 168 | ||
170 | if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { | 169 | if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { |
170 | pthread_mutex_unlock(¬es->lock); | ||
171 | pr_err("Not enough memory for annotating '%s' symbol!\n", | 171 | pr_err("Not enough memory for annotating '%s' symbol!\n", |
172 | sym->name); | 172 | sym->name); |
173 | sleep(1); | 173 | sleep(1); |
174 | goto out_unlock; | 174 | return err; |
175 | } | 175 | } |
176 | 176 | ||
177 | err = symbol__annotate(sym, syme->map, 0); | 177 | err = symbol__annotate(sym, syme->map, 0); |
178 | if (err == 0) { | 178 | if (err == 0) { |
179 | out_assign: | 179 | out_assign: |
180 | sym_filter_entry = syme; | 180 | top.sym_filter_entry = syme; |
181 | } | 181 | } |
182 | out_unlock: | 182 | |
183 | pthread_mutex_unlock(¬es->lock); | 183 | pthread_mutex_unlock(¬es->lock); |
184 | return err; | 184 | return err; |
185 | } | 185 | } |
@@ -195,7 +195,7 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) | |||
195 | struct annotation *notes; | 195 | struct annotation *notes; |
196 | struct symbol *sym; | 196 | struct symbol *sym; |
197 | 197 | ||
198 | if (syme != sym_filter_entry) | 198 | if (syme != top.sym_filter_entry) |
199 | return; | 199 | return; |
200 | 200 | ||
201 | sym = sym_entry__symbol(syme); | 201 | sym = sym_entry__symbol(syme); |
@@ -275,8 +275,8 @@ static void print_sym_table(struct perf_session *session) | |||
275 | session->hists.stats.total_lost); | 275 | session->hists.stats.total_lost); |
276 | } | 276 | } |
277 | 277 | ||
278 | if (sym_filter_entry) { | 278 | if (top.sym_filter_entry) { |
279 | show_details(sym_filter_entry); | 279 | show_details(top.sym_filter_entry); |
280 | return; | 280 | return; |
281 | } | 281 | } |
282 | 282 | ||
@@ -417,8 +417,8 @@ static void print_mapped_keys(void) | |||
417 | { | 417 | { |
418 | char *name = NULL; | 418 | char *name = NULL; |
419 | 419 | ||
420 | if (sym_filter_entry) { | 420 | if (top.sym_filter_entry) { |
421 | struct symbol *sym = sym_entry__symbol(sym_filter_entry); | 421 | struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); |
422 | name = sym->name; | 422 | name = sym->name; |
423 | } | 423 | } |
424 | 424 | ||
@@ -549,15 +549,15 @@ static void handle_keypress(struct perf_session *session, int c) | |||
549 | perf_session__fprintf_dsos(session, stderr); | 549 | perf_session__fprintf_dsos(session, stderr); |
550 | exit(0); | 550 | exit(0); |
551 | case 's': | 551 | case 's': |
552 | prompt_symbol(&sym_filter_entry, "Enter details symbol"); | 552 | prompt_symbol(&top.sym_filter_entry, "Enter details symbol"); |
553 | break; | 553 | break; |
554 | case 'S': | 554 | case 'S': |
555 | if (!sym_filter_entry) | 555 | if (!top.sym_filter_entry) |
556 | break; | 556 | break; |
557 | else { | 557 | else { |
558 | struct sym_entry *syme = sym_filter_entry; | 558 | struct sym_entry *syme = top.sym_filter_entry; |
559 | 559 | ||
560 | sym_filter_entry = NULL; | 560 | top.sym_filter_entry = NULL; |
561 | __zero_source_counters(syme); | 561 | __zero_source_counters(syme); |
562 | } | 562 | } |
563 | break; | 563 | break; |
@@ -656,7 +656,7 @@ static int symbol_filter(struct map *map, struct symbol *sym) | |||
656 | syme->map = map; | 656 | syme->map = map; |
657 | symbol__annotate_init(map, sym); | 657 | symbol__annotate_init(map, sym); |
658 | 658 | ||
659 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { | 659 | if (!top.sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { |
660 | /* schedule initial sym_filter_entry setup */ | 660 | /* schedule initial sym_filter_entry setup */ |
661 | sym_filter_entry_sched = syme; | 661 | sym_filter_entry_sched = syme; |
662 | sym_filter = NULL; | 662 | sym_filter = NULL; |
@@ -750,13 +750,13 @@ static void perf_event__process_sample(const union perf_event *event, | |||
750 | 750 | ||
751 | /* let's see, whether we need to install initial sym_filter_entry */ | 751 | /* let's see, whether we need to install initial sym_filter_entry */ |
752 | if (sym_filter_entry_sched) { | 752 | if (sym_filter_entry_sched) { |
753 | sym_filter_entry = sym_filter_entry_sched; | 753 | top.sym_filter_entry = sym_filter_entry_sched; |
754 | sym_filter_entry_sched = NULL; | 754 | sym_filter_entry_sched = NULL; |
755 | if (parse_source(sym_filter_entry) < 0) { | 755 | if (parse_source(top.sym_filter_entry) < 0) { |
756 | struct symbol *sym = sym_entry__symbol(sym_filter_entry); | 756 | struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); |
757 | 757 | ||
758 | pr_err("Can't annotate %s", sym->name); | 758 | pr_err("Can't annotate %s", sym->name); |
759 | if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { | 759 | if (top.sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { |
760 | pr_err(": No vmlinux file was found in the path:\n"); | 760 | pr_err(": No vmlinux file was found in the path:\n"); |
761 | machine__fprintf_vmlinux_path(machine, stderr); | 761 | machine__fprintf_vmlinux_path(machine, stderr); |
762 | } else | 762 | } else |