aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-02-18 02:25:05 -0500
committerIngo Molnar <mingo@elte.hu>2011-02-18 02:25:05 -0500
commite4cc9f4a207aeb819f358114eb23a04547d4807c (patch)
tree4c8f7f56427948ca9c2f30659ee18c6dcfdb4d08 /tools
parente9345aab675382176740bc8a2c6d3caf1510e46d (diff)
parent668b8788f497b2386402daeca583d6300240d41d (diff)
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-list.txt23
-rw-r--r--tools/perf/builtin-list.c43
-rw-r--r--tools/perf/builtin-record.c10
-rw-r--r--tools/perf/builtin-report.c6
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/hist.c7
-rw-r--r--tools/perf/util/parse-events.c104
-rw-r--r--tools/perf/util/parse-events.h5
-rw-r--r--tools/perf/util/setup.py2
10 files changed, 177 insertions, 31 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 399751befeed..7a527f7e9da9 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' 11'perf list' [hw|sw|cache|tracepoint|event_glob]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
@@ -63,7 +63,26 @@ details. Some of them are referenced in the SEE ALSO section below.
63 63
64OPTIONS 64OPTIONS
65------- 65-------
66None 66
67Without options all known events will be listed.
68
69To limit the list use:
70
71. 'hw' or 'hardware' to list hardware events such as cache-misses, etc.
72
73. 'sw' or 'software' to list software events such as context switches, etc.
74
75. 'cache' or 'hwcache' to list hardware cache events such as L1-dcache-loads, etc.
76
77. 'tracepoint' to list all tracepoint events, alternatively use
78 'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched,
79 block, etc.
80
81. If none of the above is matched, it will apply the supplied glob to all
82 events, printing the ones that match.
83
84One or more types can be used at the same time, listing the events for the
85types specified.
67 86
68SEE ALSO 87SEE ALSO
69-------- 88--------
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index d88c6961274c..6313b6eb3ebb 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -5,6 +5,7 @@
5 * 5 *
6 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de> 6 * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
7 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 7 * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
8 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
8 */ 9 */
9#include "builtin.h" 10#include "builtin.h"
10 11
@@ -13,9 +14,47 @@
13#include "util/parse-events.h" 14#include "util/parse-events.h"
14#include "util/cache.h" 15#include "util/cache.h"
15 16
16int cmd_list(int argc __used, const char **argv __used, const char *prefix __used) 17int cmd_list(int argc, const char **argv, const char *prefix __used)
17{ 18{
18 setup_pager(); 19 setup_pager();
19 print_events(); 20
21 if (argc == 1)
22 print_events(NULL);
23 else {
24 int i;
25
26 for (i = 1; i < argc; ++i) {
27 if (i > 1)
28 putchar('\n');
29 if (strncmp(argv[i], "tracepoint", 10) == 0)
30 print_tracepoint_events(NULL, NULL);
31 else if (strcmp(argv[i], "hw") == 0 ||
32 strcmp(argv[i], "hardware") == 0)
33 print_events_type(PERF_TYPE_HARDWARE);
34 else if (strcmp(argv[i], "sw") == 0 ||
35 strcmp(argv[i], "software") == 0)
36 print_events_type(PERF_TYPE_SOFTWARE);
37 else if (strcmp(argv[i], "cache") == 0 ||
38 strcmp(argv[i], "hwcache") == 0)
39 print_hwcache_events(NULL);
40 else {
41 char *sep = strchr(argv[i], ':'), *s;
42 int sep_idx;
43
44 if (sep == NULL) {
45 print_events(argv[i]);
46 continue;
47 }
48 sep_idx = sep - argv[i];
49 s = strdup(argv[i]);
50 if (s == NULL)
51 return -1;
52
53 s[sep_idx] = '\0';
54 print_tracepoint_events(s, s + sep_idx + 1);
55 free(s);
56 }
57 }
58 }
20 return 0; 59 return 0;
21} 60}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index a4aaadcb4c8b..db4cd1e7b51a 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -538,11 +538,6 @@ static int __cmd_record(int argc, const char **argv)
538 if (have_tracepoints(&evsel_list->entries)) 538 if (have_tracepoints(&evsel_list->entries))
539 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 539 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
540 540
541 /*
542 * perf_session__delete(session) will be called at atexit_header()
543 */
544 atexit(atexit_header);
545
546 if (forks) { 541 if (forks) {
547 child_pid = fork(); 542 child_pid = fork();
548 if (child_pid < 0) { 543 if (child_pid < 0) {
@@ -601,6 +596,11 @@ static int __cmd_record(int argc, const char **argv)
601 596
602 perf_session__set_sample_type(session, sample_type); 597 perf_session__set_sample_type(session, sample_type);
603 598
599 /*
600 * perf_session__delete(session) will be called at atexit_header()
601 */
602 atexit(atexit_header);
603
604 if (pipe_output) { 604 if (pipe_output) {
605 err = perf_header__write_pipe(output); 605 err = perf_header__write_pipe(output);
606 if (err < 0) 606 if (err < 0)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index f9a99a1ce609..dddcc7ea2bec 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -350,6 +350,12 @@ static int __cmd_report(void)
350 perf_session__fprintf_dsos(session, stdout); 350 perf_session__fprintf_dsos(session, stdout);
351 351
352 next = rb_first(&session->hists_tree); 352 next = rb_first(&session->hists_tree);
353
354 if (next == NULL) {
355 ui__warning("The %s file has no samples!\n", input_name);
356 goto out_delete;
357 }
358
353 while (next) { 359 while (next) {
354 struct hists *hists; 360 struct hists *hists;
355 361
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index c974e08d07ab..63cadaf3e208 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -86,6 +86,7 @@ void perf_evsel__delete(struct perf_evsel *evsel)
86{ 86{
87 perf_evsel__exit(evsel); 87 perf_evsel__exit(evsel);
88 close_cgroup(evsel->cgrp); 88 close_cgroup(evsel->cgrp);
89 free(evsel->name);
89 free(evsel); 90 free(evsel);
90} 91}
91 92
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 1d3d5a3dbe60..f6fc8f651a25 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -37,6 +37,12 @@ struct perf_sample_id {
37 struct perf_evsel *evsel; 37 struct perf_evsel *evsel;
38}; 38};
39 39
40/** struct perf_evsel - event selector
41 *
42 * @name - Can be set to retain the original event name passed by the user,
43 * so that when showing results in tools such as 'perf stat', we
44 * show the name used, not some alias.
45 */
40struct perf_evsel { 46struct perf_evsel {
41 struct list_head node; 47 struct list_head node;
42 struct perf_event_attr attr; 48 struct perf_event_attr attr;
@@ -45,6 +51,7 @@ struct perf_evsel {
45 struct xyarray *id; 51 struct xyarray *id;
46 struct perf_counts *counts; 52 struct perf_counts *counts;
47 int idx; 53 int idx;
54 char *name;
48 void *priv; 55 void *priv;
49 struct cgroup_sel *cgrp; 56 struct cgroup_sel *cgrp;
50}; 57};
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 3f437236f193..da2899e8c6f8 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -591,6 +591,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
591{ 591{
592 struct sort_entry *se; 592 struct sort_entry *se;
593 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us; 593 u64 period, total, period_sys, period_us, period_guest_sys, period_guest_us;
594 u64 nr_events;
594 const char *sep = symbol_conf.field_sep; 595 const char *sep = symbol_conf.field_sep;
595 int ret; 596 int ret;
596 597
@@ -599,6 +600,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
599 600
600 if (pair_hists) { 601 if (pair_hists) {
601 period = self->pair ? self->pair->period : 0; 602 period = self->pair ? self->pair->period : 0;
603 nr_events = self->pair ? self->pair->nr_events : 0;
602 total = pair_hists->stats.total_period; 604 total = pair_hists->stats.total_period;
603 period_sys = self->pair ? self->pair->period_sys : 0; 605 period_sys = self->pair ? self->pair->period_sys : 0;
604 period_us = self->pair ? self->pair->period_us : 0; 606 period_us = self->pair ? self->pair->period_us : 0;
@@ -606,6 +608,7 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
606 period_guest_us = self->pair ? self->pair->period_guest_us : 0; 608 period_guest_us = self->pair ? self->pair->period_guest_us : 0;
607 } else { 609 } else {
608 period = self->period; 610 period = self->period;
611 nr_events = self->nr_events;
609 total = session_total; 612 total = session_total;
610 period_sys = self->period_sys; 613 period_sys = self->period_sys;
611 period_us = self->period_us; 614 period_us = self->period_us;
@@ -646,9 +649,9 @@ int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
646 649
647 if (symbol_conf.show_nr_samples) { 650 if (symbol_conf.show_nr_samples) {
648 if (sep) 651 if (sep)
649 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, period); 652 ret += snprintf(s + ret, size - ret, "%c%" PRIu64, *sep, nr_events);
650 else 653 else
651 ret += snprintf(s + ret, size - ret, "%11" PRIu64, period); 654 ret += snprintf(s + ret, size - ret, "%11" PRIu64, nr_events);
652 } 655 }
653 656
654 if (pair_hists) { 657 if (pair_hists) {
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index cf082daa43e3..54a7e2634d58 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -268,6 +268,9 @@ const char *event_name(struct perf_evsel *evsel)
268 u64 config = evsel->attr.config; 268 u64 config = evsel->attr.config;
269 int type = evsel->attr.type; 269 int type = evsel->attr.type;
270 270
271 if (evsel->name)
272 return evsel->name;
273
271 return __event_name(type, config); 274 return __event_name(type, config);
272} 275}
273 276
@@ -782,8 +785,10 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
782 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 785 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
783 struct perf_event_attr attr; 786 struct perf_event_attr attr;
784 enum event_result ret; 787 enum event_result ret;
788 const char *ostr;
785 789
786 for (;;) { 790 for (;;) {
791 ostr = str;
787 memset(&attr, 0, sizeof(attr)); 792 memset(&attr, 0, sizeof(attr));
788 ret = parse_event_symbols(opt, &str, &attr); 793 ret = parse_event_symbols(opt, &str, &attr);
789 if (ret == EVT_FAILED) 794 if (ret == EVT_FAILED)
@@ -798,6 +803,11 @@ int parse_events(const struct option *opt, const char *str, int unset __used)
798 if (evsel == NULL) 803 if (evsel == NULL)
799 return -1; 804 return -1;
800 perf_evlist__add(evlist, evsel); 805 perf_evlist__add(evlist, evsel);
806
807 evsel->name = calloc(str - ostr + 1, 1);
808 if (!evsel->name)
809 return -1;
810 strncpy(evsel->name, ostr, str - ostr);
801 } 811 }
802 812
803 if (*str == 0) 813 if (*str == 0)
@@ -848,7 +858,7 @@ static const char * const event_type_descriptors[] = {
848 * Print the events from <debugfs_mount_point>/tracing/events 858 * Print the events from <debugfs_mount_point>/tracing/events
849 */ 859 */
850 860
851static void print_tracepoint_events(void) 861void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
852{ 862{
853 DIR *sys_dir, *evt_dir; 863 DIR *sys_dir, *evt_dir;
854 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 864 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -863,6 +873,9 @@ static void print_tracepoint_events(void)
863 return; 873 return;
864 874
865 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 875 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
876 if (subsys_glob != NULL &&
877 !strglobmatch(sys_dirent.d_name, subsys_glob))
878 continue;
866 879
867 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 880 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
868 sys_dirent.d_name); 881 sys_dirent.d_name);
@@ -871,6 +884,10 @@ static void print_tracepoint_events(void)
871 continue; 884 continue;
872 885
873 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { 886 for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
887 if (event_glob != NULL &&
888 !strglobmatch(evt_dirent.d_name, event_glob))
889 continue;
890
874 snprintf(evt_path, MAXPATHLEN, "%s:%s", 891 snprintf(evt_path, MAXPATHLEN, "%s:%s",
875 sys_dirent.d_name, evt_dirent.d_name); 892 sys_dirent.d_name, evt_dirent.d_name);
876 printf(" %-42s [%s]\n", evt_path, 893 printf(" %-42s [%s]\n", evt_path,
@@ -922,13 +939,61 @@ int is_valid_tracepoint(const char *event_string)
922 return 0; 939 return 0;
923} 940}
924 941
942void print_events_type(u8 type)
943{
944 struct event_symbol *syms = event_symbols;
945 unsigned int i;
946 char name[64];
947
948 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
949 if (type != syms->type)
950 continue;
951
952 if (strlen(syms->alias))
953 snprintf(name, sizeof(name), "%s OR %s",
954 syms->symbol, syms->alias);
955 else
956 snprintf(name, sizeof(name), "%s", syms->symbol);
957
958 printf(" %-42s [%s]\n", name,
959 event_type_descriptors[type]);
960 }
961}
962
963int print_hwcache_events(const char *event_glob)
964{
965 unsigned int type, op, i, printed = 0;
966
967 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
968 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
969 /* skip invalid cache type */
970 if (!is_cache_op_valid(type, op))
971 continue;
972
973 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
974 char *name = event_cache_name(type, op, i);
975
976 if (event_glob != NULL &&
977 !strglobmatch(name, event_glob))
978 continue;
979
980 printf(" %-42s [%s]\n", name,
981 event_type_descriptors[PERF_TYPE_HW_CACHE]);
982 ++printed;
983 }
984 }
985 }
986
987 return printed;
988}
989
925/* 990/*
926 * Print the help text for the event symbols: 991 * Print the help text for the event symbols:
927 */ 992 */
928void print_events(void) 993void print_events(const char *event_glob)
929{ 994{
930 struct event_symbol *syms = event_symbols; 995 struct event_symbol *syms = event_symbols;
931 unsigned int i, type, op, prev_type = -1; 996 unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
932 char name[40]; 997 char name[40];
933 998
934 printf("\n"); 999 printf("\n");
@@ -937,8 +1002,16 @@ void print_events(void)
937 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) { 1002 for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
938 type = syms->type; 1003 type = syms->type;
939 1004
940 if (type != prev_type) 1005 if (type != prev_type && printed) {
941 printf("\n"); 1006 printf("\n");
1007 printed = 0;
1008 ntypes_printed++;
1009 }
1010
1011 if (event_glob != NULL &&
1012 !(strglobmatch(syms->symbol, event_glob) ||
1013 (syms->alias && strglobmatch(syms->alias, event_glob))))
1014 continue;
942 1015
943 if (strlen(syms->alias)) 1016 if (strlen(syms->alias))
944 sprintf(name, "%s OR %s", syms->symbol, syms->alias); 1017 sprintf(name, "%s OR %s", syms->symbol, syms->alias);
@@ -948,22 +1021,17 @@ void print_events(void)
948 event_type_descriptors[type]); 1021 event_type_descriptors[type]);
949 1022
950 prev_type = type; 1023 prev_type = type;
1024 ++printed;
951 } 1025 }
952 1026
953 printf("\n"); 1027 if (ntypes_printed) {
954 for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) { 1028 printed = 0;
955 for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) { 1029 printf("\n");
956 /* skip invalid cache type */
957 if (!is_cache_op_valid(type, op))
958 continue;
959
960 for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
961 printf(" %-42s [%s]\n",
962 event_cache_name(type, op, i),
963 event_type_descriptors[PERF_TYPE_HW_CACHE]);
964 }
965 }
966 } 1030 }
1031 print_hwcache_events(event_glob);
1032
1033 if (event_glob != NULL)
1034 return;
967 1035
968 printf("\n"); 1036 printf("\n");
969 printf(" %-42s [%s]\n", 1037 printf(" %-42s [%s]\n",
@@ -976,7 +1044,7 @@ void print_events(void)
976 event_type_descriptors[PERF_TYPE_BREAKPOINT]); 1044 event_type_descriptors[PERF_TYPE_BREAKPOINT]);
977 printf("\n"); 1045 printf("\n");
978 1046
979 print_tracepoint_events(); 1047 print_tracepoint_events(NULL, NULL);
980 1048
981 exit(129); 1049 exit(129);
982} 1050}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index cf7e94abb676..212f88e07a9c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -28,7 +28,10 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
28 28
29#define EVENTS_HELP_MAX (128*1024) 29#define EVENTS_HELP_MAX (128*1024)
30 30
31extern void print_events(void); 31void print_events(const char *event_glob);
32void print_events_type(u8 type);
33void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
34int print_hwcache_events(const char *event_glob);
32extern int is_valid_tracepoint(const char *event_string); 35extern int is_valid_tracepoint(const char *event_string);
33 36
34extern char debugfs_path[]; 37extern char debugfs_path[];
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 1947b0430c94..e24ffadb20b2 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -5,7 +5,7 @@ from distutils.core import setup, Extension
5perf = Extension('perf', 5perf = Extension('perf',
6 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 6 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
7 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 7 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
8 'util/util.c', 'util/xyarray.c'], 8 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'],
9 include_dirs = ['util/include'], 9 include_dirs = ['util/include'],
10 extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings']) 10 extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings'])
11 11