[PATCH V13 07/12] perf tools: add support for PERF_SAMPLE_IDENTFIER
Enable parsing of samples with sample format bit PERF_SAMPLE_IDENTFIER. 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 --- tools/perf/builtin-report.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/util/event.h | 3 +- tools/perf/util/evlist.c | 111 +++--- tools/perf/util/evlist.h | 8 ++- tools/perf/util/evsel.c | 101 -- tools/perf/util/evsel.h | 14 +- tools/perf/util/record.c | 89 +++-- tools/perf/util/session.c | 2 +- 9 files changed, 310 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 958a56a..9725aa3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -365,7 +365,7 @@ static int process_read_event(struct perf_tool *tool, static int perf_report__setup_sample_type(struct perf_report *rep) { struct perf_session *self = rep->session; - u64 sample_type = perf_evlist__sample_type(self->evlist); + u64 sample_type = perf_evlist__combined_sample_type(self->evlist); if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) { if (sort__has_parent) { diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 5b1b5ab..c4185b9 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -72,7 +72,7 @@ int test__basic_mmap(void) } evsels[i]->attr.wakeup_events = 1; - perf_evsel__set_sample_id(evsels[i]); + perf_evsel__set_sample_id(evsels[i], false); perf_evlist__add(evlist, evsels[i]); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 19d911c..4913339 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -53,7 +53,8 @@ struct read_event { (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID |\ -PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) +PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \ +PERF_SAMPLE_IDENTIFIER) struct sample_event { struct perf_event_headerheader; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 9d682e5..6a629af 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -49,6 +49,21 @@ struct perf_evlist *perf_evlist__new(void) return evlist; } +/** + * perf_evlist__set_id_pos - set the positions of event ids. + * @evlist: selected event list + * + * Events with compatible sample types all have the same id_pos + * and is_pos. For convenience, put a copy on evlist. + */ +void perf_evlist__set_id_pos(struct perf_evlist *evlist) +{ + struct perf_evsel *first = perf_evlist__first(evlist); + + evlist->id_pos = first->id_pos; + evlist->is_pos = first->is_pos; +} + static void perf_evlist__purge(struct perf_evlist *evlist) { struct perf_evsel *pos, *n; @@ -79,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist) void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) { list_add_tail(>node, >entries); - ++evlist->nr_entries; + if (!evlist->nr_entries++) + perf_evlist__set_id_pos(evlist); } void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list, int nr_entries) { + bool set_id_pos = !evlist->nr_entries; + list_splice_tail(list, >entries); evlist->nr_entries += nr_entries; + if (set_id_pos) + perf_evlist__set_id_pos(evlist); } 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) return NULL; } +static int perf_evlist__event2id(struct perf_evlist *evlist, +union perf_event *event, u64 *id) +{ + const u64 *array = event->sample.array; + ssize_t n; + + n = (event->header.size - sizeof(event->header)) >> 3; + + if (event->header.type == PERF_RECORD_SAMPLE) { + if (evlist->id_pos >= n) + return -1; + *id = array[evlist->id_pos]; + } else { + if (evlist->is_pos > n) + return -1; + n -= evlist->is_pos; + *id = array[n]; + } + return 0; +} + +static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, + union perf_event *event) +{ + struct hlist_head *head; + struct perf_sample_id *sid; + int hash; + u64 id; + + if
[PATCH V13 07/12] perf tools: add support for PERF_SAMPLE_IDENTFIER
Enable parsing of samples with sample format bit PERF_SAMPLE_IDENTFIER. 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.hun...@intel.com --- tools/perf/builtin-report.c | 2 +- tools/perf/tests/mmap-basic.c | 2 +- tools/perf/util/event.h | 3 +- tools/perf/util/evlist.c | 111 +++--- tools/perf/util/evlist.h | 8 ++- tools/perf/util/evsel.c | 101 -- tools/perf/util/evsel.h | 14 +- tools/perf/util/record.c | 89 +++-- tools/perf/util/session.c | 2 +- 9 files changed, 310 insertions(+), 22 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 958a56a..9725aa3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -365,7 +365,7 @@ static int process_read_event(struct perf_tool *tool, static int perf_report__setup_sample_type(struct perf_report *rep) { struct perf_session *self = rep-session; - u64 sample_type = perf_evlist__sample_type(self-evlist); + u64 sample_type = perf_evlist__combined_sample_type(self-evlist); if (!self-fd_pipe !(sample_type PERF_SAMPLE_CALLCHAIN)) { if (sort__has_parent) { diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 5b1b5ab..c4185b9 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c @@ -72,7 +72,7 @@ int test__basic_mmap(void) } evsels[i]-attr.wakeup_events = 1; - perf_evsel__set_sample_id(evsels[i]); + perf_evsel__set_sample_id(evsels[i], false); perf_evlist__add(evlist, evsels[i]); diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 19d911c..4913339 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h @@ -53,7 +53,8 @@ struct read_event { (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID |\ -PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) +PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD | \ +PERF_SAMPLE_IDENTIFIER) struct sample_event { struct perf_event_headerheader; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 9d682e5..6a629af 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -49,6 +49,21 @@ struct perf_evlist *perf_evlist__new(void) return evlist; } +/** + * perf_evlist__set_id_pos - set the positions of event ids. + * @evlist: selected event list + * + * Events with compatible sample types all have the same id_pos + * and is_pos. For convenience, put a copy on evlist. + */ +void perf_evlist__set_id_pos(struct perf_evlist *evlist) +{ + struct perf_evsel *first = perf_evlist__first(evlist); + + evlist-id_pos = first-id_pos; + evlist-is_pos = first-is_pos; +} + static void perf_evlist__purge(struct perf_evlist *evlist) { struct perf_evsel *pos, *n; @@ -79,15 +94,20 @@ void perf_evlist__delete(struct perf_evlist *evlist) void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry) { list_add_tail(entry-node, evlist-entries); - ++evlist-nr_entries; + if (!evlist-nr_entries++) + perf_evlist__set_id_pos(evlist); } void perf_evlist__splice_list_tail(struct perf_evlist *evlist, struct list_head *list, int nr_entries) { + bool set_id_pos = !evlist-nr_entries; + list_splice_tail(list, evlist-entries); evlist-nr_entries += nr_entries; + if (set_id_pos) + perf_evlist__set_id_pos(evlist); } 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) return NULL; } +static int perf_evlist__event2id(struct perf_evlist *evlist, +union perf_event *event, u64 *id) +{ + const u64 *array = event-sample.array; + ssize_t n; + + n = (event-header.size - sizeof(event-header)) 3; + + if (event-header.type == PERF_RECORD_SAMPLE) { + if (evlist-id_pos = n) + return -1; + *id = array[evlist-id_pos]; + } else { + if (evlist-is_pos n) + return -1; + n -= evlist-is_pos; + *id = array[n]; + } + return 0; +} + +static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, + union perf_event *event) +{ + struct hlist_head *head; + struct perf_sample_id *sid; + int hash; + u64 id; + +