diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-18 10:21:50 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-09-24 11:26:59 -0400 |
commit | efd2b924d3af0efd360cb5b7f29ddc9bc74fce4b (patch) | |
tree | d33cf0ddc12567a6cbef32b614b9873044decc95 /tools/perf | |
parent | 2b29175d2b212d88f100c8819aaea097be61e062 (diff) |
perf evsel: Provide a new constructor for tracepoints
The existing constructor receives a perf_event_attr filled with the
event type and the config.
To reduce the boilerplate for tracepoints, provide a new constructor,
perf_evsel__newtp() that receives the tracepoint name and will open
the debugfs file, call into libtraceevent new pevent_parse_format file
to fill its ->tp_format member, so that users can then just call
perf_evsel__field() to access its fields.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/n/tip-6du8dl1hz0y5l4cybodye7hn@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/evsel.c | 88 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 5 |
2 files changed, 87 insertions, 6 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1506ba0453f1..00936ad29ff2 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <byteswap.h> | 10 | #include <byteswap.h> |
11 | #include <linux/bitops.h> | 11 | #include <linux/bitops.h> |
12 | #include "asm/bug.h" | 12 | #include "asm/bug.h" |
13 | #include "debugfs.h" | ||
13 | #include "event-parse.h" | 14 | #include "event-parse.h" |
14 | #include "evsel.h" | 15 | #include "evsel.h" |
15 | #include "evlist.h" | 16 | #include "evlist.h" |
@@ -69,6 +70,72 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) | |||
69 | return evsel; | 70 | return evsel; |
70 | } | 71 | } |
71 | 72 | ||
73 | static struct event_format *event_format__new(const char *sys, const char *name) | ||
74 | { | ||
75 | int fd, n; | ||
76 | char *filename; | ||
77 | void *bf = NULL, *nbf; | ||
78 | size_t size = 0, alloc_size = 0; | ||
79 | struct event_format *format = NULL; | ||
80 | |||
81 | if (asprintf(&filename, "%s/%s/%s/format", tracing_events_path, sys, name) < 0) | ||
82 | goto out; | ||
83 | |||
84 | fd = open(filename, O_RDONLY); | ||
85 | if (fd < 0) | ||
86 | goto out_free_filename; | ||
87 | |||
88 | do { | ||
89 | if (size == alloc_size) { | ||
90 | alloc_size += BUFSIZ; | ||
91 | nbf = realloc(bf, alloc_size); | ||
92 | if (nbf == NULL) | ||
93 | goto out_free_bf; | ||
94 | bf = nbf; | ||
95 | } | ||
96 | |||
97 | n = read(fd, bf + size, BUFSIZ); | ||
98 | if (n < 0) | ||
99 | goto out_free_bf; | ||
100 | size += n; | ||
101 | } while (n > 0); | ||
102 | |||
103 | pevent_parse_format(&format, bf, size, sys); | ||
104 | |||
105 | out_free_bf: | ||
106 | free(bf); | ||
107 | close(fd); | ||
108 | out_free_filename: | ||
109 | free(filename); | ||
110 | out: | ||
111 | return format; | ||
112 | } | ||
113 | |||
114 | struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) | ||
115 | { | ||
116 | struct perf_evsel *evsel = zalloc(sizeof(*evsel)); | ||
117 | |||
118 | if (evsel != NULL) { | ||
119 | struct perf_event_attr attr = { | ||
120 | .type = PERF_TYPE_TRACEPOINT, | ||
121 | }; | ||
122 | |||
123 | evsel->tp_format = event_format__new(sys, name); | ||
124 | if (evsel->tp_format == NULL) | ||
125 | goto out_free; | ||
126 | |||
127 | attr.config = evsel->tp_format->id; | ||
128 | perf_evsel__init(evsel, &attr, idx); | ||
129 | evsel->name = evsel->tp_format->name; | ||
130 | } | ||
131 | |||
132 | return evsel; | ||
133 | |||
134 | out_free: | ||
135 | free(evsel); | ||
136 | return NULL; | ||
137 | } | ||
138 | |||
72 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { | 139 | const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { |
73 | "cycles", | 140 | "cycles", |
74 | "instructions", | 141 | "instructions", |
@@ -495,6 +562,10 @@ void perf_evsel__delete(struct perf_evsel *evsel) | |||
495 | perf_evsel__exit(evsel); | 562 | perf_evsel__exit(evsel); |
496 | close_cgroup(evsel->cgrp); | 563 | close_cgroup(evsel->cgrp); |
497 | free(evsel->group_name); | 564 | free(evsel->group_name); |
565 | if (evsel->tp_format && evsel->name == evsel->tp_format->name) { | ||
566 | evsel->name = NULL; | ||
567 | pevent_free_format(evsel->tp_format); | ||
568 | } | ||
498 | free(evsel->name); | 569 | free(evsel->name); |
499 | free(evsel); | 570 | free(evsel); |
500 | } | 571 | } |
@@ -1002,14 +1073,19 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
1002 | return 0; | 1073 | return 0; |
1003 | } | 1074 | } |
1004 | 1075 | ||
1076 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) | ||
1077 | { | ||
1078 | return pevent_find_field(evsel->tp_format, name); | ||
1079 | } | ||
1080 | |||
1005 | char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | 1081 | char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, |
1006 | const char *name) | 1082 | const char *name) |
1007 | { | 1083 | { |
1008 | struct format_field *field = pevent_find_field(evsel->tp_format, name); | 1084 | struct format_field *field = perf_evsel__field(evsel, name); |
1009 | int offset; | 1085 | int offset; |
1010 | 1086 | ||
1011 | if (!field) | 1087 | if (!field) |
1012 | return NULL; | 1088 | return NULL; |
1013 | 1089 | ||
1014 | offset = field->offset; | 1090 | offset = field->offset; |
1015 | 1091 | ||
@@ -1024,11 +1100,11 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
1024 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 1100 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
1025 | const char *name) | 1101 | const char *name) |
1026 | { | 1102 | { |
1027 | struct format_field *field = pevent_find_field(evsel->tp_format, name); | 1103 | struct format_field *field = perf_evsel__field(evsel, name); |
1028 | u64 val; | 1104 | u64 val; |
1029 | 1105 | ||
1030 | if (!field) | 1106 | if (!field) |
1031 | return 0; | 1107 | return 0; |
1032 | 1108 | ||
1033 | val = pevent_read_number(evsel->tp_format->pevent, | 1109 | val = pevent_read_number(evsel->tp_format->pevent, |
1034 | sample->raw_data + field->offset, field->size); | 1110 | sample->raw_data + field->offset, field->size); |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 93876bad2e52..bb445d1cbc7b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -81,6 +81,7 @@ struct perf_evlist; | |||
81 | struct perf_record_opts; | 81 | struct perf_record_opts; |
82 | 82 | ||
83 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); | 83 | struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); |
84 | struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx); | ||
84 | void perf_evsel__init(struct perf_evsel *evsel, | 85 | void perf_evsel__init(struct perf_evsel *evsel, |
85 | struct perf_event_attr *attr, int idx); | 86 | struct perf_event_attr *attr, int idx); |
86 | void perf_evsel__exit(struct perf_evsel *evsel); | 87 | void perf_evsel__exit(struct perf_evsel *evsel); |
@@ -128,6 +129,10 @@ char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, | |||
128 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, | 129 | u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, |
129 | const char *name); | 130 | const char *name); |
130 | 131 | ||
132 | struct format_field; | ||
133 | |||
134 | struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); | ||
135 | |||
131 | #define perf_evsel__match(evsel, t, c) \ | 136 | #define perf_evsel__match(evsel, t, c) \ |
132 | (evsel->attr.type == PERF_TYPE_##t && \ | 137 | (evsel->attr.type == PERF_TYPE_##t && \ |
133 | evsel->attr.config == PERF_COUNT_##c) | 138 | evsel->attr.config == PERF_COUNT_##c) |