aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-09-06 08:08:08 -0400
committerIngo Molnar <mingo@kernel.org>2013-09-06 08:08:08 -0400
commit72f4a11d2fb16792f5e5107922652366194cfd66 (patch)
tree44429da06dafd36090000092e02be2e9cc0b4f44 /tools
parent816434ec4a674fcdb3c2221a6dffdc8f34020550 (diff)
parent526fd8d4f770d18e99680ff87965e16bb8f1d806 (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/Makefile3
-rw-r--r--tools/perf/builtin-trace.c5
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c108
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/ui/stdio/hist.c23
-rw-r--r--tools/perf/util/evlist.c9
-rw-r--r--tools/perf/util/session.c3
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)
394LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o 394LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
395endif 395endif
396LIB_OBJS += $(OUTPUT)tests/code-reading.o 396LIB_OBJS += $(OUTPUT)tests/code-reading.o
397LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
398LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
397 399
398BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 400BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
399BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 401BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -439,7 +441,6 @@ PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
439ifneq ($(OUTPUT),) 441ifneq ($(OUTPUT),)
440 CFLAGS += -I$(OUTPUT) 442 CFLAGS += -I$(OUTPUT)
441endif 443endif
442LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
443 444
444ifdef NO_LIBELF 445ifdef NO_LIBELF
445EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) 446EXTLIBS := $(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
11static 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
37static 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
52struct 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 */
69int 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);
39int test__code_reading(void); 39int test__code_reading(void);
40int test__sample_parsing(void); 40int test__sample_parsing(void);
41int test__keep_tracking(void); 41int test__keep_tracking(void);
42int 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
352static int hist_entry__fprintf(struct hist_entry *he, size_t size, 352static 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
481print_entries: 483print_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);
504out: 515out:
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,
446static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 446static 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...");