aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-05-14 19:05:21 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-05-14 19:05:21 -0400
commit3e1bbdc3a721f4b1ed44f4554402a8dbc60fa97f (patch)
tree36dce578a3f530c72e30051ded963759dc40a716 /tools/perf
parentc82ee828aa20487d254a5225d256cd422acee459 (diff)
perf newt: Make <- zoom out filters
After we use the filters to zoom into DSOs or threads, we can use <- (left arrow) to zoom out from the last filter applied. It is still possible to zoom out of order by using the popup menu. With this we now have the zoom out operation on the browsing fast path, by allowing fast navigation using just the four arrors and the enter key to expand collapse callchains. Suggested-by: Ingo Molnar <mingo@elte.hu> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> 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')
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/util/newt.c34
-rw-r--r--tools/perf/util/pstack.c75
-rw-r--r--tools/perf/util/pstack.h12
4 files changed, 120 insertions, 3 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9c4dc30cdc13..a9281cca4114 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -416,6 +416,7 @@ LIB_H += util/thread.h
416LIB_H += util/trace-event.h 416LIB_H += util/trace-event.h
417LIB_H += util/probe-finder.h 417LIB_H += util/probe-finder.h
418LIB_H += util/probe-event.h 418LIB_H += util/probe-event.h
419LIB_H += util/pstack.h
419LIB_H += util/cpumap.h 420LIB_H += util/cpumap.h
420 421
421LIB_OBJS += $(OUTPUT)util/abspath.o 422LIB_OBJS += $(OUTPUT)util/abspath.o
@@ -451,6 +452,7 @@ LIB_OBJS += $(OUTPUT)util/callchain.o
451LIB_OBJS += $(OUTPUT)util/values.o 452LIB_OBJS += $(OUTPUT)util/values.o
452LIB_OBJS += $(OUTPUT)util/debug.o 453LIB_OBJS += $(OUTPUT)util/debug.o
453LIB_OBJS += $(OUTPUT)util/map.o 454LIB_OBJS += $(OUTPUT)util/map.o
455LIB_OBJS += $(OUTPUT)util/pstack.o
454LIB_OBJS += $(OUTPUT)util/session.o 456LIB_OBJS += $(OUTPUT)util/session.o
455LIB_OBJS += $(OUTPUT)util/thread.o 457LIB_OBJS += $(OUTPUT)util/thread.o
456LIB_OBJS += $(OUTPUT)util/trace-event-parse.o 458LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index 3402453812b3..e74df1240ef6 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -9,6 +9,7 @@
9 9
10#include "cache.h" 10#include "cache.h"
11#include "hist.h" 11#include "hist.h"
12#include "pstack.h"
12#include "session.h" 13#include "session.h"
13#include "sort.h" 14#include "sort.h"
14#include "symbol.h" 15#include "symbol.h"
@@ -750,6 +751,7 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
750 newtFormAddHotKey(self->form, 'A'); 751 newtFormAddHotKey(self->form, 'A');
751 newtFormAddHotKey(self->form, 'a'); 752 newtFormAddHotKey(self->form, 'a');
752 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); 753 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
754 newtFormAddHotKey(self->form, NEWT_KEY_LEFT);
753 newtFormAddComponents(self->form, self->tree, NULL); 755 newtFormAddComponents(self->form, self->tree, NULL);
754 self->selection = newt__symbol_tree_get_current(self->tree); 756 self->selection = newt__symbol_tree_get_current(self->tree);
755 757
@@ -801,6 +803,7 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
801int hists__browse(struct hists *self, const char *helpline, const char *input_name) 803int hists__browse(struct hists *self, const char *helpline, const char *input_name)
802{ 804{
803 struct hist_browser *browser = hist_browser__new(); 805 struct hist_browser *browser = hist_browser__new();
806 struct pstack *fstack = pstack__new(2);
804 const struct thread *thread_filter = NULL; 807 const struct thread *thread_filter = NULL;
805 const struct dso *dso_filter = NULL; 808 const struct dso *dso_filter = NULL;
806 struct newtExitStruct es; 809 struct newtExitStruct es;
@@ -810,12 +813,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
810 if (browser == NULL) 813 if (browser == NULL)
811 return -1; 814 return -1;
812 815
816 fstack = pstack__new(2);
817 if (fstack == NULL)
818 goto out;
819
813 ui_helpline__push(helpline); 820 ui_helpline__push(helpline);
814 821
815 hist_browser__title(msg, sizeof(msg), input_name, 822 hist_browser__title(msg, sizeof(msg), input_name,
816 dso_filter, thread_filter); 823 dso_filter, thread_filter);
817 if (hist_browser__populate(browser, self, msg) < 0) 824 if (hist_browser__populate(browser, self, msg) < 0)
818 goto out; 825 goto out_free_stack;
819 826
820 while (1) { 827 while (1) {
821 const struct thread *thread; 828 const struct thread *thread;
@@ -836,6 +843,19 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
836 else 843 else
837 continue; 844 continue;
838 } 845 }
846
847 if (es.u.key == NEWT_KEY_LEFT) {
848 const void *top;
849
850 if (pstack__empty(fstack))
851 continue;
852 top = pstack__pop(fstack);
853 if (top == &dso_filter)
854 goto zoom_out_dso;
855 if (top == &thread_filter)
856 goto zoom_out_thread;
857 continue;
858 }
839 } 859 }
840 860
841 if (browser->selection->sym != NULL && 861 if (browser->selection->sym != NULL &&
@@ -888,12 +908,15 @@ do_annotate:
888 hist_entry__annotate_browser(he); 908 hist_entry__annotate_browser(he);
889 } else if (choice == zoom_dso) { 909 } else if (choice == zoom_dso) {
890 if (dso_filter) { 910 if (dso_filter) {
911 pstack__remove(fstack, &dso_filter);
912zoom_out_dso:
891 ui_helpline__pop(); 913 ui_helpline__pop();
892 dso_filter = NULL; 914 dso_filter = NULL;
893 } else { 915 } else {
894 ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s DSO\"", 916 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"",
895 dso->kernel ? "the Kernel" : dso->short_name); 917 dso->kernel ? "the Kernel" : dso->short_name);
896 dso_filter = dso; 918 dso_filter = dso;
919 pstack__push(fstack, &dso_filter);
897 } 920 }
898 hists__filter_by_dso(self, dso_filter); 921 hists__filter_by_dso(self, dso_filter);
899 hist_browser__title(msg, sizeof(msg), input_name, 922 hist_browser__title(msg, sizeof(msg), input_name,
@@ -902,13 +925,16 @@ do_annotate:
902 goto out; 925 goto out;
903 } else if (choice == zoom_thread) { 926 } else if (choice == zoom_thread) {
904 if (thread_filter) { 927 if (thread_filter) {
928 pstack__remove(fstack, &thread_filter);
929zoom_out_thread:
905 ui_helpline__pop(); 930 ui_helpline__pop();
906 thread_filter = NULL; 931 thread_filter = NULL;
907 } else { 932 } else {
908 ui_helpline__fpush("To zoom out press -> + \"Zoom out of %s(%d) thread\"", 933 ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"",
909 thread->comm_set ? thread->comm : "", 934 thread->comm_set ? thread->comm : "",
910 thread->pid); 935 thread->pid);
911 thread_filter = thread; 936 thread_filter = thread;
937 pstack__push(fstack, &thread_filter);
912 } 938 }
913 hists__filter_by_thread(self, thread_filter); 939 hists__filter_by_thread(self, thread_filter);
914 hist_browser__title(msg, sizeof(msg), input_name, 940 hist_browser__title(msg, sizeof(msg), input_name,
@@ -918,6 +944,8 @@ do_annotate:
918 } 944 }
919 } 945 }
920 err = 0; 946 err = 0;
947out_free_stack:
948 pstack__delete(fstack);
921out: 949out:
922 hist_browser__delete(browser); 950 hist_browser__delete(browser);
923 return err; 951 return err;
diff --git a/tools/perf/util/pstack.c b/tools/perf/util/pstack.c
new file mode 100644
index 000000000000..13d36faf64eb
--- /dev/null
+++ b/tools/perf/util/pstack.c
@@ -0,0 +1,75 @@
1/*
2 * Simple pointer stack
3 *
4 * (c) 2010 Arnaldo Carvalho de Melo <acme@redhat.com>
5 */
6
7#include "util.h"
8#include "pstack.h"
9#include <linux/kernel.h>
10#include <stdlib.h>
11
12struct pstack {
13 unsigned short top;
14 unsigned short max_nr_entries;
15 void *entries[0];
16};
17
18struct pstack *pstack__new(unsigned short max_nr_entries)
19{
20 struct pstack *self = zalloc((sizeof(*self) +
21 max_nr_entries * sizeof(void *)));
22 if (self != NULL)
23 self->max_nr_entries = max_nr_entries;
24 return self;
25}
26
27void pstack__delete(struct pstack *self)
28{
29 free(self);
30}
31
32bool pstack__empty(const struct pstack *self)
33{
34 return self->top == 0;
35}
36
37void pstack__remove(struct pstack *self, void *key)
38{
39 unsigned short i = self->top, last_index = self->top - 1;
40
41 while (i-- != 0) {
42 if (self->entries[i] == key) {
43 if (i < last_index)
44 memmove(self->entries + i,
45 self->entries + i + 1,
46 (last_index - i) * sizeof(void *));
47 --self->top;
48 return;
49 }
50 }
51 pr_err("%s: %p not on the pstack!\n", __func__, key);
52}
53
54void pstack__push(struct pstack *self, void *key)
55{
56 if (self->top == self->max_nr_entries) {
57 pr_err("%s: top=%d, overflow!\n", __func__, self->top);
58 return;
59 }
60 self->entries[self->top++] = key;
61}
62
63void *pstack__pop(struct pstack *self)
64{
65 void *ret;
66
67 if (self->top == 0) {
68 pr_err("%s: underflow!\n", __func__);
69 return NULL;
70 }
71
72 ret = self->entries[--self->top];
73 self->entries[self->top] = NULL;
74 return ret;
75}
diff --git a/tools/perf/util/pstack.h b/tools/perf/util/pstack.h
new file mode 100644
index 000000000000..5ad07023504b
--- /dev/null
+++ b/tools/perf/util/pstack.h
@@ -0,0 +1,12 @@
1#ifndef _PERF_PSTACK_
2#define _PERF_PSTACK_
3
4struct pstack;
5struct pstack *pstack__new(unsigned short max_nr_entries);
6void pstack__delete(struct pstack *self);
7bool pstack__empty(const struct pstack *self);
8void pstack__remove(struct pstack *self, void *key);
9void pstack__push(struct pstack *self, void *key);
10void *pstack__pop(struct pstack *self);
11
12#endif /* _PERF_PSTACK_ */