aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c141
1 files changed, 138 insertions, 3 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 6702ac28754b..f4478ce72fdb 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
231static 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
231void perf_tool__fill_defaults(struct perf_tool *tool) 240void 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
267static void swap_sample_id_all(union perf_event *event, void *data) 278static 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,11 +900,26 @@ 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 }
894} 908}
895 909
910int perf_session__deliver_synth_event(struct perf_session *session,
911 union perf_event *event,
912 struct perf_sample *sample,
913 struct perf_tool *tool)
914{
915 events_stats__inc(&session->stats, event->header.type);
916
917 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
918 return perf_session__process_user_event(session, event, tool, 0);
919
920 return perf_session__deliver_event(session, event, sample, tool, 0);
921}
922
896static void event_swap(union perf_event *event, bool sample_id_all) 923static void event_swap(union perf_event *event, bool sample_id_all)
897{ 924{
898 perf_event__swap_op swap; 925 perf_event__swap_op swap;
@@ -1417,9 +1444,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1417 if (symbol_conf.use_callchain && sample->callchain) { 1444 if (symbol_conf.use_callchain && sample->callchain) {
1418 struct addr_location node_al; 1445 struct addr_location node_al;
1419 1446
1420 if (machine__resolve_callchain(al->machine, evsel, al->thread, 1447 if (thread__resolve_callchain(al->thread, evsel,
1421 sample, NULL, NULL, 1448 sample, NULL, NULL,
1422 PERF_MAX_STACK_DEPTH) != 0) { 1449 PERF_MAX_STACK_DEPTH) != 0) {
1423 if (verbose) 1450 if (verbose)
1424 error("Failed to resolve callchain. Skipping\n"); 1451 error("Failed to resolve callchain. Skipping\n");
1425 return; 1452 return;
@@ -1594,3 +1621,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1594out: 1621out:
1595 return err; 1622 return err;
1596} 1623}
1624
1625int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
1626 union perf_event *event,
1627 struct perf_session *session)
1628{
1629 struct perf_evlist *evlist = session->evlist;
1630 struct id_index_event *ie = &event->id_index;
1631 size_t i, nr, max_nr;
1632
1633 max_nr = (ie->header.size - sizeof(struct id_index_event)) /
1634 sizeof(struct id_index_entry);
1635 nr = ie->nr;
1636 if (nr > max_nr)
1637 return -EINVAL;
1638
1639 if (dump_trace)
1640 fprintf(stdout, " nr: %zu\n", nr);
1641
1642 for (i = 0; i < nr; i++) {
1643 struct id_index_entry *e = &ie->entries[i];
1644 struct perf_sample_id *sid;
1645
1646 if (dump_trace) {
1647 fprintf(stdout, " ... id: %"PRIu64, e->id);
1648 fprintf(stdout, " idx: %"PRIu64, e->idx);
1649 fprintf(stdout, " cpu: %"PRId64, e->cpu);
1650 fprintf(stdout, " tid: %"PRId64"\n", e->tid);
1651 }
1652
1653 sid = perf_evlist__id2sid(evlist, e->id);
1654 if (!sid)
1655 return -ENOENT;
1656 sid->idx = e->idx;
1657 sid->cpu = e->cpu;
1658 sid->tid = e->tid;
1659 }
1660 return 0;
1661}
1662
1663int perf_event__synthesize_id_index(struct perf_tool *tool,
1664 perf_event__handler_t process,
1665 struct perf_evlist *evlist,
1666 struct machine *machine)
1667{
1668 union perf_event *ev;
1669 struct perf_evsel *evsel;
1670 size_t nr = 0, i = 0, sz, max_nr, n;
1671 int err;
1672
1673 pr_debug2("Synthesizing id index\n");
1674
1675 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
1676 sizeof(struct id_index_entry);
1677
1678 evlist__for_each(evlist, evsel)
1679 nr += evsel->ids;
1680
1681 n = nr > max_nr ? max_nr : nr;
1682 sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
1683 ev = zalloc(sz);
1684 if (!ev)
1685 return -ENOMEM;
1686
1687 ev->id_index.header.type = PERF_RECORD_ID_INDEX;
1688 ev->id_index.header.size = sz;
1689 ev->id_index.nr = n;
1690
1691 evlist__for_each(evlist, evsel) {
1692 u32 j;
1693
1694 for (j = 0; j < evsel->ids; j++) {
1695 struct id_index_entry *e;
1696 struct perf_sample_id *sid;
1697
1698 if (i >= n) {
1699 err = process(tool, ev, NULL, machine);
1700 if (err)
1701 goto out_err;
1702 nr -= n;
1703 i = 0;
1704 }
1705
1706 e = &ev->id_index.entries[i++];
1707
1708 e->id = evsel->id[j];
1709
1710 sid = perf_evlist__id2sid(evlist, e->id);
1711 if (!sid) {
1712 free(ev);
1713 return -ENOENT;
1714 }
1715
1716 e->idx = sid->idx;
1717 e->cpu = sid->cpu;
1718 e->tid = sid->tid;
1719 }
1720 }
1721
1722 sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
1723 ev->id_index.header.size = sz;
1724 ev->id_index.nr = nr;
1725
1726 err = process(tool, ev, NULL, machine);
1727out_err:
1728 free(ev);
1729
1730 return err;
1731}