diff options
author | Ingo Molnar <mingo@kernel.org> | 2013-09-06 08:08:08 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2013-09-06 08:08:08 -0400 |
commit | 72f4a11d2fb16792f5e5107922652366194cfd66 (patch) | |
tree | 44429da06dafd36090000092e02be2e9cc0b4f44 /tools | |
parent | 816434ec4a674fcdb3c2221a6dffdc8f34020550 (diff) | |
parent | 526fd8d4f770d18e99680ff87965e16bb8f1d806 (diff) |
Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/urgent fixes from Arnaldo Carvalho de Melo:
* Fix parsing with no sample_id_all bit set, this regression prevents perf
from reading old perf.data files generated in systems where
perf_event_attr.sample_id_all isn't available, from Adrian Hunter.
* Add signal checking to the inner 'perf trace' event processing loop, allowing
faster response to control+C.
* Fix formatting of long symbol names removing the hardcoding of a buffer
size used to format histogram entries, which was truncating the lines.
* Separate progress bar update when processing events, reducing potentially big
overhead in not needed TUI progress bar screen updates, from Jiri Olsa.
* Fix 'perf trace' build in architectures where MAP_32BIT is not defined, from
Kyle McMartin.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Makefile | 3 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 5 | ||||
-rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/parse-no-sample-id-all.c | 108 | ||||
-rw-r--r-- | tools/perf/tests/tests.h | 1 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 23 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 9 | ||||
-rw-r--r-- | tools/perf/util/session.c | 3 |
8 files changed, 146 insertions, 10 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c5dc1ad1b8d7..3a0ff7fb71b6 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -394,6 +394,8 @@ ifeq ($(ARCH),x86) | |||
394 | LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o | 394 | LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o |
395 | endif | 395 | endif |
396 | LIB_OBJS += $(OUTPUT)tests/code-reading.o | 396 | LIB_OBJS += $(OUTPUT)tests/code-reading.o |
397 | LIB_OBJS += $(OUTPUT)tests/sample-parsing.o | ||
398 | LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o | ||
397 | 399 | ||
398 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o | 400 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o |
399 | BUILTIN_OBJS += $(OUTPUT)builtin-bench.o | 401 | BUILTIN_OBJS += $(OUTPUT)builtin-bench.o |
@@ -439,7 +441,6 @@ PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT) | |||
439 | ifneq ($(OUTPUT),) | 441 | ifneq ($(OUTPUT),) |
440 | CFLAGS += -I$(OUTPUT) | 442 | CFLAGS += -I$(OUTPUT) |
441 | endif | 443 | endif |
442 | LIB_OBJS += $(OUTPUT)tests/sample-parsing.o | ||
443 | 444 | ||
444 | ifdef NO_LIBELF | 445 | ifdef NO_LIBELF |
445 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) | 446 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b6f0725068bd..f5aa6375e3e9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -100,7 +100,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, | |||
100 | 100 | ||
101 | P_MMAP_FLAG(SHARED); | 101 | P_MMAP_FLAG(SHARED); |
102 | P_MMAP_FLAG(PRIVATE); | 102 | P_MMAP_FLAG(PRIVATE); |
103 | #ifdef MAP_32BIT | ||
103 | P_MMAP_FLAG(32BIT); | 104 | P_MMAP_FLAG(32BIT); |
105 | #endif | ||
104 | P_MMAP_FLAG(ANONYMOUS); | 106 | P_MMAP_FLAG(ANONYMOUS); |
105 | P_MMAP_FLAG(DENYWRITE); | 107 | P_MMAP_FLAG(DENYWRITE); |
106 | P_MMAP_FLAG(EXECUTABLE); | 108 | P_MMAP_FLAG(EXECUTABLE); |
@@ -994,6 +996,9 @@ again: | |||
994 | 996 | ||
995 | handler = evsel->handler.func; | 997 | handler = evsel->handler.func; |
996 | handler(trace, evsel, &sample); | 998 | handler(trace, evsel, &sample); |
999 | |||
1000 | if (done) | ||
1001 | goto out_unmap_evlist; | ||
997 | } | 1002 | } |
998 | } | 1003 | } |
999 | 1004 | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 8bbeba322df9..1e67437fb4ca 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -112,6 +112,10 @@ static struct test { | |||
112 | .func = test__keep_tracking, | 112 | .func = test__keep_tracking, |
113 | }, | 113 | }, |
114 | { | 114 | { |
115 | .desc = "Test parsing with no sample_id_all bit set", | ||
116 | .func = test__parse_no_sample_id_all, | ||
117 | }, | ||
118 | { | ||
115 | .func = NULL, | 119 | .func = NULL, |
116 | }, | 120 | }, |
117 | }; | 121 | }; |
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c new file mode 100644 index 000000000000..e117b6c6a248 --- /dev/null +++ b/tools/perf/tests/parse-no-sample-id-all.c | |||
@@ -0,0 +1,108 @@ | |||
1 | #include <sys/types.h> | ||
2 | #include <stddef.h> | ||
3 | |||
4 | #include "tests.h" | ||
5 | |||
6 | #include "event.h" | ||
7 | #include "evlist.h" | ||
8 | #include "header.h" | ||
9 | #include "util.h" | ||
10 | |||
11 | static int process_event(struct perf_evlist **pevlist, union perf_event *event) | ||
12 | { | ||
13 | struct perf_sample sample; | ||
14 | |||
15 | if (event->header.type == PERF_RECORD_HEADER_ATTR) { | ||
16 | if (perf_event__process_attr(NULL, event, pevlist)) { | ||
17 | pr_debug("perf_event__process_attr failed\n"); | ||
18 | return -1; | ||
19 | } | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | if (event->header.type >= PERF_RECORD_USER_TYPE_START) | ||
24 | return -1; | ||
25 | |||
26 | if (!*pevlist) | ||
27 | return -1; | ||
28 | |||
29 | if (perf_evlist__parse_sample(*pevlist, event, &sample)) { | ||
30 | pr_debug("perf_evlist__parse_sample failed\n"); | ||
31 | return -1; | ||
32 | } | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int process_events(union perf_event **events, size_t count) | ||
38 | { | ||
39 | struct perf_evlist *evlist = NULL; | ||
40 | int err = 0; | ||
41 | size_t i; | ||
42 | |||
43 | for (i = 0; i < count && !err; i++) | ||
44 | err = process_event(&evlist, events[i]); | ||
45 | |||
46 | if (evlist) | ||
47 | perf_evlist__delete(evlist); | ||
48 | |||
49 | return err; | ||
50 | } | ||
51 | |||
52 | struct test_attr_event { | ||
53 | struct attr_event attr; | ||
54 | u64 id; | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * test__parse_no_sample_id_all - test parsing with no sample_id_all bit set. | ||
59 | * | ||
60 | * This function tests parsing data produced on kernel's that do not support the | ||
61 | * sample_id_all bit. Without the sample_id_all bit, non-sample events (such as | ||
62 | * mmap events) do not have an id sample appended, and consequently logic | ||
63 | * designed to determine the id will not work. That case happens when there is | ||
64 | * more than one selected event, so this test processes three events: 2 | ||
65 | * attributes representing the selected events and one mmap event. | ||
66 | * | ||
67 | * Return: %0 on success, %-1 if the test fails. | ||
68 | */ | ||
69 | int test__parse_no_sample_id_all(void) | ||
70 | { | ||
71 | int err; | ||
72 | |||
73 | struct test_attr_event event1 = { | ||
74 | .attr = { | ||
75 | .header = { | ||
76 | .type = PERF_RECORD_HEADER_ATTR, | ||
77 | .size = sizeof(struct test_attr_event), | ||
78 | }, | ||
79 | }, | ||
80 | .id = 1, | ||
81 | }; | ||
82 | struct test_attr_event event2 = { | ||
83 | .attr = { | ||
84 | .header = { | ||
85 | .type = PERF_RECORD_HEADER_ATTR, | ||
86 | .size = sizeof(struct test_attr_event), | ||
87 | }, | ||
88 | }, | ||
89 | .id = 2, | ||
90 | }; | ||
91 | struct mmap_event event3 = { | ||
92 | .header = { | ||
93 | .type = PERF_RECORD_MMAP, | ||
94 | .size = sizeof(struct mmap_event), | ||
95 | }, | ||
96 | }; | ||
97 | union perf_event *events[] = { | ||
98 | (union perf_event *)&event1, | ||
99 | (union perf_event *)&event2, | ||
100 | (union perf_event *)&event3, | ||
101 | }; | ||
102 | |||
103 | err = process_events(events, ARRAY_SIZE(events)); | ||
104 | if (err) | ||
105 | return -1; | ||
106 | |||
107 | return 0; | ||
108 | } | ||
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index c048b589998a..e0ac713857ba 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -39,5 +39,6 @@ int test__perf_time_to_tsc(void); | |||
39 | int test__code_reading(void); | 39 | int test__code_reading(void); |
40 | int test__sample_parsing(void); | 40 | int test__sample_parsing(void); |
41 | int test__keep_tracking(void); | 41 | int test__keep_tracking(void); |
42 | int test__parse_no_sample_id_all(void); | ||
42 | 43 | ||
43 | #endif /* TESTS_H */ | 44 | #endif /* TESTS_H */ |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 5b4fb330f656..194e2f42ff5d 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -350,9 +350,9 @@ static int hist_entry__period_snprintf(struct perf_hpp *hpp, | |||
350 | } | 350 | } |
351 | 351 | ||
352 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, | 352 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, |
353 | struct hists *hists, FILE *fp) | 353 | struct hists *hists, |
354 | char *bf, size_t bfsz, FILE *fp) | ||
354 | { | 355 | { |
355 | char bf[512]; | ||
356 | int ret; | 356 | int ret; |
357 | struct perf_hpp hpp = { | 357 | struct perf_hpp hpp = { |
358 | .buf = bf, | 358 | .buf = bf, |
@@ -360,8 +360,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, | |||
360 | }; | 360 | }; |
361 | bool color = !symbol_conf.field_sep; | 361 | bool color = !symbol_conf.field_sep; |
362 | 362 | ||
363 | if (size == 0 || size > sizeof(bf)) | 363 | if (size == 0 || size > bfsz) |
364 | size = hpp.size = sizeof(bf); | 364 | size = hpp.size = bfsz; |
365 | 365 | ||
366 | ret = hist_entry__period_snprintf(&hpp, he, color); | 366 | ret = hist_entry__period_snprintf(&hpp, he, color); |
367 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); | 367 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); |
@@ -392,6 +392,8 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
392 | .ptr = hists_to_evsel(hists), | 392 | .ptr = hists_to_evsel(hists), |
393 | }; | 393 | }; |
394 | bool first = true; | 394 | bool first = true; |
395 | size_t linesz; | ||
396 | char *line = NULL; | ||
395 | 397 | ||
396 | init_rem_hits(); | 398 | init_rem_hits(); |
397 | 399 | ||
@@ -479,6 +481,13 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
479 | goto out; | 481 | goto out; |
480 | 482 | ||
481 | print_entries: | 483 | print_entries: |
484 | linesz = hists__sort_list_width(hists) + 3 + 1; | ||
485 | line = malloc(linesz); | ||
486 | if (line == NULL) { | ||
487 | ret = -1; | ||
488 | goto out; | ||
489 | } | ||
490 | |||
482 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 491 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
483 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 492 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
484 | float percent = h->stat.period * 100.0 / | 493 | float percent = h->stat.period * 100.0 / |
@@ -490,10 +499,10 @@ print_entries: | |||
490 | if (percent < min_pcnt) | 499 | if (percent < min_pcnt) |
491 | continue; | 500 | continue; |
492 | 501 | ||
493 | ret += hist_entry__fprintf(h, max_cols, hists, fp); | 502 | ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); |
494 | 503 | ||
495 | if (max_rows && ++nr_rows >= max_rows) | 504 | if (max_rows && ++nr_rows >= max_rows) |
496 | goto out; | 505 | break; |
497 | 506 | ||
498 | if (h->ms.map == NULL && verbose > 1) { | 507 | if (h->ms.map == NULL && verbose > 1) { |
499 | __map_groups__fprintf_maps(&h->thread->mg, | 508 | __map_groups__fprintf_maps(&h->thread->mg, |
@@ -501,6 +510,8 @@ print_entries: | |||
501 | fprintf(fp, "%.10s end\n", graph_dotted_line); | 510 | fprintf(fp, "%.10s end\n", graph_dotted_line); |
502 | } | 511 | } |
503 | } | 512 | } |
513 | |||
514 | free(line); | ||
504 | out: | 515 | out: |
505 | free(rem_sq_bracket); | 516 | free(rem_sq_bracket); |
506 | 517 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b8727ae45e3b..7101283ac3c5 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -446,20 +446,25 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, | |||
446 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | 446 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, |
447 | union perf_event *event) | 447 | union perf_event *event) |
448 | { | 448 | { |
449 | struct perf_evsel *first = perf_evlist__first(evlist); | ||
449 | struct hlist_head *head; | 450 | struct hlist_head *head; |
450 | struct perf_sample_id *sid; | 451 | struct perf_sample_id *sid; |
451 | int hash; | 452 | int hash; |
452 | u64 id; | 453 | u64 id; |
453 | 454 | ||
454 | if (evlist->nr_entries == 1) | 455 | if (evlist->nr_entries == 1) |
455 | return perf_evlist__first(evlist); | 456 | return first; |
457 | |||
458 | if (!first->attr.sample_id_all && | ||
459 | event->header.type != PERF_RECORD_SAMPLE) | ||
460 | return first; | ||
456 | 461 | ||
457 | if (perf_evlist__event2id(evlist, event, &id)) | 462 | if (perf_evlist__event2id(evlist, event, &id)) |
458 | return NULL; | 463 | return NULL; |
459 | 464 | ||
460 | /* Synthesized events have an id of zero */ | 465 | /* Synthesized events have an id of zero */ |
461 | if (!id) | 466 | if (!id) |
462 | return perf_evlist__first(evlist); | 467 | return first; |
463 | 468 | ||
464 | hash = hash_64(id, PERF_EVLIST__HLIST_BITS); | 469 | hash = hash_64(id, PERF_EVLIST__HLIST_BITS); |
465 | head = &evlist->heads[hash]; | 470 | head = &evlist->heads[hash]; |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1fc0c628683e..476caa129a20 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -504,6 +504,7 @@ static int flush_sample_queue(struct perf_session *s, | |||
504 | u64 limit = os->next_flush; | 504 | u64 limit = os->next_flush; |
505 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; | 505 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; |
506 | unsigned idx = 0, progress_next = os->nr_samples / 16; | 506 | unsigned idx = 0, progress_next = os->nr_samples / 16; |
507 | bool show_progress = limit == ULLONG_MAX; | ||
507 | int ret; | 508 | int ret; |
508 | 509 | ||
509 | if (!tool->ordered_samples || !limit) | 510 | if (!tool->ordered_samples || !limit) |
@@ -526,7 +527,7 @@ static int flush_sample_queue(struct perf_session *s, | |||
526 | os->last_flush = iter->timestamp; | 527 | os->last_flush = iter->timestamp; |
527 | list_del(&iter->list); | 528 | list_del(&iter->list); |
528 | list_add(&iter->list, &os->sample_cache); | 529 | list_add(&iter->list, &os->sample_cache); |
529 | if (++idx >= progress_next) { | 530 | if (show_progress && (++idx >= progress_next)) { |
530 | progress_next += os->nr_samples / 16; | 531 | progress_next += os->nr_samples / 16; |
531 | ui_progress__update(idx, os->nr_samples, | 532 | ui_progress__update(idx, os->nr_samples, |
532 | "Processing time ordered events..."); | 533 | "Processing time ordered events..."); |