History

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Improve listing of accessible enum perf probe variables, from Hyeoncheol Lee. * Don't stop the build if the audit libraries are not installed, fix from Namhyung Kim.

Ingo Molnar committed 14 years ago

Commit 1d787d32 parents ac2ba2b aec193022 files · +683 −90Browse files

Unified · Split

22 files
  1. tools/perf/Documentation/perf-trace.txt +53 −0
  2. tools/perf/Makefile +13 −0
  3. tools/perf/builtin-record.c +1 −1
  4. tools/perf/builtin-stat.c +1 −1
  5. tools/perf/builtin-test.c +118 −2
  6. tools/perf/builtin-top.c +1 −1
  7. tools/perf/builtin-trace.c +310 −0
  8. tools/perf/builtin.h +1 −0
  9. tools/perf/command-list.txt +1 −0
  10. tools/perf/config/feature-tests.mak +11 −0
  11. tools/perf/perf.c +3 −0
  12. tools/perf/util/cpumap.h +11 −0
  13. tools/perf/util/dwarf-aux.c +2 −0
  14. tools/perf/util/evlist.c +34 −27
  15. tools/perf/util/evlist.h +4 −2
  16. tools/perf/util/evsel.c +72 −16
  17. tools/perf/util/evsel.h +16 −2
  18. tools/perf/util/header.c +5 −1
  19. tools/perf/util/hist.c +7 −2
  20. tools/perf/util/parse-events.c +16 −30
  21. tools/perf/util/python.c +1 −1
  22. tools/perf/util/session.c +2 −4
tools/perf/Documentation/perf-trace.txt+53−0
@@ -0,0 +1,53 @@
1perf-trace(1)
2=============
3
4NAME
5----
6perf-trace - strace inspired tool
7
8SYNOPSIS
9--------
10[verse]
11'perf trace'
12
13DESCRIPTION
14-----------
15This command will show the events associated with the target, initially
16syscalls, but other system events like pagefaults, task lifetime events,
17scheduling events, etc.
18
19Initially this is a live mode only tool, but eventually will work with
20perf.data files like the other tools, allowing a detached 'record' from
21analysis phases.
22
23OPTIONS
24-------
25
26--all-cpus::
27 System-wide collection from all CPUs.
28
29-p::
30--pid=::
31 Record events on existing process ID (comma separated list).
32
33--tid=::
34 Record events on existing thread ID (comma separated list).
35
36--uid=::
37 Record events in threads owned by uid. Name or number.
38
39--no-inherit::
40 Child tasks do not inherit counters.
41
42--mmap-pages=::
43 Number of mmap data pages. Must be a power of two.
44
45--cpu::
46Collect samples only on the list of CPUs provided. Multiple CPUs can be provided as a
47comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2.
48In per-thread mode with inheritance mode on (default), Events are captured only when
49the thread executes on the designated CPUs. Default is to monitor all CPUs.
50
51SEE ALSO
52--------
53linkperf:perf-record[1], linkperf:perf-script[1]
tools/perf/Makefile+13−0
@@ -559,6 +559,19 @@ else · 558 unmodified lines
559 LIB_OBJS += $(OUTPUT)util/unwind.o559 LIB_OBJS += $(OUTPUT)util/unwind.o
560endif560endif
561 561
562ifdef NO_LIBAUDIT
563 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
564else
565 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
566 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y)
567 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
568 BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT
569 else
570 BUILTIN_OBJS += $(OUTPUT)builtin-trace.o
571 EXTLIBS += -laudit
572 endif
573endif
574
562ifdef NO_NEWT575ifdef NO_NEWT
563 BASIC_CFLAGS += -DNO_NEWT_SUPPORT576 BASIC_CFLAGS += -DNO_NEWT_SUPPORT
564else577else
tools/perf/builtin-record.c+1−1
@@ -320,7 +320,7 @@ try_again: · 319 unmodified lines
320 }320 }
321 }321 }
322 322
323 if (perf_evlist__set_filters(evlist)) {323 if (perf_evlist__apply_filters(evlist)) {
324 error("failed to set filter with %d (%s)\n", errno,324 error("failed to set filter with %d (%s)\n", errno,
325 strerror(errno));325 strerror(errno));
326 rc = -1;326 rc = -1;
tools/perf/builtin-stat.c+1−1
@@ -478,7 +478,7 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv) · 477 unmodified lines
478 counter->supported = true;478 counter->supported = true;
479 }479 }
480 480
481 if (perf_evlist__set_filters(evsel_list)) {481 if (perf_evlist__apply_filters(evsel_list)) {
482 error("failed to set filter with %d (%s)\n", errno,482 error("failed to set filter with %d (%s)\n", errno,
483 strerror(errno));483 strerror(errno));
484 return -1;484 return -1;
tools/perf/builtin-test.c+118−2
@@ -564,7 +564,7 @@ static int test__basic_mmap(void) · 563 unmodified lines
564 goto out_munmap;564 goto out_munmap;
565 }565 }
566 566
567 err = perf_evlist__parse_sample(evlist, event, &sample, false);567 err = perf_evlist__parse_sample(evlist, event, &sample);
568 if (err) {568 if (err) {
569 pr_err("Can't parse sample, err = %d\n", err);569 pr_err("Can't parse sample, err = %d\n", err);
570 goto out_munmap;570 goto out_munmap;
@@ -781,7 +781,7 @@ static int test__PERF_RECORD(void) · 210 unmodified lines
781 if (type < PERF_RECORD_MAX)781 if (type < PERF_RECORD_MAX)
782 nr_events[type]++;782 nr_events[type]++;
783 783
784 err = perf_evlist__parse_sample(evlist, event, &sample, false);784 err = perf_evlist__parse_sample(evlist, event, &sample);
785 if (err < 0) {785 if (err < 0) {
786 if (verbose)786 if (verbose)
787 perf_event__fprintf(event, stderr);787 perf_event__fprintf(event, stderr);
@@ -1289,6 +1289,118 @@ static int perf_evsel__tp_sched_test(void) · 501 unmodified lines
1289 return ret;1289 return ret;
1290}1290}
1291 1291
1292static int test__syscall_open_tp_fields(void)
1293{
1294 struct perf_record_opts opts = {
1295 .target = {
1296 .uid = UINT_MAX,
1297 .uses_mmap = true,
1298 },
1299 .no_delay = true,
1300 .freq = 1,
1301 .mmap_pages = 256,
1302 .raw_samples = true,
1303 };
1304 const char *filename = "/etc/passwd";
1305 int flags = O_RDONLY | O_DIRECTORY;
1306 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
1307 struct perf_evsel *evsel;
1308 int err = -1, i, nr_events = 0, nr_polls = 0;
1309
1310 if (evlist == NULL) {
1311 pr_debug("%s: perf_evlist__new\n", __func__);
1312 goto out;
1313 }
1314
1315 evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
1316 if (evsel == NULL) {
1317 pr_debug("%s: perf_evsel__newtp\n", __func__);
1318 goto out_delete_evlist;
1319 }
1320
1321 perf_evlist__add(evlist, evsel);
1322
1323 err = perf_evlist__create_maps(evlist, &opts.target);
1324 if (err < 0) {
1325 pr_debug("%s: perf_evlist__create_maps\n", __func__);
1326 goto out_delete_evlist;
1327 }
1328
1329 perf_evsel__config(evsel, &opts, evsel);
1330
1331 evlist->threads->map[0] = getpid();
1332
1333 err = perf_evlist__open(evlist);
1334 if (err < 0) {
1335 pr_debug("perf_evlist__open: %s\n", strerror(errno));
1336 goto out_delete_evlist;
1337 }
1338
1339 err = perf_evlist__mmap(evlist, UINT_MAX, false);
1340 if (err < 0) {
1341 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
1342 goto out_delete_evlist;
1343 }
1344
1345 perf_evlist__enable(evlist);
1346
1347 /*
1348 * Generate the event:
1349 */
1350 open(filename, flags);
1351
1352 while (1) {
1353 int before = nr_events;
1354
1355 for (i = 0; i < evlist->nr_mmaps; i++) {
1356 union perf_event *event;
1357
1358 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1359 const u32 type = event->header.type;
1360 int tp_flags;
1361 struct perf_sample sample;
1362
1363 ++nr_events;
1364
1365 if (type != PERF_RECORD_SAMPLE)
1366 continue;
1367
1368 err = perf_evsel__parse_sample(evsel, event, &sample);
1369 if (err) {
1370 pr_err("Can't parse sample, err = %d\n", err);
1371 goto out_munmap;
1372 }
1373
1374 tp_flags = perf_evsel__intval(evsel, &sample, "flags");
1375
1376 if (flags != tp_flags) {
1377 pr_debug("%s: Expected flags=%#x, got %#x\n",
1378 __func__, flags, tp_flags);
1379 goto out_munmap;
1380 }
1381
1382 goto out_ok;
1383 }
1384 }
1385
1386 if (nr_events == before)
1387 poll(evlist->pollfd, evlist->nr_fds, 10);
1388
1389 if (++nr_polls > 5) {
1390 pr_debug("%s: no events!\n", __func__);
1391 goto out_munmap;
1392 }
1393 }
1394out_ok:
1395 err = 0;
1396out_munmap:
1397 perf_evlist__munmap(evlist);
1398out_delete_evlist:
1399 perf_evlist__delete(evlist);
1400out:
1401 return err;
1402}
1403
1292static struct test {1404static struct test {
1293 const char *desc;1405 const char *desc;
1294 int (*func)(void);1406 int (*func)(void);
@@ -1339,6 +1451,10 @@ static struct test { · 44 unmodified lines
1339 .desc = "Check parsing of sched tracepoints fields",1451 .desc = "Check parsing of sched tracepoints fields",
1340 .func = perf_evsel__tp_sched_test,1452 .func = perf_evsel__tp_sched_test,
1341 },1453 },
1454 {
1455 .desc = "Generate and check syscalls:sys_enter_open event fields",
1456 .func = test__syscall_open_tp_fields,
1457 },
1342 {1458 {
1343 .func = NULL,1459 .func = NULL,
1344 },1460 },
tools/perf/builtin-top.c+1−1
@@ -823,7 +823,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) · 822 unmodified lines
823 int ret;823 int ret;
824 824
825 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {825 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
826 ret = perf_evlist__parse_sample(top->evlist, event, &sample, false);826 ret = perf_evlist__parse_sample(top->evlist, event, &sample);
827 if (ret) {827 if (ret) {
828 pr_err("Can't parse sample, err = %d\n", ret);828 pr_err("Can't parse sample, err = %d\n", ret);
829 continue;829 continue;
tools/perf/builtin-trace.c+310−0
@@ -0,0 +1,310 @@
1#include "builtin.h"
2#include "util/evlist.h"
3#include "util/parse-options.h"
4#include "util/thread_map.h"
5#include "event-parse.h"
6
7#include <libaudit.h>
8#include <stdlib.h>
9
10static struct syscall_fmt {
11 const char *name;
12 const char *alias;
13 bool errmsg;
14 bool timeout;
15} syscall_fmts[] = {
16 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
17 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
18 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
19 { .name = "futex", .errmsg = true, },
20 { .name = "poll", .errmsg = true, .timeout = true, },
21 { .name = "ppoll", .errmsg = true, .timeout = true, },
22 { .name = "read", .errmsg = true, },
23 { .name = "recvfrom", .errmsg = true, },
24 { .name = "select", .errmsg = true, .timeout = true, },
25 { .name = "stat", .errmsg = true, .alias = "newstat", },
26};
27
28static int syscall_fmt__cmp(const void *name, const void *fmtp)
29{
30 const struct syscall_fmt *fmt = fmtp;
31 return strcmp(name, fmt->name);
32}
33
34static struct syscall_fmt *syscall_fmt__find(const char *name)
35{
36 const int nmemb = ARRAY_SIZE(syscall_fmts);
37 return bsearch(name, syscall_fmts, nmemb, sizeof(struct syscall_fmt), syscall_fmt__cmp);
38}
39
40struct syscall {
41 struct event_format *tp_format;
42 const char *name;
43 struct syscall_fmt *fmt;
44};
45
46struct trace {
47 int audit_machine;
48 struct {
49 int max;
50 struct syscall *table;
51 } syscalls;
52 struct perf_record_opts opts;
53};
54
55static int trace__read_syscall_info(struct trace *trace, int id)
56{
57 char tp_name[128];
58 struct syscall *sc;
59
60 if (id > trace->syscalls.max) {
61 struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
62
63 if (nsyscalls == NULL)
64 return -1;
65
66 if (trace->syscalls.max != -1) {
67 memset(nsyscalls + trace->syscalls.max + 1, 0,
68 (id - trace->syscalls.max) * sizeof(*sc));
69 } else {
70 memset(nsyscalls, 0, (id + 1) * sizeof(*sc));
71 }
72
73 trace->syscalls.table = nsyscalls;
74 trace->syscalls.max = id;
75 }
76
77 sc = trace->syscalls.table + id;
78 sc->name = audit_syscall_to_name(id, trace->audit_machine);
79 if (sc->name == NULL)
80 return -1;
81
82 sc->fmt = syscall_fmt__find(sc->name);
83
84 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
85 sc->tp_format = event_format__new("syscalls", tp_name);
86
87 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
88 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
89 sc->tp_format = event_format__new("syscalls", tp_name);
90 }
91
92 return sc->tp_format != NULL ? 0 : -1;
93}
94
95static size_t syscall__fprintf_args(struct syscall *sc, unsigned long *args, FILE *fp)
96{
97 int i = 0;
98 size_t printed = 0;
99
100 if (sc->tp_format != NULL) {
101 struct format_field *field;
102
103 for (field = sc->tp_format->format.fields->next; field; field = field->next) {
104 printed += fprintf(fp, "%s%s: %ld", printed ? ", " : "",
105 field->name, args[i++]);
106 }
107 } else {
108 while (i < 6) {
109 printed += fprintf(fp, "%sarg%d: %ld", printed ? ", " : "", i, args[i]);
110 ++i;
111 }
112 }
113
114 return printed;
115}
116
117static int trace__run(struct trace *trace)
118{
119 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
120 struct perf_evsel *evsel, *evsel_enter, *evsel_exit;
121 int err = -1, i, nr_events = 0, before;
122
123 if (evlist == NULL) {
124 printf("Not enough memory to run!\n");
125 goto out;
126 }
127
128 evsel_enter = perf_evsel__newtp("raw_syscalls", "sys_enter", 0);
129 if (evsel_enter == NULL) {
130 printf("Couldn't read the raw_syscalls:sys_enter tracepoint information!\n");
131 goto out_delete_evlist;
132 }
133
134 perf_evlist__add(evlist, evsel_enter);
135
136 evsel_exit = perf_evsel__newtp("raw_syscalls", "sys_exit", 1);
137 if (evsel_exit == NULL) {
138 printf("Couldn't read the raw_syscalls:sys_exit tracepoint information!\n");
139 goto out_delete_evlist;
140 }
141
142 perf_evlist__add(evlist, evsel_exit);
143
144 err = perf_evlist__create_maps(evlist, &trace->opts.target);
145 if (err < 0) {
146 printf("Problems parsing the target to trace, check your options!\n");
147 goto out_delete_evlist;
148 }
149
150 perf_evlist__config_attrs(evlist, &trace->opts);
151
152 err = perf_evlist__open(evlist);
153 if (err < 0) {
154 printf("Couldn't create the events: %s\n", strerror(errno));
155 goto out_delete_evlist;
156 }
157
158 err = perf_evlist__mmap(evlist, UINT_MAX, false);
159 if (err < 0) {
160 printf("Couldn't mmap the events: %s\n", strerror(errno));
161 goto out_delete_evlist;
162 }
163
164 perf_evlist__enable(evlist);
165again:
166 before = nr_events;
167
168 for (i = 0; i < evlist->nr_mmaps; i++) {
169 union perf_event *event;
170
171 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
172 const u32 type = event->header.type;
173 struct syscall *sc;
174 struct perf_sample sample;
175 int id;
176
177 ++nr_events;
178
179 switch (type) {
180 case PERF_RECORD_SAMPLE:
181 break;
182 case PERF_RECORD_LOST:
183 printf("LOST %" PRIu64 " events!\n", event->lost.lost);
184 continue;
185 default:
186 printf("Unexpected %s event, skipping...\n",
187 perf_event__name(type));
188 continue;
189 }
190
191 err = perf_evlist__parse_sample(evlist, event, &sample);
192 if (err) {
193 printf("Can't parse sample, err = %d, skipping...\n", err);
194 continue;
195 }
196
197 evsel = perf_evlist__id2evsel(evlist, sample.id);
198 if (evsel == NULL) {
199 printf("Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
200 continue;
201 }
202
203 id = perf_evsel__intval(evsel, &sample, "id");
204 if (id < 0) {
205 printf("Invalid syscall %d id, skipping...\n", id);
206 continue;
207 }
208
209 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL) &&
210 trace__read_syscall_info(trace, id))
211 continue;
212
213 if ((id > trace->syscalls.max || trace->syscalls.table[id].name == NULL))
214 continue;
215
216 sc = &trace->syscalls.table[id];
217
218 if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
219 printf("%d ", sample.tid);
220
221 if (evsel == evsel_enter) {
222 void *args = perf_evsel__rawptr(evsel, &sample, "args");
223
224 printf("%s(", sc->name);
225 syscall__fprintf_args(sc, args, stdout);
226 } else if (evsel == evsel_exit) {
227 int ret = perf_evsel__intval(evsel, &sample, "ret");
228
229 if (ret < 0 && sc->fmt && sc->fmt->errmsg) {
230 char bf[256];
231 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
232 *e = audit_errno_to_name(-ret);
233
234 printf(") = -1 %s %s", e, emsg);
235 } else if (ret == 0 && sc->fmt && sc->fmt->timeout)
236 printf(") = 0 Timeout");
237 else
238 printf(") = %d", ret);
239
240 putchar('\n');
241 }
242 }
243 }
244
245 if (nr_events == before)
246 poll(evlist->pollfd, evlist->nr_fds, -1);
247
248 goto again;
249
250out_delete_evlist:
251 perf_evlist__delete(evlist);
252out:
253 return err;
254}
255
256int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
257{
258 const char * const trace_usage[] = {
259 "perf trace [<options>]",
260 NULL
261 };
262 struct trace trace = {
263 .audit_machine = audit_detect_machine(),
264 .syscalls = {
265 . max = -1,
266 },
267 .opts = {
268 .target = {
269 .uid = UINT_MAX,
270 .uses_mmap = true,
271 },
272 .user_freq = UINT_MAX,
273 .user_interval = ULLONG_MAX,
274 .no_delay = true,
275 .mmap_pages = 1024,
276 },
277 };
278 const struct option trace_options[] = {
279 OPT_STRING('p', "pid", &trace.opts.target.pid, "pid",
280 "trace events on existing process id"),
281 OPT_STRING(0, "tid", &trace.opts.target.tid, "tid",
282 "trace events on existing thread id"),
283 OPT_BOOLEAN(0, "all-cpus", &trace.opts.target.system_wide,
284 "system-wide collection from all CPUs"),
285 OPT_STRING(0, "cpu", &trace.opts.target.cpu_list, "cpu",
286 "list of cpus to monitor"),
287 OPT_BOOLEAN(0, "no-inherit", &trace.opts.no_inherit,
288 "child tasks do not inherit counters"),
289 OPT_UINTEGER(0, "mmap-pages", &trace.opts.mmap_pages,
290 "number of mmap data pages"),
291 OPT_STRING(0, "uid", &trace.opts.target.uid_str, "user",
292 "user to profile"),
293 OPT_END()
294 };
295 int err;
296
297 argc = parse_options(argc, argv, trace_options, trace_usage, 0);
298 if (argc)
299 usage_with_options(trace_usage, trace_options);
300
301 err = perf_target__parse_uid(&trace.opts.target);
302 if (err) {
303 char bf[BUFSIZ];
304 perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
305 printf("%s", bf);
306 return err;
307 }
308
309 return trace__run(&trace);
310}
tools/perf/builtin.h+1−0
@@ -34,6 +34,7 @@ extern int cmd_kmem(int argc, const char **argv, const char *prefix); · 33 unmodified lines
34extern int cmd_lock(int argc, const char **argv, const char *prefix);34extern int cmd_lock(int argc, const char **argv, const char *prefix);
35extern int cmd_kvm(int argc, const char **argv, const char *prefix);35extern int cmd_kvm(int argc, const char **argv, const char *prefix);
36extern int cmd_test(int argc, const char **argv, const char *prefix);36extern int cmd_test(int argc, const char **argv, const char *prefix);
37extern int cmd_trace(int argc, const char **argv, const char *prefix);
37extern int cmd_inject(int argc, const char **argv, const char *prefix);38extern int cmd_inject(int argc, const char **argv, const char *prefix);
38 39
39extern int find_scripts(char **scripts_array, char **scripts_path_array);40extern int find_scripts(char **scripts_array, char **scripts_path_array);
tools/perf/command-list.txt+1−0
@@ -17,6 +17,7 @@ perf-report mainporcelain common · 16 unmodified lines
17perf-stat mainporcelain common17perf-stat mainporcelain common
18perf-timechart mainporcelain common18perf-timechart mainporcelain common
19perf-top mainporcelain common19perf-top mainporcelain common
20perf-trace mainporcelain common
20perf-script mainporcelain common21perf-script mainporcelain common
21perf-probe mainporcelain full22perf-probe mainporcelain full
22perf-kmem mainporcelain common23perf-kmem mainporcelain common
tools/perf/config/feature-tests.mak+11−0
@@ -193,3 +193,14 @@ int main(void) · 192 unmodified lines
193}193}
194endef194endef
195endif195endif
196
197ifndef NO_LIBAUDIT
198define SOURCE_LIBAUDIT
199#include <libaudit.h>
200
201int main(void)
202{
203 return audit_open();
204}
205endef
206endif
tools/perf/perf.c+3−0
@@ -55,6 +55,9 @@ static struct cmd_struct commands[] = { · 54 unmodified lines
55 { "lock", cmd_lock, 0 },55 { "lock", cmd_lock, 0 },
56 { "kvm", cmd_kvm, 0 },56 { "kvm", cmd_kvm, 0 },
57 { "test", cmd_test, 0 },57 { "test", cmd_test, 0 },
58#ifndef NO_LIBAUDIT_SUPPORT
59 { "trace", cmd_trace, 0 },
60#endif
58 { "inject", cmd_inject, 0 },61 { "inject", cmd_inject, 0 },
59};62};
60 63
tools/perf/util/cpumap.h+11−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2#define __PERF_CPUMAP_H2#define __PERF_CPUMAP_H
3 3
4#include <stdio.h>4#include <stdio.h>
5#include <stdbool.h>
5 6
6struct cpu_map {7struct cpu_map {
7 int nr;8 int nr;
@@ -14,4 +15,14 @@ void cpu_map__delete(struct cpu_map *map); · 6 unmodified lines
14struct cpu_map *cpu_map__read(FILE *file);15struct cpu_map *cpu_map__read(FILE *file);
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);16size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16 17
18static inline int cpu_map__nr(const struct cpu_map *map)
19{
20 return map ? map->nr : 1;
21}
22
23static inline bool cpu_map__all(const struct cpu_map *map)
24{
25 return map ? map->map[0] == -1 : true;
26}
27
17#endif /* __PERF_CPUMAP_H */28#endif /* __PERF_CPUMAP_H */
tools/perf/util/dwarf-aux.c+2−0
@@ -804,6 +804,8 @@ int die_get_typename(Dwarf_Die *vr_die, char *buf, int len) · 803 unmodified lines
804 tmp = "union ";804 tmp = "union ";
805 else if (tag == DW_TAG_structure_type)805 else if (tag == DW_TAG_structure_type)
806 tmp = "struct ";806 tmp = "struct ";
807 else if (tag == DW_TAG_enumeration_type)
808 tmp = "enum ";
807 /* Write a base name */809 /* Write a base name */
808 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));810 ret = snprintf(buf, len, "%s%s", tmp, dwarf_diename(&type));
809 return (ret >= len) ? -E2BIG : ret;811 return (ret >= len) ? -E2BIG : ret;
tools/perf/util/evlist.c+34−27
@@ -304,7 +304,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) · 303 unmodified lines
304 int cpu, thread;304 int cpu, thread;
305 struct perf_evsel *pos;305 struct perf_evsel *pos;
306 306
307 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {307 for (cpu = 0; cpu < cpu_map__nr(evlist->cpus); cpu++) {
308 list_for_each_entry(pos, &evlist->entries, node) {308 list_for_each_entry(pos, &evlist->entries, node) {
309 for (thread = 0; thread < evlist->threads->nr; thread++)309 for (thread = 0; thread < evlist->threads->nr; thread++)
310 ioctl(FD(pos, cpu, thread),310 ioctl(FD(pos, cpu, thread),
@@ -315,7 +315,7 @@ void perf_evlist__enable(struct perf_evlist *evlist) · 4 unmodified lines
315 315
316static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)316static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
317{317{
318 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;318 int nfds = cpu_map__nr(evlist->cpus) * evlist->threads->nr * evlist->nr_entries;
319 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);319 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
320 return evlist->pollfd != NULL ? 0 : -ENOMEM;320 return evlist->pollfd != NULL ? 0 : -ENOMEM;
321}321}
@@ -475,8 +475,8 @@ void perf_evlist__munmap(struct perf_evlist *evlist) · 153 unmodified lines
475 475
476static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)476static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
477{477{
478 evlist->nr_mmaps = evlist->cpus->nr;478 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
479 if (evlist->cpus->map[0] == -1)479 if (cpu_map__all(evlist->cpus))
480 evlist->nr_mmaps = evlist->threads->nr;480 evlist->nr_mmaps = evlist->threads->nr;
481 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));481 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
482 return evlist->mmap != NULL ? 0 : -ENOMEM;482 return evlist->mmap != NULL ? 0 : -ENOMEM;
@@ -622,11 +622,11 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, · 139 unmodified lines
622 list_for_each_entry(evsel, &evlist->entries, node) {622 list_for_each_entry(evsel, &evlist->entries, node) {
623 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&623 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
624 evsel->sample_id == NULL &&624 evsel->sample_id == NULL &&
625 perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0)625 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
626 return -ENOMEM;626 return -ENOMEM;
627 }627 }
628 628
629 if (evlist->cpus->map[0] == -1)629 if (cpu_map__all(cpus))
630 return perf_evlist__mmap_per_thread(evlist, prot, mask);630 return perf_evlist__mmap_per_thread(evlist, prot, mask);
631 631
632 return perf_evlist__mmap_per_cpu(evlist, prot, mask);632 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
@@ -666,32 +666,39 @@ void perf_evlist__delete_maps(struct perf_evlist *evlist) · 33 unmodified lines
666 evlist->threads = NULL;666 evlist->threads = NULL;
667}667}
668 668
669int perf_evlist__set_filters(struct perf_evlist *evlist)669int perf_evlist__apply_filters(struct perf_evlist *evlist)
670{670{
671 const struct thread_map *threads = evlist->threads;
672 const struct cpu_map *cpus = evlist->cpus;
673 struct perf_evsel *evsel;671 struct perf_evsel *evsel;
674 char *filter;672 int err = 0;
675 int thread;673 const int ncpus = cpu_map__nr(evlist->cpus),
676 int cpu;674 nthreads = evlist->threads->nr;
677 int err;
678 int fd;
679 675
680 list_for_each_entry(evsel, &evlist->entries, node) {676 list_for_each_entry(evsel, &evlist->entries, node) {
681 filter = evsel->filter;677 if (evsel->filter == NULL)
682 if (!filter)
683 continue;678 continue;
684 for (cpu = 0; cpu < cpus->nr; cpu++) {679
685 for (thread = 0; thread < threads->nr; thread++) {680 err = perf_evsel__set_filter(evsel, ncpus, nthreads, evsel->filter);
686 fd = FD(evsel, cpu, thread);681 if (err)
687 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);682 break;
688 if (err)
689 return err;
690 }
691 }
692 }683 }
693 684
694 return 0;685 return err;
686}
687
688int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
689{
690 struct perf_evsel *evsel;
691 int err = 0;
692 const int ncpus = cpu_map__nr(evlist->cpus),
693 nthreads = evlist->threads->nr;
694
695 list_for_each_entry(evsel, &evlist->entries, node) {
696 err = perf_evsel__set_filter(evsel, ncpus, nthreads, filter);
697 if (err)
698 break;
699 }
700
701 return err;
695}702}
696 703
697bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)704bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
@@ -884,10 +891,10 @@ int perf_evlist__start_workload(struct perf_evlist *evlist) · 186 unmodified lines
884}891}
885 892
886int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,893int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
887 struct perf_sample *sample, bool swapped)894 struct perf_sample *sample)
888{895{
889 struct perf_evsel *evsel = perf_evlist__first(evlist);896 struct perf_evsel *evsel = perf_evlist__first(evlist);
890 return perf_evsel__parse_sample(evsel, event, sample, swapped);897 return perf_evsel__parse_sample(evsel, event, sample);
891}898}
892 899
893size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)900size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
tools/perf/util/evlist.h+4−2
@@ -72,6 +72,8 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, · 71 unmodified lines
72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \72#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))73 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
74 74
75int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
76
75struct perf_evsel *77struct perf_evsel *
76perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);78perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
77 79
@@ -115,7 +117,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist, · 37 unmodified lines
115int perf_evlist__create_maps(struct perf_evlist *evlist,117int perf_evlist__create_maps(struct perf_evlist *evlist,
116 struct perf_target *target);118 struct perf_target *target);
117void perf_evlist__delete_maps(struct perf_evlist *evlist);119void perf_evlist__delete_maps(struct perf_evlist *evlist);
118int perf_evlist__set_filters(struct perf_evlist *evlist);120int perf_evlist__apply_filters(struct perf_evlist *evlist);
119 121
120void __perf_evlist__set_leader(struct list_head *list);122void __perf_evlist__set_leader(struct list_head *list);
121void perf_evlist__set_leader(struct perf_evlist *evlist);123void perf_evlist__set_leader(struct perf_evlist *evlist);
@@ -125,7 +127,7 @@ bool perf_evlist__sample_id_all(struct perf_evlist *evlist); · 3 unmodified lines
125u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);127u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
126 128
127int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,129int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
128 struct perf_sample *sample, bool swapped);130 struct perf_sample *sample);
129 131
130bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);132bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
131bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);133bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
tools/perf/util/evsel.c+72−16
@@ -70,7 +70,7 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) · 69 unmodified lines
70 return evsel;70 return evsel;
71}71}
72 72
73static struct event_format *event_format__new(const char *sys, const char *name)73struct event_format *event_format__new(const char *sys, const char *name)
74{74{
75 int fd, n;75 int fd, n;
76 char *filename;76 char *filename;
@@ -117,21 +117,28 @@ struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx) · 40 unmodified lines
117 117
118 if (evsel != NULL) {118 if (evsel != NULL) {
119 struct perf_event_attr attr = {119 struct perf_event_attr attr = {
120 .type = PERF_TYPE_TRACEPOINT,120 .type = PERF_TYPE_TRACEPOINT,
121 .sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
122 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
121 };123 };
122 124
125 if (asprintf(&evsel->name, "%s:%s", sys, name) < 0)
126 goto out_free;
127
123 evsel->tp_format = event_format__new(sys, name);128 evsel->tp_format = event_format__new(sys, name);
124 if (evsel->tp_format == NULL)129 if (evsel->tp_format == NULL)
125 goto out_free;130 goto out_free;
126 131
132 event_attr_init(&attr);
127 attr.config = evsel->tp_format->id;133 attr.config = evsel->tp_format->id;
134 attr.sample_period = 1;
128 perf_evsel__init(evsel, &attr, idx);135 perf_evsel__init(evsel, &attr, idx);
129 evsel->name = evsel->tp_format->name;
130 }136 }
131 137
132 return evsel;138 return evsel;
133 139
134out_free:140out_free:
141 free(evsel->name);
135 free(evsel);142 free(evsel);
136 return NULL;143 return NULL;
137}144}
@@ -501,6 +508,24 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) · 363 unmodified lines
501 return evsel->fd != NULL ? 0 : -ENOMEM;508 return evsel->fd != NULL ? 0 : -ENOMEM;
502}509}
503 510
511int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
512 const char *filter)
513{
514 int cpu, thread;
515
516 for (cpu = 0; cpu < ncpus; cpu++) {
517 for (thread = 0; thread < nthreads; thread++) {
518 int fd = FD(evsel, cpu, thread),
519 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
520
521 if (err)
522 return err;
523 }
524 }
525
526 return 0;
527}
528
504int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)529int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
505{530{
506 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));531 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
@@ -562,10 +587,8 @@ void perf_evsel__delete(struct perf_evsel *evsel) · 55 unmodified lines
562 perf_evsel__exit(evsel);587 perf_evsel__exit(evsel);
563 close_cgroup(evsel->cgrp);588 close_cgroup(evsel->cgrp);
564 free(evsel->group_name);589 free(evsel->group_name);
565 if (evsel->tp_format && evsel->name == evsel->tp_format->name) {590 if (evsel->tp_format)
566 evsel->name = NULL;
567 pevent_free_format(evsel->tp_format);591 pevent_free_format(evsel->tp_format);
568 }
569 free(evsel->name);592 free(evsel->name);
570 free(evsel);593 free(evsel);
571}594}
@@ -763,11 +786,13 @@ int perf_evsel__open_per_thread(struct perf_evsel *evsel, · 191 unmodified lines
763 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);786 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
764}787}
765 788
766static int perf_event__parse_id_sample(const union perf_event *event, u64 type,789static int perf_evsel__parse_id_sample(const struct perf_evsel *evsel,
767 struct perf_sample *sample,790 const union perf_event *event,
768 bool swapped)791 struct perf_sample *sample)
769{792{
793 u64 type = evsel->attr.sample_type;
770 const u64 *array = event->sample.array;794 const u64 *array = event->sample.array;
795 bool swapped = evsel->needs_swap;
771 union u64_swap u;796 union u64_swap u;
772 797
773 array += ((event->header.size -798 array += ((event->header.size -
@@ -828,10 +853,11 @@ static bool sample_overlap(const union perf_event *event, · 54 unmodified lines
828}853}
829 854
830int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,855int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
831 struct perf_sample *data, bool swapped)856 struct perf_sample *data)
832{857{
833 u64 type = evsel->attr.sample_type;858 u64 type = evsel->attr.sample_type;
834 u64 regs_user = evsel->attr.sample_regs_user;859 u64 regs_user = evsel->attr.sample_regs_user;
860 bool swapped = evsel->needs_swap;
835 const u64 *array;861 const u64 *array;
836 862
837 /*863 /*
@@ -848,7 +874,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, · 10 unmodified lines
848 if (event->header.type != PERF_RECORD_SAMPLE) {874 if (event->header.type != PERF_RECORD_SAMPLE) {
849 if (!evsel->attr.sample_id_all)875 if (!evsel->attr.sample_id_all)
850 return 0;876 return 0;
851 return perf_event__parse_id_sample(event, type, data, swapped);877 return perf_evsel__parse_id_sample(evsel, event, data);
852 }878 }
853 879
854 array = event->sample.array;880 array = event->sample.array;
@@ -1078,7 +1104,7 @@ struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *nam · 223 unmodified lines
1078 return pevent_find_field(evsel->tp_format, name);1104 return pevent_find_field(evsel->tp_format, name);
1079}1105}
1080 1106
1081char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,1107void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
1082 const char *name)1108 const char *name)
1083{1109{
1084 struct format_field *field = perf_evsel__field(evsel, name);1110 struct format_field *field = perf_evsel__field(evsel, name);
@@ -1101,13 +1127,43 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, · 16 unmodified lines
1101 const char *name)1127 const char *name)
1102{1128{
1103 struct format_field *field = perf_evsel__field(evsel, name);1129 struct format_field *field = perf_evsel__field(evsel, name);
1104 u64 val;1130 void *ptr;
1131 u64 value;
1105 1132
1106 if (!field)1133 if (!field)
1107 return 0;1134 return 0;
1108 1135
1109 val = pevent_read_number(evsel->tp_format->pevent,1136 ptr = sample->raw_data + field->offset;
1110 sample->raw_data + field->offset, field->size);
1111 return val;
1112 1137
1138 switch (field->size) {
1139 case 1:
1140 return *(u8 *)ptr;
1141 case 2:
1142 value = *(u16 *)ptr;
1143 break;
1144 case 4:
1145 value = *(u32 *)ptr;
1146 break;
1147 case 8:
1148 value = *(u64 *)ptr;
1149 break;
1150 default:
1151 return 0;
1152 }
1153
1154 if (!evsel->needs_swap)
1155 return value;
1156
1157 switch (field->size) {
1158 case 2:
1159 return bswap_16(value);
1160 case 4:
1161 return bswap_32(value);
1162 case 8:
1163 return bswap_64(value);
1164 default:
1165 return 0;
1166 }
1167
1168 return 0;
1113}1169}
tools/perf/util/evsel.h+16−2
@@ -69,6 +69,7 @@ struct perf_evsel { · 68 unmodified lines
69 struct cpu_map *cpus;69 struct cpu_map *cpus;
70 unsigned int sample_size;70 unsigned int sample_size;
71 bool supported;71 bool supported;
72 bool needs_swap;
72 /* parse modifier helper */73 /* parse modifier helper */
73 int exclude_GH;74 int exclude_GH;
74 struct perf_evsel *leader;75 struct perf_evsel *leader;
@@ -82,6 +83,9 @@ struct perf_record_opts; · 7 unmodified lines
82 83
83struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);84struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
84struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx);85struct perf_evsel *perf_evsel__newtp(const char *sys, const char *name, int idx);
86
87struct event_format *event_format__new(const char *sys, const char *name);
88
85void perf_evsel__init(struct perf_evsel *evsel,89void perf_evsel__init(struct perf_evsel *evsel,
86 struct perf_event_attr *attr, int idx);90 struct perf_event_attr *attr, int idx);
87void perf_evsel__exit(struct perf_evsel *evsel);91void perf_evsel__exit(struct perf_evsel *evsel);
@@ -114,6 +118,9 @@ void perf_evsel__free_fd(struct perf_evsel *evsel); · 26 unmodified lines
114void perf_evsel__free_id(struct perf_evsel *evsel);118void perf_evsel__free_id(struct perf_evsel *evsel);
115void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);119void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
116 120
121int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
122 const char *filter);
123
117int perf_evsel__open_per_cpu(struct perf_evsel *evsel,124int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
118 struct cpu_map *cpus);125 struct cpu_map *cpus);
119int perf_evsel__open_per_thread(struct perf_evsel *evsel,126int perf_evsel__open_per_thread(struct perf_evsel *evsel,
@@ -124,11 +131,18 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); · 4 unmodified lines
124 131
125struct perf_sample;132struct perf_sample;
126 133
127char *perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample,134void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
128 const char *name);135 const char *name);
129u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,136u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
130 const char *name);137 const char *name);
131 138
139static inline char *perf_evsel__strval(struct perf_evsel *evsel,
140 struct perf_sample *sample,
141 const char *name)
142{
143 return perf_evsel__rawptr(evsel, sample, name);
144}
145
132struct format_field;146struct format_field;
133 147
134struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);148struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
@@ -205,7 +219,7 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, · 70 unmodified lines
205void hists__init(struct hists *hists);219void hists__init(struct hists *hists);
206 220
207int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,221int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
208 struct perf_sample *sample, bool swapped);222 struct perf_sample *sample);
209 223
210static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)224static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
211{225{
tools/perf/util/header.c+5−1
@@ -1256,8 +1256,10 @@ read_event_desc(struct perf_header *ph, int fd) · 1255 unmodified lines
1256 if (ret != (ssize_t)sizeof(nr))1256 if (ret != (ssize_t)sizeof(nr))
1257 goto error;1257 goto error;
1258 1258
1259 if (ph->needs_swap)1259 if (ph->needs_swap) {
1260 nr = bswap_32(nr);1260 nr = bswap_32(nr);
1261 evsel->needs_swap = true;
1262 }
1261 1263
1262 evsel->name = do_read_string(fd, ph);1264 evsel->name = do_read_string(fd, ph);
1263 1265
@@ -2626,6 +2628,8 @@ int perf_session__read_header(struct perf_session *session, int fd) · 1362 unmodified lines
2626 2628
2627 if (evsel == NULL)2629 if (evsel == NULL)
2628 goto out_delete_evlist;2630 goto out_delete_evlist;
2631
2632 evsel->needs_swap = header->needs_swap;
2629 /*2633 /*
2630 * Do it before so that if perf_evsel__alloc_id fails, this2634 * Do it before so that if perf_evsel__alloc_id fails, this
2631 * entry gets purged too at perf_evlist__delete().2635 * entry gets purged too at perf_evlist__delete().
tools/perf/util/hist.c+7−2
@@ -410,8 +410,13 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, · 409 unmodified lines
410 cmp = hist_entry__collapse(iter, he);410 cmp = hist_entry__collapse(iter, he);
411 411
412 if (!cmp) {412 if (!cmp) {
413 iter->period += he->period;413 iter->period += he->period;
414 iter->nr_events += he->nr_events;414 iter->period_sys += he->period_sys;
415 iter->period_us += he->period_us;
416 iter->period_guest_sys += he->period_guest_sys;
417 iter->period_guest_us += he->period_guest_us;
418 iter->nr_events += he->nr_events;
419
415 if (symbol_conf.use_callchain) {420 if (symbol_conf.use_callchain) {
416 callchain_cursor_reset(&callchain_cursor);421 callchain_cursor_reset(&callchain_cursor);
417 callchain_merge(&callchain_cursor,422 callchain_merge(&callchain_cursor,
tools/perf/util/parse-events.c+16−30
@@ -356,42 +356,28 @@ int parse_events_add_cache(struct list_head **list, int *idx, · 355 unmodified lines
356 return add_event(list, idx, &attr, name);356 return add_event(list, idx, &attr, name);
357}357}
358 358
359static int add_tracepoint(struct list_head **list, int *idx,359static int add_tracepoint(struct list_head **listp, int *idx,
360 char *sys_name, char *evt_name)360 char *sys_name, char *evt_name)
361{361{
362 struct perf_event_attr attr;362 struct perf_evsel *evsel;
363 char name[MAX_NAME_LEN];363 struct list_head *list = *listp;
364 char evt_path[MAXPATHLEN];
365 char id_buf[4];
366 u64 id;
367 int fd;
368
369 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
370 sys_name, evt_name);
371
372 fd = open(evt_path, O_RDONLY);
373 if (fd < 0)
374 return -1;
375 364
376 if (read(fd, id_buf, sizeof(id_buf)) < 0) {365 if (!list) {
377 close(fd);366 list = malloc(sizeof(*list));
378 return -1;367 if (!list)
368 return -ENOMEM;
369 INIT_LIST_HEAD(list);
379 }370 }
380 371
381 close(fd);372 evsel = perf_evsel__newtp(sys_name, evt_name, (*idx)++);
382 id = atoll(id_buf);373 if (!evsel) {
383 374 free(list);
384 memset(&attr, 0, sizeof(attr));375 return -ENOMEM;
385 attr.config = id;376 }
386 attr.type = PERF_TYPE_TRACEPOINT;
387 attr.sample_type |= PERF_SAMPLE_RAW;
388 attr.sample_type |= PERF_SAMPLE_TIME;
389 attr.sample_type |= PERF_SAMPLE_CPU;
390 attr.sample_type |= PERF_SAMPLE_PERIOD;
391 attr.sample_period = 1;
392 377
393 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);378 list_add_tail(&evsel->node, list);
394 return add_event(list, idx, &attr, name);379 *listp = list;
380 return 0;
395}381}
396 382
397static int add_tracepoint_multi(struct list_head **list, int *idx,383static int add_tracepoint_multi(struct list_head **list, int *idx,
tools/perf/util/python.c+1−1
@@ -805,7 +805,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, · 804 unmodified lines
805 if (pyevent == NULL)805 if (pyevent == NULL)
806 return PyErr_NoMemory();806 return PyErr_NoMemory();
807 807
808 err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false);808 err = perf_evlist__parse_sample(evlist, event, &pevent->sample);
809 if (err)809 if (err)
810 return PyErr_Format(PyExc_OSError,810 return PyErr_Format(PyExc_OSError,
811 "perf: can't parse sample, err=%d", err);811 "perf: can't parse sample, err=%d", err);
tools/perf/util/session.c+2−4
@@ -722,8 +722,7 @@ static int flush_sample_queue(struct perf_session *s, · 721 unmodified lines
722 if (iter->timestamp > limit)722 if (iter->timestamp > limit)
723 break;723 break;
724 724
725 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample,725 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
726 s->header.needs_swap);
727 if (ret)726 if (ret)
728 pr_err("Can't parse sample, err = %d\n", ret);727 pr_err("Can't parse sample, err = %d\n", ret);
729 else {728 else {
@@ -1174,8 +1173,7 @@ static int perf_session__process_event(struct perf_session *session, · 444 unmodified lines
1174 /*1173 /*
1175 * For all kernel events we get the sample data1174 * For all kernel events we get the sample data
1176 */1175 */
1177 ret = perf_evlist__parse_sample(session->evlist, event, &sample,1176 ret = perf_evlist__parse_sample(session->evlist, event, &sample);
1178 session->header.needs_swap);
1179 if (ret)1177 if (ret)
1180 return ret;1178 return ret;
1181 1179