diff options
| author | Adrian Hunter <adrian.hunter@intel.com> | 2013-08-27 04:23:09 -0400 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-08-29 15:09:31 -0400 |
| commit | 75562573bab35b129cfd342fc2bcf89da84a6644 (patch) | |
| tree | b7dfa219d1a73560ce95639b7291f377645497ba /tools/perf/util | |
| parent | faf967068e8c4d8df52f01f9361241101b3065a0 (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.h | 3 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 111 | ||||
| -rw-r--r-- | tools/perf/util/evlist.h | 8 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 101 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 14 | ||||
| -rw-r--r-- | tools/perf/util/record.c | 89 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 2 |
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 | ||
| 58 | struct sample_event { | 59 | struct 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 | */ | ||
| 59 | void 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 | |||
| 52 | static void perf_evlist__purge(struct perf_evlist *evlist) | 67 | static 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) | |||
| 79 | void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) | 94 | void 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 | ||
| 85 | void perf_evlist__splice_list_tail(struct perf_evlist *evlist, | 101 | void 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 | ||
| 93 | void __perf_evlist__set_leader(struct list_head *list) | 113 | void __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 | ||
| 372 | static 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 | |||
| 393 | static 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 | |||
| 352 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | 421 | union 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 | ||
| 660 | bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) | 729 | bool 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 | ||
| 672 | u64 perf_evlist__sample_type(struct perf_evlist *evlist) | 748 | u64 __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 | |||
| 761 | u64 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 | ||
| 678 | bool perf_evlist__valid_read_format(struct perf_evlist *evlist) | 767 | bool 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 | |||
