aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2013-08-27 04:23:09 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-08-29 15:09:31 -0400
commit75562573bab35b129cfd342fc2bcf89da84a6644 (patch)
treeb7dfa219d1a73560ce95639b7291f377645497ba /tools/perf/util
parentfaf967068e8c4d8df52f01f9361241101b3065a0 (diff)
perf tools: Add support for PERF_SAMPLE_IDENTIFIER
Enable parsing of samples with sample format bit PERF_SAMPLE_IDENTIFIER. In addition, if the kernel supports it, prefer it to selecting PERF_SAMPLE_ID thereby allowing non-matching sample types. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> 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> Link: http://lkml.kernel.org/r/1377591794-30553-8-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/event.h3
-rw-r--r--tools/perf/util/evlist.c111
-rw-r--r--tools/perf/util/evlist.h8
-rw-r--r--tools/perf/util/evsel.c101
-rw-r--r--tools/perf/util/evsel.h14
-rw-r--r--tools/perf/util/record.c89
-rw-r--r--tools/perf/util/session.c2
7 files changed, 308 insertions, 20 deletions
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 19d911c011cd..491333910cf1 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -53,7 +53,8 @@ struct read_event {
53 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ 53 (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \
54 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ 54 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \
55 PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \ 55 PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \
56 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) 56 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \
57 PERF_SAMPLE_IDENTIFIER)
57 58
58struct sample_event { 59struct sample_event {
59 struct perf_event_header header; 60 struct perf_event_header header;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 9d682e5f7184..6a629af51376 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -49,6 +49,21 @@ struct perf_evlist *perf_evlist__new(void)
49 return evlist; 49 return evlist;
50} 50}
51 51
52/**
53 * perf_evlist__set_id_pos - set the positions of event ids.
54 * @evlist: selected event list
55 *
56 * Events with compatible sample types all have the same id_pos
57 * and is_pos. For convenience, put a copy on evlist.
58 */
59void perf_evlist__set_id_pos(struct perf_evlist *evlist)
60{
61 struct perf_evsel *first = perf_evlist__first(evlist);
62
63 evlist->id_pos = first->id_pos;
64 evlist->is_pos = first->is_pos;
65}
66
52static void perf_evlist__purge(struct perf_evlist *evlist) 67static void perf_evlist__purge(struct perf_evlist *evlist)
53{ 68{
54 struct perf_evsel *pos, *n; 69 struct perf_evsel *pos, *n;
@@ -79,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist)
79void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) 94void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
80{ 95{
81 list_add_tail(&entry->node, &evlist->entries); 96 list_add_tail(&entry->node, &evlist->entries);
82 ++evlist->nr_entries; 97 if (!evlist->nr_entries++)
98 perf_evlist__set_id_pos(evlist);
83} 99}
84 100
85void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 101void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
86 struct list_head *list, 102 struct list_head *list,
87 int nr_entries) 103 int nr_entries)
88{ 104{
105 bool set_id_pos = !evlist->nr_entries;
106
89 list_splice_tail(list, &evlist->entries); 107 list_splice_tail(list, &evlist->entries);
90 evlist->nr_entries += nr_entries; 108 evlist->nr_entries += nr_entries;
109 if (set_id_pos)
110 perf_evlist__set_id_pos(evlist);
91} 111}
92 112
93void __perf_evlist__set_leader(struct list_head *list) 113void __perf_evlist__set_leader(struct list_head *list)
@@ -349,6 +369,55 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
349 return NULL; 369 return NULL;
350} 370}
351 371
372static int perf_evlist__event2id(struct perf_evlist *evlist,
373 union perf_event *event, u64 *id)
374{
375 const u64 *array = event->sample.array;
376 ssize_t n;
377
378 n = (event->header.size - sizeof(event->header)) >> 3;
379
380 if (event->header.type == PERF_RECORD_SAMPLE) {
381 if (evlist->id_pos >= n)
382 return -1;
383 *id = array[evlist->id_pos];
384 } else {
385 if (evlist->is_pos > n)
386 return -1;
387 n -= evlist->is_pos;
388 *id = array[n];
389 }
390 return 0;
391}
392
393static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
394 union perf_event *event)
395{
396 struct hlist_head *head;
397 struct perf_sample_id *sid;
398 int hash;
399 u64 id;
400
401 if (evlist->nr_entries == 1)
402 return perf_evlist__first(evlist);
403
404 if (perf_evlist__event2id(evlist, event, &id))
405 return NULL;
406
407 /* Synthesized events have an id of zero */
408 if (!id)
409 return perf_evlist__first(evlist);
410
411 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
412 head = &evlist->heads[hash];
413
414 hlist_for_each_entry(sid, head, node) {
415 if (sid->id == id)
416 return sid->evsel;
417 }
418 return NULL;
419}
420
352union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 421union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
353{ 422{
354 struct perf_mmap *md = &evlist->mmap[idx]; 423 struct perf_mmap *md = &evlist->mmap[idx];
@@ -659,20 +728,40 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
659 728
660bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) 729bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
661{ 730{
662 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 731 struct perf_evsel *pos;
663 732
664 list_for_each_entry_continue(pos, &evlist->entries, node) { 733 if (evlist->nr_entries == 1)
665 if (first->attr.sample_type != pos->attr.sample_type) 734 return true;
735
736 if (evlist->id_pos < 0 || evlist->is_pos < 0)
737 return false;
738
739 list_for_each_entry(pos, &evlist->entries, node) {
740 if (pos->id_pos != evlist->id_pos ||
741 pos->is_pos != evlist->is_pos)
666 return false; 742 return false;
667 } 743 }
668 744
669 return true; 745 return true;
670} 746}
671 747
672u64 perf_evlist__sample_type(struct perf_evlist *evlist) 748u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
673{ 749{
674 struct perf_evsel *first = perf_evlist__first(evlist); 750 struct perf_evsel *evsel;
675 return first->attr.sample_type; 751
752 if (evlist->combined_sample_type)
753 return evlist->combined_sample_type;
754
755 list_for_each_entry(evsel, &evlist->entries, node)
756 evlist->combined_sample_type |= evsel->attr.sample_type;
757
758 return evlist->combined_sample_type;
759}
760
761u64 perf_evlist__combined_sample_type(struct perf_evlist *evlist)
762{
763 evlist->combined_sample_type = 0;
764 return __perf_evlist__combined_sample_type(evlist);
676} 765}
677 766
678bool perf_evlist__valid_read_format(struct perf_evlist *evlist) 767bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
@@ -727,6 +816,9 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
727 816
728 if (sample_type & PERF_SAMPLE_CPU) 817 if (sample_type & PERF_SAMPLE_CPU)
729 size += sizeof(data->cpu) * 2; 818 size += sizeof(data->cpu) * 2;
819