diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/builtin-inject.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/event.h | 15 | ||||
| -rw-r--r-- | tools/perf/util/evlist.c | 26 | ||||
| -rw-r--r-- | tools/perf/util/evsel.h | 3 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 122 | ||||
| -rw-r--r-- | tools/perf/util/session.h | 10 | ||||
| -rw-r--r-- | tools/perf/util/tool.h | 3 |
8 files changed, 177 insertions, 4 deletions
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 06f1758951f1..84df2deed988 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
| @@ -409,6 +409,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
| 409 | .tracing_data = perf_event__repipe_op2_synth, | 409 | .tracing_data = perf_event__repipe_op2_synth, |
| 410 | .finished_round = perf_event__repipe_op2_synth, | 410 | .finished_round = perf_event__repipe_op2_synth, |
| 411 | .build_id = perf_event__repipe_op2_synth, | 411 | .build_id = perf_event__repipe_op2_synth, |
| 412 | .id_index = perf_event__repipe_op2_synth, | ||
| 412 | }, | 413 | }, |
| 413 | .input_name = "-", | 414 | .input_name = "-", |
| 414 | .samples = LIST_HEAD_INIT(inject.samples), | 415 | .samples = LIST_HEAD_INIT(inject.samples), |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index e00a29fb099f..6c6d044e959a 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -28,6 +28,7 @@ static const char *perf_event__names[] = { | |||
| 28 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", | 28 | [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", |
| 29 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", | 29 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", |
| 30 | [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", | 30 | [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", |
| 31 | [PERF_RECORD_ID_INDEX] = "ID_INDEX", | ||
| 31 | }; | 32 | }; |
| 32 | 33 | ||
| 33 | const char *perf_event__name(unsigned int id) | 34 | const char *perf_event__name(unsigned int id) |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 5f0e0b89e130..8c7fe9d64e79 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
| @@ -187,6 +187,7 @@ enum perf_user_event_type { /* above any possible kernel type */ | |||
| 187 | PERF_RECORD_HEADER_TRACING_DATA = 66, | 187 | PERF_RECORD_HEADER_TRACING_DATA = 66, |
| 188 | PERF_RECORD_HEADER_BUILD_ID = 67, | 188 | PERF_RECORD_HEADER_BUILD_ID = 67, |
| 189 | PERF_RECORD_FINISHED_ROUND = 68, | 189 | PERF_RECORD_FINISHED_ROUND = 68, |
| 190 | PERF_RECORD_ID_INDEX = 69, | ||
| 190 | PERF_RECORD_HEADER_MAX | 191 | PERF_RECORD_HEADER_MAX |
| 191 | }; | 192 | }; |
| 192 | 193 | ||
| @@ -239,6 +240,19 @@ struct tracing_data_event { | |||
| 239 | u32 size; | 240 | u32 size; |
| 240 | }; | 241 | }; |
| 241 | 242 | ||
| 243 | struct id_index_entry { | ||
| 244 | u64 id; | ||
| 245 | u64 idx; | ||
| 246 | u64 cpu; | ||
| 247 | u64 tid; | ||
| 248 | }; | ||
| 249 | |||
| 250 | struct id_index_event { | ||
| 251 | struct perf_event_header header; | ||
| 252 | u64 nr; | ||
| 253 | struct id_index_entry entries[0]; | ||
| 254 | }; | ||
| 255 | |||
| 242 | union perf_event { | 256 | union perf_event { |
| 243 | struct perf_event_header header; | 257 | struct perf_event_header header; |
| 244 | struct mmap_event mmap; | 258 | struct mmap_event mmap; |
| @@ -253,6 +267,7 @@ union perf_event { | |||
| 253 | struct event_type_event event_type; | 267 | struct event_type_event event_type; |
| 254 | struct tracing_data_event tracing_data; | 268 | struct tracing_data_event tracing_data; |
| 255 | struct build_id_event build_id; | 269 | struct build_id_event build_id; |
| 270 | struct id_index_event id_index; | ||
| 256 | }; | 271 | }; |
| 257 | 272 | ||
| 258 | void perf_event__print_totals(void); | 273 | void perf_event__print_totals(void); |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 3c9e77d6b4c2..0babd390963c 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -527,6 +527,22 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist, | |||
| 527 | return 0; | 527 | return 0; |
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | static void perf_evlist__set_sid_idx(struct perf_evlist *evlist, | ||
| 531 | struct perf_evsel *evsel, int idx, int cpu, | ||
| 532 | int thread) | ||
| 533 | { | ||
| 534 | struct perf_sample_id *sid = SID(evsel, cpu, thread); | ||
| 535 | sid->idx = idx; | ||
| 536 | if (evlist->cpus && cpu >= 0) | ||
| 537 | sid->cpu = evlist->cpus->map[cpu]; | ||
| 538 | else | ||
| 539 | sid->cpu = -1; | ||
| 540 | if (!evsel->system_wide && evlist->threads && thread >= 0) | ||
| 541 | sid->tid = evlist->threads->map[thread]; | ||
| 542 | else | ||
| 543 | sid->tid = -1; | ||
| 544 | } | ||
| 545 | |||
| 530 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) | 546 | struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) |
| 531 | { | 547 | { |
| 532 | struct hlist_head *head; | 548 | struct hlist_head *head; |
| @@ -805,9 +821,13 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, | |||
| 805 | return -1; | 821 | return -1; |
| 806 | } | 822 | } |
| 807 | 823 | ||
| 808 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 824 | if (evsel->attr.read_format & PERF_FORMAT_ID) { |
| 809 | perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) | 825 | if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread, |
| 810 | return -1; | 826 | fd) < 0) |
| 827 | return -1; | ||
| 828 | perf_evlist__set_sid_idx(evlist, evsel, idx, cpu, | ||
| 829 | thread); | ||
| 830 | } | ||
| 811 | } | 831 | } |
| 812 | 832 | ||
| 813 | return 0; | 833 | return 0; |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index d3854c4f52e1..979790951bfb 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -36,6 +36,9 @@ struct perf_sample_id { | |||
| 36 | struct hlist_node node; | 36 | struct hlist_node node; |
| 37 | u64 id; | 37 | u64 id; |
| 38 | struct perf_evsel *evsel; | 38 | struct perf_evsel *evsel; |
| 39 | int idx; | ||
| 40 | int cpu; | ||
| 41 | pid_t tid; | ||
| 39 | 42 | ||
| 40 | /* Holds total ID period value for PERF_SAMPLE_READ processing. */ | 43 | /* Holds total ID period value for PERF_SAMPLE_READ processing. */ |
| 41 | u64 period; | 44 | u64 period; |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 776010844cdc..27a0049118b5 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -228,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool, | |||
| 228 | union perf_event *event, | 228 | union perf_event *event, |
| 229 | struct perf_session *session); | 229 | struct perf_session *session); |
| 230 | 230 | ||
| 231 | static int process_id_index_stub(struct perf_tool *tool __maybe_unused, | ||
| 232 | union perf_event *event __maybe_unused, | ||
| 233 | struct perf_session *perf_session | ||
| 234 | __maybe_unused) | ||
| 235 | { | ||
| 236 | dump_printf(": unhandled!\n"); | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 231 | void perf_tool__fill_defaults(struct perf_tool *tool) | 240 | void perf_tool__fill_defaults(struct perf_tool *tool) |
| 232 | { | 241 | { |
| 233 | if (tool->sample == NULL) | 242 | if (tool->sample == NULL) |
| @@ -262,6 +271,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) | |||
| 262 | else | 271 | else |
| 263 | tool->finished_round = process_finished_round_stub; | 272 | tool->finished_round = process_finished_round_stub; |
| 264 | } | 273 | } |
| 274 | if (tool->id_index == NULL) | ||
| 275 | tool->id_index = process_id_index_stub; | ||
| 265 | } | 276 | } |
| 266 | 277 | ||
| 267 | static void swap_sample_id_all(union perf_event *event, void *data) | 278 | static void swap_sample_id_all(union perf_event *event, void *data) |
| @@ -460,6 +471,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { | |||
| 460 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, | 471 | [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, |
| 461 | [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, | 472 | [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, |
| 462 | [PERF_RECORD_HEADER_BUILD_ID] = NULL, | 473 | [PERF_RECORD_HEADER_BUILD_ID] = NULL, |
| 474 | [PERF_RECORD_ID_INDEX] = perf_event__all64_swap, | ||
| 463 | [PERF_RECORD_HEADER_MAX] = NULL, | 475 | [PERF_RECORD_HEADER_MAX] = NULL, |
| 464 | }; | 476 | }; |
| 465 | 477 | ||
| @@ -888,6 +900,8 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
| 888 | return tool->build_id(tool, event, session); | 900 | return tool->build_id(tool, event, session); |
| 889 | case PERF_RECORD_FINISHED_ROUND: | 901 | case PERF_RECORD_FINISHED_ROUND: |
| 890 | return tool->finished_round(tool, event, session); | 902 | return tool->finished_round(tool, event, session); |
| 903 | case PERF_RECORD_ID_INDEX: | ||
| 904 | return tool->id_index(tool, event, session); | ||
| 891 | default: | 905 | default: |
| 892 | return -EINVAL; | 906 | return -EINVAL; |
| 893 | } | 907 | } |
| @@ -1594,3 +1608,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
| 1594 | out: | 1608 | out: |
| 1595 | return err; | 1609 | return err; |
| 1596 | } | 1610 | } |
| 1611 | |||
| 1612 | int perf_event__process_id_index(struct perf_tool *tool __maybe_unused, | ||
| 1613 | union perf_event *event, | ||
| 1614 | struct perf_session *session) | ||
| 1615 | { | ||
| 1616 | struct perf_evlist *evlist = session->evlist; | ||
| 1617 | struct id_index_event *ie = &event->id_index; | ||
| 1618 | size_t i, nr, max_nr; | ||
| 1619 | |||
| 1620 | max_nr = (ie->header.size - sizeof(struct id_index_event)) / | ||
| 1621 | sizeof(struct id_index_entry); | ||
| 1622 | nr = ie->nr; | ||
| 1623 | if (nr > max_nr) | ||
| 1624 | return -EINVAL; | ||
| 1625 | |||
| 1626 | if (dump_trace) | ||
| 1627 | fprintf(stdout, " nr: %zu\n", nr); | ||
| 1628 | |||
| 1629 | for (i = 0; i < nr; i++) { | ||
| 1630 | struct id_index_entry *e = &ie->entries[i]; | ||
| 1631 | struct perf_sample_id *sid; | ||
| 1632 | |||
| 1633 | if (dump_trace) { | ||
| 1634 | fprintf(stdout, " ... id: %"PRIu64, e->id); | ||
| 1635 | fprintf(stdout, " idx: %"PRIu64, e->idx); | ||
| 1636 | fprintf(stdout, " cpu: %"PRId64, e->cpu); | ||
| 1637 | fprintf(stdout, " tid: %"PRId64"\n", e->tid); | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | sid = perf_evlist__id2sid(evlist, e->id); | ||
| 1641 | if (!sid) | ||
| 1642 | return -ENOENT; | ||
| 1643 | sid->idx = e->idx; | ||
| 1644 | sid->cpu = e->cpu; | ||
| 1645 | sid->tid = e->tid; | ||
| 1646 | } | ||
| 1647 | return 0; | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | int perf_event__synthesize_id_index(struct perf_tool *tool, | ||
| 1651 | perf_event__handler_t process, | ||
| 1652 | struct perf_evlist *evlist, | ||
| 1653 | struct machine *machine) | ||
| 1654 | { | ||
| 1655 | union perf_event *ev; | ||
| 1656 | struct perf_evsel *evsel; | ||
| 1657 | size_t nr = 0, i = 0, sz, max_nr, n; | ||
| 1658 | int err; | ||
| 1659 | |||
| 1660 | pr_debug2("Synthesizing id index\n"); | ||
| 1661 | |||
| 1662 | max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / | ||
| 1663 | sizeof(struct id_index_entry); | ||
| 1664 | |||
| 1665 | list_for_each_entry(evsel, &evlist->entries, node) | ||
| 1666 | nr += evsel->ids; | ||
| 1667 | |||
| 1668 | n = nr > max_nr ? max_nr : nr; | ||
| 1669 | sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry); | ||
| 1670 | ev = zalloc(sz); | ||
| 1671 | if (!ev) | ||
| 1672 | return -ENOMEM; | ||
| 1673 | |||
| 1674 | ev->id_index.header.type = PERF_RECORD_ID_INDEX; | ||
| 1675 | ev->id_index.header.size = sz; | ||
| 1676 | ev->id_index.nr = n; | ||
| 1677 | |||
| 1678 | list_for_each_entry(evsel, &evlist->entries, node) { | ||
| 1679 | u32 j; | ||
| 1680 | |||
| 1681 | for (j = 0; j < evsel->ids; j++) { | ||
| 1682 | struct id_index_entry *e; | ||
| 1683 | struct perf_sample_id *sid; | ||
| 1684 | |||
| 1685 | if (i >= n) { | ||
| 1686 | err = process(tool, ev, NULL, machine); | ||
| 1687 | if (err) | ||
| 1688 | goto out_err; | ||
| 1689 | nr -= n; | ||
| 1690 | i = 0; | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | e = &ev->id_index.entries[i++]; | ||
| 1694 | |||
| 1695 | e->id = evsel->id[j]; | ||
| 1696 | |||
| 1697 | sid = perf_evlist__id2sid(evlist, e->id); | ||
| 1698 | if (!sid) { | ||
| 1699 | free(ev); | ||
| 1700 | return -ENOENT; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | e->idx = sid->idx; | ||
| 1704 | e->cpu = sid->cpu; | ||
| 1705 | e->tid = sid->tid; | ||
| 1706 | } | ||
| 1707 | } | ||
| 1708 | |||
| 1709 | sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry); | ||
| 1710 | ev->id_index.header.size = sz; | ||
| 1711 | ev->id_index.nr = nr; | ||
| 1712 | |||
| 1713 | err = process(tool, ev, NULL, machine); | ||
| 1714 | out_err: | ||
| 1715 | free(ev); | ||
| 1716 | |||
| 1717 | return err; | ||
| 1718 | } | ||
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index a4be851f1a90..d8521ac73a10 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
| @@ -126,4 +126,14 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
| 126 | extern volatile int session_done; | 126 | extern volatile int session_done; |
| 127 | 127 | ||
| 128 | #define session_done() ACCESS_ONCE(session_done) | 128 | #define session_done() ACCESS_ONCE(session_done) |
| 129 | |||
| 130 | int perf_event__process_id_index(struct perf_tool *tool, | ||
| 131 | union perf_event *event, | ||
| 132 | struct perf_session *session); | ||
| 133 | |||
| 134 | int perf_event__synthesize_id_index(struct perf_tool *tool, | ||
| 135 | perf_event__handler_t process, | ||
| 136 | struct perf_evlist *evlist, | ||
| 137 | struct machine *machine); | ||
| 138 | |||
| 129 | #endif /* __PERF_SESSION_H */ | 139 | #endif /* __PERF_SESSION_H */ |
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index f11636966a0f..bb2708bbfaca 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h | |||
| @@ -39,7 +39,8 @@ struct perf_tool { | |||
| 39 | event_attr_op attr; | 39 | event_attr_op attr; |
| 40 | event_op2 tracing_data; | 40 | event_op2 tracing_data; |
| 41 | event_op2 finished_round, | 41 | event_op2 finished_round, |
| 42 | build_id; | 42 | build_id, |
| 43 | id_index; | ||
| 43 | bool ordered_events; | 44 | bool ordered_events; |
| 44 | bool ordering_requires_timestamps; | 45 | bool ordering_requires_timestamps; |
| 45 | }; | 46 | }; |
