aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-inject.c1
-rw-r--r--tools/perf/util/event.c1
-rw-r--r--tools/perf/util/event.h15
-rw-r--r--tools/perf/util/evlist.c26
-rw-r--r--tools/perf/util/evsel.h3
-rw-r--r--tools/perf/util/session.c122
-rw-r--r--tools/perf/util/session.h10
-rw-r--r--tools/perf/util/tool.h3
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
33const char *perf_event__name(unsigned int id) 34const 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
243struct id_index_entry {
244 u64 id;
245 u64 idx;
246 u64 cpu;
247 u64 tid;
248};
249
250struct id_index_event {
251 struct perf_event_header header;
252 u64 nr;
253 struct id_index_entry entries[0];
254};
255
242union perf_event { 256union 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
258void perf_event__print_totals(void); 273void 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
530static 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
530struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 546struct 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
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,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,
1594out: 1608out:
1595 return err; 1609 return err;
1596} 1610}
1611
1612int 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
1650int 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);
1714out_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,
126extern volatile int session_done; 126extern volatile int session_done;
127 127
128#define session_done() ACCESS_ONCE(session_done) 128#define session_done() ACCESS_ONCE(session_done)
129
130int perf_event__process_id_index(struct perf_tool *tool,
131 union perf_event *event,
132 struct perf_session *session);
133
134int 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};