diff options
-rw-r--r-- | tools/perf/builtin-annotate.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 11 | ||||
-rw-r--r-- | tools/perf/builtin-inject.c | 39 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 21 | ||||
-rw-r--r-- | tools/perf/builtin-lock.c | 12 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 15 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 21 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 34 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 40 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 4 | ||||
-rw-r--r-- | tools/perf/util/build-id.c | 7 | ||||
-rw-r--r-- | tools/perf/util/event.c | 66 | ||||
-rw-r--r-- | tools/perf/util/event.h | 20 | ||||
-rw-r--r-- | tools/perf/util/header.c | 11 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 2 | ||||
-rw-r--r-- | tools/perf/util/session.c | 103 | ||||
-rw-r--r-- | tools/perf/util/session.h | 9 |
18 files changed, 236 insertions, 192 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 6d5604d8df95..569a2761b90a 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -58,12 +58,12 @@ static int hists__add_entry(struct hists *self, struct addr_location *al) | |||
58 | return hist_entry__inc_addr_samples(he, al->addr); | 58 | return hist_entry__inc_addr_samples(he, al->addr); |
59 | } | 59 | } |
60 | 60 | ||
61 | static int process_sample_event(event_t *event, struct perf_session *session) | 61 | static int process_sample_event(event_t *event, struct sample_data *sample, |
62 | struct perf_session *session) | ||
62 | { | 63 | { |
63 | struct addr_location al; | 64 | struct addr_location al; |
64 | struct sample_data data; | ||
65 | 65 | ||
66 | if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { | 66 | if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { |
67 | pr_warning("problem processing %d event, skipping it.\n", | 67 | pr_warning("problem processing %d event, skipping it.\n", |
68 | event->header.type); | 68 | event->header.type); |
69 | return -1; | 69 | return -1; |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 221b823bc26f..5e1a043aae03 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -30,12 +30,13 @@ static int hists__add_entry(struct hists *self, | |||
30 | return -ENOMEM; | 30 | return -ENOMEM; |
31 | } | 31 | } |
32 | 32 | ||
33 | static int diff__process_sample_event(event_t *event, struct perf_session *session) | 33 | static int diff__process_sample_event(event_t *event, |
34 | struct sample_data *sample, | ||
35 | struct perf_session *session) | ||
34 | { | 36 | { |
35 | struct addr_location al; | 37 | struct addr_location al; |
36 | struct sample_data data = { .period = 1, }; | ||
37 | 38 | ||
38 | if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { | 39 | if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { |
39 | pr_warning("problem processing %d event, skipping it.\n", | 40 | pr_warning("problem processing %d event, skipping it.\n", |
40 | event->header.type); | 41 | event->header.type); |
41 | return -1; | 42 | return -1; |
@@ -44,12 +45,12 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi | |||
44 | if (al.filtered || al.sym == NULL) | 45 | if (al.filtered || al.sym == NULL) |
45 | return 0; | 46 | return 0; |
46 | 47 | ||
47 | if (hists__add_entry(&session->hists, &al, data.period)) { | 48 | if (hists__add_entry(&session->hists, &al, sample->period)) { |
48 | pr_warning("problem incrementing symbol period, skipping event\n"); | 49 | pr_warning("problem incrementing symbol period, skipping event\n"); |
49 | return -1; | 50 | return -1; |
50 | } | 51 | } |
51 | 52 | ||
52 | session->hists.stats.total_period += data.period; | 53 | session->hists.stats.total_period += sample->period; |
53 | return 0; | 54 | return 0; |
54 | } | 55 | } |
55 | 56 | ||
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 8e3e47b064ce..4b66b8579410 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -16,8 +16,8 @@ | |||
16 | static char const *input_name = "-"; | 16 | static char const *input_name = "-"; |
17 | static bool inject_build_ids; | 17 | static bool inject_build_ids; |
18 | 18 | ||
19 | static int event__repipe(event_t *event __used, | 19 | static int event__repipe_synth(event_t *event, |
20 | struct perf_session *session __used) | 20 | struct perf_session *session __used) |
21 | { | 21 | { |
22 | uint32_t size; | 22 | uint32_t size; |
23 | void *buf = event; | 23 | void *buf = event; |
@@ -36,22 +36,30 @@ static int event__repipe(event_t *event __used, | |||
36 | return 0; | 36 | return 0; |
37 | } | 37 | } |
38 | 38 | ||
39 | static int event__repipe_mmap(event_t *self, struct perf_session *session) | 39 | static int event__repipe(event_t *event, struct sample_data *sample __used, |
40 | struct perf_session *session) | ||
41 | { | ||
42 | return event__repipe_synth(event, session); | ||
43 | } | ||
44 | |||
45 | static int event__repipe_mmap(event_t *self, struct sample_data *sample, | ||
46 | struct perf_session *session) | ||
40 | { | 47 | { |
41 | int err; | 48 | int err; |
42 | 49 | ||
43 | err = event__process_mmap(self, session); | 50 | err = event__process_mmap(self, sample, session); |
44 | event__repipe(self, session); | 51 | event__repipe(self, sample, session); |
45 | 52 | ||
46 | return err; | 53 | return err; |
47 | } | 54 | } |
48 | 55 | ||
49 | static int event__repipe_task(event_t *self, struct perf_session *session) | 56 | static int event__repipe_task(event_t *self, struct sample_data *sample, |
57 | struct perf_session *session) | ||
50 | { | 58 | { |
51 | int err; | 59 | int err; |
52 | 60 | ||
53 | err = event__process_task(self, session); | 61 | err = event__process_task(self, sample, session); |
54 | event__repipe(self, session); | 62 | event__repipe(self, sample, session); |
55 | 63 | ||
56 | return err; | 64 | return err; |
57 | } | 65 | } |
@@ -61,7 +69,7 @@ static int event__repipe_tracing_data(event_t *self, | |||
61 | { | 69 | { |
62 | int err; | 70 | int err; |
63 | 71 | ||
64 | event__repipe(self, session); | 72 | event__repipe_synth(self, session); |
65 | err = event__process_tracing_data(self, session); | 73 | err = event__process_tracing_data(self, session); |
66 | 74 | ||
67 | return err; | 75 | return err; |
@@ -111,7 +119,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session) | |||
111 | return 0; | 119 | return 0; |
112 | } | 120 | } |
113 | 121 | ||
114 | static int event__inject_buildid(event_t *event, struct perf_session *session) | 122 | static int event__inject_buildid(event_t *event, struct sample_data *sample, |
123 | struct perf_session *session) | ||
115 | { | 124 | { |
116 | struct addr_location al; | 125 | struct addr_location al; |
117 | struct thread *thread; | 126 | struct thread *thread; |
@@ -146,7 +155,7 @@ static int event__inject_buildid(event_t *event, struct perf_session *session) | |||
146 | } | 155 | } |
147 | 156 | ||
148 | repipe: | 157 | repipe: |
149 | event__repipe(event, session); | 158 | event__repipe(event, sample, session); |
150 | return 0; | 159 | return 0; |
151 | } | 160 | } |
152 | 161 | ||
@@ -160,10 +169,10 @@ struct perf_event_ops inject_ops = { | |||
160 | .read = event__repipe, | 169 | .read = event__repipe, |
161 | .throttle = event__repipe, | 170 | .throttle = event__repipe, |
162 | .unthrottle = event__repipe, | 171 | .unthrottle = event__repipe, |
163 | .attr = event__repipe, | 172 | .attr = event__repipe_synth, |
164 | .event_type = event__repipe, | 173 | .event_type = event__repipe_synth, |
165 | .tracing_data = event__repipe, | 174 | .tracing_data = event__repipe_synth, |
166 | .build_id = event__repipe, | 175 | .build_id = event__repipe_synth, |
167 | }; | 176 | }; |
168 | 177 | ||
169 | extern volatile int session_done; | 178 | extern volatile int session_done; |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 31f60a2535e0..d0a652e9c708 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -304,22 +304,11 @@ process_raw_event(event_t *raw_event __used, void *data, | |||
304 | } | 304 | } |
305 | } | 305 | } |
306 | 306 | ||
307 | static int process_sample_event(event_t *event, struct perf_session *session) | 307 | static int process_sample_event(event_t *event, struct sample_data *sample, |
308 | struct perf_session *session) | ||
308 | { | 309 | { |
309 | struct sample_data data; | 310 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
310 | struct thread *thread; | ||
311 | 311 | ||
312 | memset(&data, 0, sizeof(data)); | ||
313 | data.time = -1; | ||
314 | data.cpu = -1; | ||
315 | data.period = 1; | ||
316 | |||
317 | event__parse_sample(event, session->sample_type, &data); | ||
318 | |||
319 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc, | ||
320 | data.pid, data.tid, data.ip, data.period); | ||
321 | |||
322 | thread = perf_session__findnew(session, event->ip.pid); | ||
323 | if (thread == NULL) { | 312 | if (thread == NULL) { |
324 | pr_debug("problem processing %d event, skipping it.\n", | 313 | pr_debug("problem processing %d event, skipping it.\n", |
325 | event->header.type); | 314 | event->header.type); |
@@ -328,8 +317,8 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
328 | 317 | ||
329 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 318 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); |
330 | 319 | ||
331 | process_raw_event(event, data.raw_data, data.cpu, | 320 | process_raw_event(event, sample->raw_data, sample->cpu, |
332 | data.time, thread); | 321 | sample->time, thread); |
333 | 322 | ||
334 | return 0; | 323 | return 0; |
335 | } | 324 | } |
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 8452a2ae2191..92d3da52a5cf 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c | |||
@@ -834,22 +834,18 @@ static void dump_info(void) | |||
834 | die("Unknown type of information\n"); | 834 | die("Unknown type of information\n"); |
835 | } | 835 | } |
836 | 836 | ||
837 | static int process_sample_event(event_t *self, struct perf_session *s) | 837 | static int process_sample_event(event_t *self, struct sample_data *sample, |
838 | struct perf_session *s) | ||
838 | { | 839 | { |
839 | struct sample_data data; | 840 | struct thread *thread = perf_session__findnew(s, sample->tid); |
840 | struct thread *thread; | ||
841 | 841 | ||
842 | bzero(&data, sizeof(data)); | ||
843 | event__parse_sample(self, s->sample_type, &data); | ||
844 | |||
845 | thread = perf_session__findnew(s, data.tid); | ||
846 | if (thread == NULL) { | 842 | if (thread == NULL) { |
847 | pr_debug("problem processing %d event, skipping it.\n", | 843 | pr_debug("problem processing %d event, skipping it.\n", |
848 | self->header.type); | 844 | self->header.type); |
849 | return -1; | 845 | return -1; |
850 | } | 846 | } |
851 | 847 | ||
852 | process_raw_event(data.raw_data, data.cpu, data.time, thread); | 848 | process_raw_event(sample->raw_data, sample->cpu, sample->time, thread); |
853 | 849 | ||
854 | return 0; | 850 | return 0; |
855 | } | 851 | } |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 024e1441d76b..b34de9291c27 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -36,6 +36,7 @@ static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; | |||
36 | 36 | ||
37 | static u64 user_interval = ULLONG_MAX; | 37 | static u64 user_interval = ULLONG_MAX; |
38 | static u64 default_interval = 0; | 38 | static u64 default_interval = 0; |
39 | static u64 sample_type; | ||
39 | 40 | ||
40 | static int nr_cpus = 0; | 41 | static int nr_cpus = 0; |
41 | static unsigned int page_size; | 42 | static unsigned int page_size; |
@@ -129,6 +130,7 @@ static void write_output(void *buf, size_t size) | |||
129 | } | 130 | } |
130 | 131 | ||
131 | static int process_synthesized_event(event_t *event, | 132 | static int process_synthesized_event(event_t *event, |
133 | struct sample_data *sample __used, | ||
132 | struct perf_session *self __used) | 134 | struct perf_session *self __used) |
133 | { | 135 | { |
134 | write_output(event, event->header.size); | 136 | write_output(event, event->header.size); |
@@ -287,6 +289,9 @@ static void create_counter(int counter, int cpu) | |||
287 | attr->sample_type |= PERF_SAMPLE_CPU; | 289 | attr->sample_type |= PERF_SAMPLE_CPU; |
288 | } | 290 | } |
289 | 291 | ||
292 | if (!sample_type) | ||
293 | sample_type = attr->sample_type; | ||
294 | |||
290 | attr->mmap = track; | 295 | attr->mmap = track; |
291 | attr->comm = track; | 296 | attr->comm = track; |
292 | attr->inherit = !no_inherit; | 297 | attr->inherit = !no_inherit; |
@@ -642,6 +647,8 @@ static int __cmd_record(int argc, const char **argv) | |||
642 | open_counters(cpumap[i]); | 647 | open_counters(cpumap[i]); |
643 | } | 648 | } |
644 | 649 | ||
650 | perf_session__set_sample_type(session, sample_type); | ||
651 | |||
645 | if (pipe_output) { | 652 | if (pipe_output) { |
646 | err = perf_header__write_pipe(output); | 653 | err = perf_header__write_pipe(output); |
647 | if (err < 0) | 654 | if (err < 0) |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 5de405d45230..904519fba434 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -150,13 +150,13 @@ static int add_event_total(struct perf_session *session, | |||
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int process_sample_event(event_t *event, struct perf_session *session) | 153 | static int process_sample_event(event_t *event, struct sample_data *sample, |
154 | struct perf_session *session) | ||
154 | { | 155 | { |
155 | struct sample_data data = { .period = 1, }; | ||
156 | struct addr_location al; | 156 | struct addr_location al; |
157 | struct perf_event_attr *attr; | 157 | struct perf_event_attr *attr; |
158 | 158 | ||
159 | if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { | 159 | if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) { |
160 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 160 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
161 | event->header.type); | 161 | event->header.type); |
162 | return -1; | 162 | return -1; |
@@ -165,14 +165,14 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
165 | if (al.filtered || (hide_unresolved && al.sym == NULL)) | 165 | if (al.filtered || (hide_unresolved && al.sym == NULL)) |
166 | return 0; | 166 | return 0; |
167 | 167 | ||
168 | if (perf_session__add_hist_entry(session, &al, &data)) { | 168 | if (perf_session__add_hist_entry(session, &al, sample)) { |
169 | pr_debug("problem incrementing symbol period, skipping event\n"); | 169 | pr_debug("problem incrementing symbol period, skipping event\n"); |
170 | return -1; | 170 | return -1; |
171 | } | 171 | } |
172 | 172 | ||
173 | attr = perf_header__find_attr(data.id, &session->header); | 173 | attr = perf_header__find_attr(sample->id, &session->header); |
174 | 174 | ||
175 | if (add_event_total(session, &data, attr)) { | 175 | if (add_event_total(session, sample, attr)) { |
176 | pr_debug("problem adding event period\n"); | 176 | pr_debug("problem adding event period\n"); |
177 | return -1; | 177 | return -1; |
178 | } | 178 | } |
@@ -180,7 +180,8 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
180 | return 0; | 180 | return 0; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int process_read_event(event_t *event, struct perf_session *session __used) | 183 | static int process_read_event(event_t *event, struct sample_data *sample __used, |
184 | struct perf_session *session __used) | ||
184 | { | 185 | { |
185 | struct perf_event_attr *attr; | 186 | struct perf_event_attr *attr; |
186 | 187 | ||
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 26523c939791..73d1e30b0fed 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1606,25 +1606,15 @@ process_raw_event(event_t *raw_event __used, struct perf_session *session, | |||
1606 | process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); | 1606 | process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); |
1607 | } | 1607 | } |
1608 | 1608 | ||
1609 | static int process_sample_event(event_t *event, struct perf_session *session) | 1609 | static int process_sample_event(event_t *event, struct sample_data *sample, |
1610 | struct perf_session *session) | ||
1610 | { | 1611 | { |
1611 | struct sample_data data; | ||
1612 | struct thread *thread; | 1612 | struct thread *thread; |
1613 | 1613 | ||
1614 | if (!(session->sample_type & PERF_SAMPLE_RAW)) | 1614 | if (!(session->sample_type & PERF_SAMPLE_RAW)) |
1615 | return 0; | 1615 | return 0; |
1616 | 1616 | ||
1617 | memset(&data, 0, sizeof(data)); | 1617 | thread = perf_session__findnew(session, sample->pid); |
1618 | data.time = -1; | ||
1619 | data.cpu = -1; | ||
1620 | data.period = -1; | ||
1621 | |||
1622 | event__parse_sample(event, session->sample_type, &data); | ||
1623 | |||
1624 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc, | ||
1625 | data.pid, data.tid, data.ip, data.period); | ||
1626 | |||
1627 | thread = perf_session__findnew(session, data.pid); | ||
1628 | if (thread == NULL) { | 1618 | if (thread == NULL) { |
1629 | pr_debug("problem processing %d event, skipping it.\n", | 1619 | pr_debug("problem processing %d event, skipping it.\n", |
1630 | event->header.type); | 1620 | event->header.type); |
@@ -1633,10 +1623,11 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
1633 | 1623 | ||
1634 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 1624 | dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); |
1635 | 1625 | ||
1636 | if (profile_cpu != -1 && profile_cpu != (int)data.cpu) | 1626 | if (profile_cpu != -1 && profile_cpu != (int)sample->cpu) |
1637 | return 0; | 1627 | return 0; |
1638 | 1628 | ||
1639 | process_raw_event(event, session, data.raw_data, data.cpu, data.time, thread); | 1629 | process_raw_event(event, session, sample->raw_data, sample->cpu, |
1630 | sample->time, thread); | ||
1640 | 1631 | ||
1641 | return 0; | 1632 | return 0; |
1642 | } | 1633 | } |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 4539551ab40e..683a30572cc5 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -63,22 +63,11 @@ static int cleanup_scripting(void) | |||
63 | 63 | ||
64 | static char const *input_name = "perf.data"; | 64 | static char const *input_name = "perf.data"; |
65 | 65 | ||
66 | static int process_sample_event(event_t *event, struct perf_session *session) | 66 | static int process_sample_event(event_t *event, struct sample_data *sample, |
67 | struct perf_session *session) | ||
67 | { | 68 | { |
68 | struct sample_data data; | 69 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
69 | struct thread *thread; | ||
70 | 70 | ||
71 | memset(&data, 0, sizeof(data)); | ||
72 | data.time = -1; | ||
73 | data.cpu = -1; | ||
74 | data.period = 1; | ||
75 | |||
76 | event__parse_sample(event, session->sample_type, &data); | ||
77 | |||
78 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc, | ||
79 | data.pid, data.tid, data.ip, data.period); | ||
80 | |||
81 | thread = perf_session__findnew(session, event->ip.pid); | ||
82 | if (thread == NULL) { | 71 | if (thread == NULL) { |
83 | pr_debug("problem processing %d event, skipping it.\n", | 72 | pr_debug("problem processing %d event, skipping it.\n", |
84 | event->header.type); | 73 | event->header.type); |
@@ -87,13 +76,13 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
87 | 76 | ||
88 | if (session->sample_type & PERF_SAMPLE_RAW) { | 77 | if (session->sample_type & PERF_SAMPLE_RAW) { |
89 | if (debug_mode) { | 78 | if (debug_mode) { |
90 | if (data.time < last_timestamp) { | 79 | if (sample->time < last_timestamp) { |
91 | pr_err("Samples misordered, previous: %llu " | 80 | pr_err("Samples misordered, previous: %llu " |
92 | "this: %llu\n", last_timestamp, | 81 | "this: %llu\n", last_timestamp, |
93 | data.time); | 82 | sample->time); |
94 | nr_unordered++; | 83 | nr_unordered++; |
95 | } | 84 | } |
96 | last_timestamp = data.time; | 85 | last_timestamp = sample->time; |
97 | return 0; | 86 | return 0; |
98 | } | 87 | } |
99 | /* | 88 | /* |
@@ -101,18 +90,19 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
101 | * field, although it should be the same than this perf | 90 | * field, although it should be the same than this perf |
102 | * event pid | 91 | * event pid |
103 | */ | 92 | */ |
104 | scripting_ops->process_event(data.cpu, data.raw_data, | 93 | scripting_ops->process_event(sample->cpu, sample->raw_data, |
105 | data.raw_size, | 94 | sample->raw_size, |
106 | data.time, thread->comm); | 95 | sample->time, thread->comm); |
107 | } | 96 | } |
108 | 97 | ||
109 | session->hists.stats.total_period += data.period; | 98 | session->hists.stats.total_period += sample->period; |
110 | return 0; | 99 | return 0; |
111 | } | 100 | } |
112 | 101 | ||
113 | static u64 nr_lost; | 102 | static u64 nr_lost; |
114 | 103 | ||
115 | static int process_lost_event(event_t *event, struct perf_session *session __used) | 104 | static int process_lost_event(event_t *event, struct sample_data *sample __used, |
105 | struct perf_session *session __used) | ||
116 | { | 106 | { |
117 | nr_lost += event->lost.lost; | 107 | nr_lost += event->lost.lost; |
118 | 108 | ||
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 9bcc38f0b706..1f158dc03349 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -272,19 +272,22 @@ static int cpus_cstate_state[MAX_CPUS]; | |||
272 | static u64 cpus_pstate_start_times[MAX_CPUS]; | 272 | static u64 cpus_pstate_start_times[MAX_CPUS]; |
273 | static u64 cpus_pstate_state[MAX_CPUS]; | 273 | static u64 cpus_pstate_state[MAX_CPUS]; |
274 | 274 | ||
275 | static int process_comm_event(event_t *event, struct perf_session *session __used) | 275 | static int process_comm_event(event_t *event, struct sample_data *sample __used, |
276 | struct perf_session *session __used) | ||
276 | { | 277 | { |
277 | pid_set_comm(event->comm.tid, event->comm.comm); | 278 | pid_set_comm(event->comm.tid, event->comm.comm); |
278 | return 0; | 279 | return 0; |
279 | } | 280 | } |
280 | 281 | ||
281 | static int process_fork_event(event_t *event, struct perf_session *session __used) | 282 | static int process_fork_event(event_t *event, struct sample_data *sample __used, |
283 | struct perf_session *session __used) | ||
282 | { | 284 | { |
283 | pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); | 285 | pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); |
284 | return 0; | 286 | return 0; |
285 | } | 287 | } |
286 | 288 | ||
287 | static int process_exit_event(event_t *event, struct perf_session *session __used) | 289 | static int process_exit_event(event_t *event, struct sample_data *sample __used, |
290 | struct perf_session *session __used) | ||
288 | { | 291 | { |
289 | pid_exit(event->fork.pid, event->fork.time); | 292 | pid_exit(event->fork.pid, event->fork.time); |
290 | return 0; | 293 | return 0; |
@@ -470,24 +473,21 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) | |||
470 | } | 473 | } |
471 | 474 | ||
472 | 475 | ||
473 | static int process_sample_event(event_t *event, struct perf_session *session) | 476 | static int process_sample_event(event_t *event __used, |
477 | struct sample_data *sample, | ||
478 | struct perf_session *session) | ||
474 | { | 479 | { |
475 | struct sample_data data; | ||
476 | struct trace_entry *te; | 480 | struct trace_entry *te; |
477 | 481 | ||
478 | memset(&data, 0, sizeof(data)); | ||
479 | |||
480 | event__parse_sample(event, session->sample_type, &data); | ||
481 | |||
482 | if (session->sample_type & PERF_SAMPLE_TIME) { | 482 | if (session->sample_type & PERF_SAMPLE_TIME) { |
483 | if (!first_time || first_time > data.time) | 483 | if (!first_time || first_time > sample->time) |
484 | first_time = data.time; | 484 | first_time = sample->time; |
485 | if (last_time < data.time) | 485 | if (last_time < sample->time) |
486 | last_time = data.time; | 486 | last_time = sample->time; |
487 | } | 487 | } |
488 | 488 | ||
489 | te = (void *)data.raw_data; | 489 | te = (void *)sample->raw_data; |
490 | if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { | 490 | if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) { |
491 | char *event_str; | 491 | char *event_str; |
492 | struct power_entry *pe; | 492 | struct power_entry *pe; |
493 | 493 | ||
@@ -499,19 +499,19 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
499 | return 0; | 499 | return 0; |
500 | 500 | ||
501 | if (strcmp(event_str, "power:power_start") == 0) | 501 | if (strcmp(event_str, "power:power_start") == 0) |
502 | c_state_start(pe->cpu_id, data.time, pe->value); | 502 | c_state_start(pe->cpu_id, sample->time, pe->value); |
503 | 503 | ||
504 | if (strcmp(event_str, "power:power_end") == 0) | 504 | if (strcmp(event_str, "power:power_end") == 0) |
505 | c_state_end(pe->cpu_id, data.time); | 505 | c_state_end(pe->cpu_id, sample->time); |
506 | 506 | ||
507 | if (strcmp(event_str, "power:power_frequency") == 0) | 507 | if (strcmp(event_str, "power:power_frequency") == 0) |
508 | p_state_change(pe->cpu_id, data.time, pe->value); | 508 | p_state_change(pe->cpu_id, sample->time, pe->value); |
509 | 509 | ||
510 | if (strcmp(event_str, "sched:sched_wakeup") == 0) | 510 | if (strcmp(event_str, "sched:sched_wakeup") == 0) |
511 | sched_wakeup(data.cpu, data.time, data.pid, te); | 511 | sched_wakeup(sample->cpu, sample->time, sample->pid, te); |
512 | 512 | ||
513 | if (strcmp(event_str, "sched:sched_switch") == 0) | 513 | if (strcmp(event_str, "sched:sched_switch") == 0) |
514 | sched_switch(data.cpu, data.time, te); | 514 | sched_switch(sample->cpu, sample->time, te); |
515 | } | 515 | } |
516 | return 0; | 516 | return 0; |
517 | } | 517 | } |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 3d2b47d5121a..5aa29e1e855a 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -1025,6 +1025,8 @@ static void event__process_sample(const event_t *self, | |||
1025 | if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) | 1025 | if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) |
1026 | exact_samples++; | 1026 | exact_samples++; |
1027 | 1027 | ||
1028 | event__parse_sample(self, session->sample_type, &data); | ||
1029 | |||
1028 | if (event__preprocess_sample(self, session, &al, &data, | 1030 | if (event__preprocess_sample(self, session, &al, &data, |
1029 | symbol_filter) < 0 || | 1031 | symbol_filter) < 0 || |
1030 | al.filtered) | 1032 | al.filtered) |
@@ -1155,7 +1157,7 @@ static void perf_session__mmap_read_counter(struct perf_session *self, | |||
1155 | if (event->header.type == PERF_RECORD_SAMPLE) | 1157 | if (event->header.type == PERF_RECORD_SAMPLE) |
1156 | event__process_sample(event, self, md->counter); | 1158 | event__process_sample(event, self, md->counter); |
1157 | else | 1159 | else |
1158 | event__process(event, self); | 1160 | event__process(event, NULL, self); |
1159 | old += size; | 1161 | old += size; |
1160 | } | 1162 | } |
1161 | 1163 | ||
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index e437edb72417..deffb8c96071 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -14,7 +14,9 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include "debug.h" | 15 | #include "debug.h" |
16 | 16 | ||
17 | static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) | 17 | static int build_id__mark_dso_hit(event_t *event, |
18 | struct sample_data *sample __used, | ||
19 | struct perf_session *session) | ||
18 | { | 20 | { |
19 | struct addr_location al; | 21 | struct addr_location al; |
20 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 22 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
@@ -35,7 +37,8 @@ static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) | |||
35 | return 0; | 37 | return 0; |
36 | } | 38 | } |
37 | 39 | ||
38 | static int event__exit_del_thread(event_t *self, struct perf_session *session) | 40 | static int event__exit_del_thread(event_t *self, struct sample_data *sample __used, |
41 | struct perf_session *session) | ||
39 | { | 42 | { |
40 | struct thread *thread = perf_session__findnew(session, self->fork.tid); | 43 | struct thread *thread = perf_session__findnew(session, self->fork.tid); |
41 | 44 | ||
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 7260db75b93d..34510f441975 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -24,6 +24,15 @@ const char *event__name[] = { | |||
24 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", | 24 | [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", |
25 | }; | 25 | }; |
26 | 26 | ||
27 | static struct sample_data synth_sample = { | ||
28 | .pid = -1, | ||
29 | .tid = -1, | ||
30 | .time = -1, | ||
31 | .stream_id = -1, | ||
32 | .cpu = -1, | ||
33 | .period = 1, | ||
34 | }; | ||
35 | |||
27 | static pid_t event__synthesize_comm(pid_t pid, int full, | 36 | static pid_t event__synthesize_comm(pid_t pid, int full, |
28 | event__handler_t process, | 37 | event__handler_t process, |
29 | struct perf_session *session) | 38 | struct perf_session *session) |
@@ -75,7 +84,7 @@ out_race: | |||
75 | if (!full) { | 84 | if (!full) { |
76 | ev.comm.tid = pid; | 85 | ev.comm.tid = pid; |
77 | 86 | ||
78 | process(&ev, session); | 87 | process(&ev, &synth_sample, session); |
79 | goto out_fclose; | 88 | goto out_fclose; |
80 | } | 89 | } |
81 | 90 | ||
@@ -93,7 +102,7 @@ out_race: | |||
93 | 102 | ||
94 | ev.comm.tid = pid; | 103 | ev.comm.tid = pid; |
95 | 104 | ||
96 | process(&ev, session); | 105 | process(&ev, &synth_sample, session); |
97 | } | 106 | } |
98 | closedir(tasks); | 107 | closedir(tasks); |
99 | 108 | ||
@@ -173,7 +182,7 @@ static int event__synthesize_mmap_events(pid_t pid, pid_t tgid, | |||
173 | ev.mmap.pid = tgid; | 182 | ev.mmap.pid = tgid; |
174 | ev.mmap.tid = pid; | 183 | ev.mmap.tid = pid; |
175 | 184 | ||
176 | process(&ev, session); | 185 | process(&ev, &synth_sample, session); |
177 | } | 186 | } |
178 | } | 187 | } |
179 | 188 | ||
@@ -219,7 +228,7 @@ int event__synthesize_modules(event__handler_t process, | |||
219 | 228 | ||
220 | memcpy(ev.mmap.filename, pos->dso->long_name, | 229 | memcpy(ev.mmap.filename, pos->dso->long_name, |
221 | pos->dso->long_name_len + 1); | 230 | pos->dso->long_name_len + 1); |
222 | process(&ev, session); | 231 | process(&ev, &synth_sample, session); |
223 | } | 232 | } |
224 | 233 | ||
225 | return 0; | 234 | return 0; |
@@ -331,7 +340,7 @@ int event__synthesize_kernel_mmap(event__handler_t process, | |||
331 | ev.mmap.len = map->end - ev.mmap.start; | 340 | ev.mmap.len = map->end - ev.mmap.start; |
332 | ev.mmap.pid = machine->pid; | 341 | ev.mmap.pid = machine->pid; |
333 | 342 | ||
334 | return process(&ev, session); | 343 | return process(&ev, &synth_sample, session); |
335 | } | 344 | } |
336 | 345 | ||
337 | static void thread__comm_adjust(struct thread *self, struct hists *hists) | 346 | static void thread__comm_adjust(struct thread *self, struct hists *hists) |
@@ -361,7 +370,8 @@ static int thread__set_comm_adjust(struct thread *self, const char *comm, | |||
361 | return 0; | 370 | return 0; |
362 | } | 371 | } |
363 | 372 | ||
364 | int event__process_comm(event_t *self, struct perf_session *session) | 373 | int event__process_comm(event_t *self, struct sample_data *sample __used, |
374 | struct perf_session *session) | ||
365 | { | 375 | { |
366 | struct thread *thread = perf_session__findnew(session, self->comm.tid); | 376 | struct thread *thread = perf_session__findnew(session, self->comm.tid); |
367 | 377 | ||
@@ -376,7 +386,8 @@ int event__process_comm(event_t *self, struct perf_session *session) | |||
376 | return 0; | 386 | return 0; |
377 | } | 387 | } |
378 | 388 | ||
379 | int event__process_lost(event_t *self, struct perf_session *session) | 389 | int event__process_lost(event_t *self, struct sample_data *sample __used, |
390 | struct perf_session *session) | ||
380 | { | 391 | { |
381 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); | 392 | dump_printf(": id:%Ld: lost:%Ld\n", self->lost.id, self->lost.lost); |
382 | session->hists.stats.total_lost += self->lost.lost; | 393 | session->hists.stats.total_lost += self->lost.lost; |
@@ -485,7 +496,8 @@ out_problem: | |||
485 | return -1; | 496 | return -1; |
486 | } | 497 | } |
487 | 498 | ||
488 | int event__process_mmap(event_t *self, struct perf_session *session) | 499 | int event__process_mmap(event_t *self, struct sample_data *sample __used, |
500 | struct perf_session *session) | ||
489 | { | 501 | { |
490 | struct machine *machine; | 502 | struct machine *machine; |
491 | struct thread *thread; | 503 | struct thread *thread; |
@@ -526,7 +538,8 @@ out_problem: | |||
526 | return 0; | 538 | return 0; |
527 | } | 539 | } |
528 | 540 | ||
529 | int event__process_task(event_t *self, struct perf_session *session) | 541 | int event__process_task(event_t *self, struct sample_data *sample __used, |
542 | struct perf_session *session) | ||
530 | { | 543 | { |
531 | struct thread *thread = perf_session__findnew(session, self->fork.tid); | 544 | struct thread *thread = perf_session__findnew(session, self->fork.tid); |
532 | struct thread *parent = perf_session__findnew(session, self->fork.ptid); | 545 | struct thread *parent = perf_session__findnew(session, self->fork.ptid); |
@@ -548,18 +561,19 @@ int event__process_task(event_t *self, struct perf_session *session) | |||
548 | return 0; | 561 | return 0; |
549 | } | 562 | } |
550 | 563 | ||
551 | int event__process(event_t *event, struct perf_session *session) | 564 | int event__process(event_t *event, struct sample_data *sample, |
565 | struct perf_session *session) | ||
552 | { | 566 | { |
553 | switch (event->header.type) { | 567 | switch (event->header.type) { |
554 | case PERF_RECORD_COMM: | 568 | case PERF_RECORD_COMM: |
555 | event__process_comm(event, session); | 569 | event__process_comm(event, sample, session); |
556 | break; | 570 | break; |
557 | case PERF_RECORD_MMAP: | 571 | case PERF_RECORD_MMAP: |
558 | event__process_mmap(event, session); | 572 | event__process_mmap(event, sample, session); |
559 | break; | 573 | break; |
560 | case PERF_RECORD_FORK: | 574 | case PERF_RECORD_FORK: |
561 | case PERF_RECORD_EXIT: | 575 | case PERF_RECORD_EXIT: |
562 | event__process_task(event, session); | 576 | event__process_task(event, sample, session); |
563 | break; | 577 | break; |
564 | default: | 578 | default: |
565 | break; | 579 | break; |
@@ -674,32 +688,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, | |||
674 | symbol_filter_t filter) | 688 | symbol_filter_t filter) |
675 | { | 689 | { |
676 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 690 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
677 | struct thread *thread; | 691 | struct thread *thread = perf_session__findnew(session, self->ip.pid); |
678 | |||
679 | event__parse_sample(self, session->sample_type, data); | ||
680 | 692 | ||
681 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n", | ||
682 | self->header.misc, data->pid, data->tid, data->ip, | ||
683 | data->period, data->cpu); | ||
684 | |||
685 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
686 | unsigned int i; | ||
687 | |||
688 | dump_printf("... chain: nr:%Lu\n", data->callchain->nr); | ||
689 | |||
690 | if (!ip_callchain__valid(data->callchain, self)) { | ||
691 | pr_debug("call-chain problem with event, " | ||
692 | "skipping it.\n"); | ||
693 | goto out_filtered; | ||
694 | } | ||
695 | |||
696 | if (dump_trace) { | ||
697 | for (i = 0; i < data->callchain->nr; i++) | ||
698 | dump_printf("..... %2d: %016Lx\n", | ||
699 | i, data->callchain->ips[i]); | ||
700 | } | ||
701 | } | ||
702 | thread = perf_session__findnew(session, self->ip.pid); | ||
703 | if (thread == NULL) | 693 | if (thread == NULL) |
704 | return -1; | 694 | return -1; |
705 | 695 | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 8e790dae7026..08c400b83d57 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -135,7 +135,10 @@ void event__print_totals(void); | |||
135 | 135 | ||
136 | struct perf_session; | 136 | struct perf_session; |
137 | 137 | ||
138 | typedef int (*event__handler_t)(event_t *event, struct perf_session *session); | 138 | typedef int (*event__handler_synth_t)(event_t *event, |
139 | struct perf_session *session); | ||
140 | typedef int (*event__handler_t)(event_t *event, struct sample_data *sample, | ||
141 | struct perf_session *session); | ||
139 | 142 | ||
140 | int event__synthesize_thread(pid_t pid, event__handler_t process, | 143 | int event__synthesize_thread(pid_t pid, event__handler_t process, |
141 | struct perf_session *session); | 144 | struct perf_session *session); |
@@ -150,11 +153,16 @@ int event__synthesize_modules(event__handler_t process, | |||
150 | struct perf_session *session, | 153 | struct perf_session *session, |
151 | struct machine *machine); | 154 | struct machine *machine); |
152 | 155 | ||
153 | int event__process_comm(event_t *self, struct perf_session *session); | 156 | int event__process_comm(event_t *self, struct sample_data *sample, |
154 | int event__process_lost(event_t *self, struct perf_session *session); | 157 | struct perf_session *session); |
155 | int event__process_mmap(event_t *self, struct perf_session *session); | 158 | int event__process_lost(event_t *self, struct sample_data *sample, |
156 | int event__process_task(event_t *self, struct perf_session *session); | 159 | struct perf_session *session); |
157 | int event__process(event_t *event, struct perf_session *session); | 160 | int event__process_mmap(event_t *self, struct sample_data *sample, |
161 | struct perf_session *session); | ||
162 | int event__process_task(event_t *self, struct sample_data *sample, | ||
163 | struct perf_session *session); | ||
164 | int event__process(event_t *event, struct sample_data *sample, | ||
165 | struct perf_session *session); | ||
158 | 166 | ||
159 | struct addr_location; | 167 | struct addr_location; |
160 | int event__preprocess_sample(const event_t *self, struct perf_session *session, | 168 | int event__preprocess_sample(const event_t *self, struct perf_session *session, |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index f65d7dc127b6..fe652f3b0aa7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -993,15 +993,14 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, | |||
993 | ev->attr.header.type = PERF_RECORD_HEADER_ATTR; | 993 | ev->attr.header.type = PERF_RECORD_HEADER_ATTR; |
994 | ev->attr.header.size = size; | 994 | ev->attr.header.size = size; |
995 | 995 | ||
996 | err = process(ev, session); | 996 | err = process(ev, NULL, session); |
997 | 997 | ||
998 | free(ev); | 998 | free(ev); |
999 | 999 | ||
1000 | return err; | 1000 | return err; |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | int event__synthesize_attrs(struct perf_header *self, | 1003 | int event__synthesize_attrs(struct perf_header *self, event__handler_t process, |
1004 | event__handler_t process, | ||
1005 | struct perf_session *session) | 1004 | struct perf_session *session) |
1006 | { | 1005 | { |
1007 | struct perf_header_attr *attr; | 1006 | struct perf_header_attr *attr; |
@@ -1071,7 +1070,7 @@ int event__synthesize_event_type(u64 event_id, char *name, | |||
1071 | ev.event_type.header.size = sizeof(ev.event_type) - | 1070 | ev.event_type.header.size = sizeof(ev.event_type) - |
1072 | (sizeof(ev.event_type.event_type.name) - size); | 1071 | (sizeof(ev.event_type.event_type.name) - size); |
1073 | 1072 | ||
1074 | err = process(&ev, session); | 1073 | err = process(&ev, NULL, session); |
1075 | 1074 | ||
1076 | return err; | 1075 | return err; |
1077 | } | 1076 | } |
@@ -1126,7 +1125,7 @@ int event__synthesize_tracing_data(int fd, struct perf_event_attr *pattrs, | |||
1126 | ev.tracing_data.header.size = sizeof(ev.tracing_data); | 1125 | ev.tracing_data.header.size = sizeof(ev.tracing_data); |
1127 | ev.tracing_data.size = aligned_size; | 1126 | ev.tracing_data.size = aligned_size; |
1128 | 1127 | ||
1129 | process(&ev, session); | 1128 | process(&ev, NULL, session); |
1130 | 1129 | ||
1131 | err = read_tracing_data(fd, pattrs, nb_events); | 1130 | err = read_tracing_data(fd, pattrs, nb_events); |
1132 | write_padded(fd, NULL, 0, padding); | 1131 | write_padded(fd, NULL, 0, padding); |
@@ -1186,7 +1185,7 @@ int event__synthesize_build_id(struct dso *pos, u16 misc, | |||
1186 | ev.build_id.header.size = sizeof(ev.build_id) + len; | 1185 | ev.build_id.header.size = sizeof(ev.build_id) + len; |
1187 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); | 1186 | memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); |
1188 | 1187 | ||
1189 | err = process(&ev, session); | 1188 | err = process(&ev, NULL, session); |
1190 | 1189 | ||
1191 | return err; | 1190 | return err; |
1192 | } | 1191 | } |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 587d375d3430..ee789856a8c9 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -52,8 +52,10 @@ struct sym_priv { | |||
52 | struct events_stats { | 52 | struct events_stats { |
53 | u64 total_period; | 53 | u64 total_period; |
54 | u64 total_lost; | 54 | u64 total_lost; |
55 | u64 total_invalid_chains; | ||
55 | u32 nr_events[PERF_RECORD_HEADER_MAX]; | 56 | u32 nr_events[PERF_RECORD_HEADER_MAX]; |
56 | u32 nr_unknown_events; | 57 | u32 nr_unknown_events; |
58 | u32 nr_invalid_chains; | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | enum hist_column { | 61 | enum hist_column { |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 52672dad1fe9..08ec018966a8 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -70,6 +70,11 @@ void perf_session__update_sample_type(struct perf_session *self) | |||
70 | self->sample_type = perf_header__sample_type(&self->header); | 70 | self->sample_type = perf_header__sample_type(&self->header); |
71 | } | 71 | } |
72 | 72 | ||
73 | void perf_session__set_sample_type(struct perf_session *session, u64 type) | ||
74 | { | ||
75 | session->sample_type = type; | ||
76 | } | ||
77 | |||
73 | int perf_session__create_kernel_maps(struct perf_session *self) | 78 | int perf_session__create_kernel_maps(struct perf_session *self) |
74 | { | 79 | { |
75 | int ret = machine__create_kernel_maps(&self->host_machine); | 80 | int ret = machine__create_kernel_maps(&self->host_machine); |
@@ -240,7 +245,15 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self, | |||
240 | return syms; | 245 | return syms; |
241 | } | 246 | } |
242 | 247 | ||
248 | static int process_event_synth_stub(event_t *event __used, | ||
249 | struct perf_session *session __used) | ||
250 | { | ||
251 | dump_printf(": unhandled!\n"); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
243 | static int process_event_stub(event_t *event __used, | 255 | static int process_event_stub(event_t *event __used, |
256 | struct sample_data *sample __used, | ||
244 | struct perf_session *session __used) | 257 | struct perf_session *session __used) |
245 | { | 258 | { |
246 | dump_printf(": unhandled!\n"); | 259 | dump_printf(": unhandled!\n"); |
@@ -280,13 +293,13 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) | |||
280 | if (handler->unthrottle == NULL) | 293 | if (handler->unthrottle == NULL) |
281 | handler->unthrottle = process_event_stub; | 294 | handler->unthrottle = process_event_stub; |
282 | if (handler->attr == NULL) | 295 | if (handler->attr == NULL) |
283 | handler->attr = process_event_stub; | 296 | handler->attr = process_event_synth_stub; |
284 | if (handler->event_type == NULL) | 297 | if (handler->event_type == NULL) |
285 | handler->event_type = process_event_stub; | 298 | handler->event_type = process_event_synth_stub; |
286 | if (handler->tracing_data == NULL) | 299 | if (handler->tracing_data == NULL) |
287 | handler->tracing_data = process_event_stub; | 300 | handler->tracing_data = process_event_synth_stub; |
288 | if (handler->build_id == NULL) | 301 | if (handler->build_id == NULL) |
289 | handler->build_id = process_event_stub; | 302 | handler->build_id = process_event_synth_stub; |
290 | if (handler->finished_round == NULL) { | 303 | if (handler->finished_round == NULL) { |
291 | if (handler->ordered_samples) | 304 | if (handler->ordered_samples) |
292 | handler->finished_round = process_finished_round; | 305 | handler->finished_round = process_finished_round; |
@@ -419,6 +432,7 @@ static void flush_sample_queue(struct perf_session *s, | |||
419 | struct ordered_samples *os = &s->ordered_samples; | 432 | struct ordered_samples *os = &s->ordered_samples; |
420 | struct list_head *head = &os->samples; | 433 | struct list_head *head = &os->samples; |
421 | struct sample_queue *tmp, *iter; | 434 | struct sample_queue *tmp, *iter; |
435 | struct sample_data sample; | ||
422 | u64 limit = os->next_flush; | 436 | u64 limit = os->next_flush; |
423 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; | 437 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; |
424 | 438 | ||
@@ -429,7 +443,8 @@ static void flush_sample_queue(struct perf_session *s, | |||
429 | if (iter->timestamp > limit) | 443 | if (iter->timestamp > limit) |
430 | break; | 444 | break; |
431 | 445 | ||
432 | ops->sample(iter->event, s); | 446 | event__parse_sample(iter->event, s->sample_type, &sample); |
447 | ops->sample(iter->event, &sample, s); | ||
433 | 448 | ||
434 | os->last_flush = iter->timestamp; | 449 | os->last_flush = iter->timestamp; |
435 | list_del(&iter->list); | 450 | list_del(&iter->list); |
@@ -578,20 +593,29 @@ static int queue_sample_event(event_t *event, struct sample_data *data, | |||
578 | return 0; | 593 | return 0; |
579 | } | 594 | } |
580 | 595 | ||
581 | static int perf_session__process_sample(event_t *event, struct perf_session *s, | 596 | static int perf_session__process_sample(event_t *event, |
597 | struct sample_data *sample, | ||
598 | struct perf_session *s, | ||
582 | struct perf_event_ops *ops) | 599 | struct perf_event_ops *ops) |
583 | { | 600 | { |
584 | struct sample_data data; | ||
585 | |||
586 | if (!ops->ordered_samples) | 601 | if (!ops->ordered_samples) |
587 | return ops->sample(event, s); | 602 | return ops->sample(event, sample, s); |
603 | |||
604 | queue_sample_event(event, sample, s); | ||
605 | return 0; | ||
606 | } | ||
588 | 607 | ||
589 | bzero(&data, sizeof(struct sample_data)); | 608 | static void callchain__dump(struct sample_data *sample) |
590 | event__parse_sample(event, s->sample_type, &data); | 609 | { |
610 | unsigned int i; | ||
591 | 611 | ||
592 | queue_sample_event(event, &data, s); | 612 | if (!dump_trace) |
613 | return; | ||
593 | 614 | ||
594 | return 0; | 615 | printf("... chain: nr:%Lu\n", sample->callchain->nr); |
616 | |||
617 | for (i = 0; i < sample->callchain->nr; i++) | ||
618 | printf("..... %2d: %016Lx\n", i, sample->callchain->ips[i]); | ||
595 | } | 619 | } |
596 | 620 | ||
597 | static int perf_session__process_event(struct perf_session *self, | 621 | static int perf_session__process_event(struct perf_session *self, |
@@ -599,8 +623,16 @@ static int perf_session__process_event(struct perf_session *self, | |||
599 | struct perf_event_ops *ops, | 623 | struct perf_event_ops *ops, |
600 | u64 file_offset) | 624 | u64 file_offset) |
601 | { | 625 | { |
626 | struct sample_data sample; | ||
627 | |||
602 | trace_event(event); | 628 | trace_event(event); |
603 | 629 | ||
630 | if (self->header.needs_swap && event__swap_ops[event->header.type]) | ||
631 | event__swap_ops[event->header.type](event); | ||
632 | |||
633 | if (event->header.type == PERF_RECORD_SAMPLE) | ||
634 | event__parse_sample(event, self->sample_type, &sample); | ||
635 | |||
604 | if (event->header.type < PERF_RECORD_HEADER_MAX) { | 636 | if (event->header.type < PERF_RECORD_HEADER_MAX) { |
605 | dump_printf("%#Lx [%#x]: PERF_RECORD_%s", | 637 | dump_printf("%#Lx [%#x]: PERF_RECORD_%s", |
606 | file_offset, event->header.size, | 638 | file_offset, event->header.size, |
@@ -608,28 +640,41 @@ static int perf_session__process_event(struct perf_session *self, | |||
608 | hists__inc_nr_events(&self->hists, event->header.type); | 640 | hists__inc_nr_events(&self->hists, event->header.type); |
609 | } | 641 | } |
610 | 642 | ||
611 | if (self->header.needs_swap && event__swap_ops[event->header.type]) | ||
612 | event__swap_ops[event->header.type](event); | ||
613 | |||
614 | switch (event->header.type) { | 643 | switch (event->header.type) { |
615 | case PERF_RECORD_SAMPLE: | 644 | case PERF_RECORD_SAMPLE: |
616 | return perf_session__process_sample(event, self, ops); | 645 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc, |
646 | sample.pid, sample.tid, sample.ip, sample.period); | ||
647 | |||
648 | if (self->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
649 | if (!ip_callchain__valid(sample.callchain, event)) { | ||
650 | pr_debug("call-chain problem with event, " | ||
651 | "skipping it.\n"); | ||
652 | ++self->hists.stats.nr_invalid_chains; | ||
653 | self->hists.stats.total_invalid_chains += sample.period; | ||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | callchain__dump(&sample); | ||
658 | } | ||
659 | |||
660 | return perf_session__process_sample(event, &sample, self, ops); | ||
661 | |||
617 | case PERF_RECORD_MMAP: | 662 | case PERF_RECORD_MMAP: |
618 | return ops->mmap(event, self); | 663 | return ops->mmap(event, &sample, self); |
619 | case PERF_RECORD_COMM: | 664 | case PERF_RECORD_COMM: |
620 | return ops->comm(event, self); | 665 | return ops->comm(event, &sample, self); |
621 | case PERF_RECORD_FORK: | 666 | case PERF_RECORD_FORK: |
622 | return ops->fork(event, self); | 667 | return ops->fork(event, &sample, self); |
623 | case PERF_RECORD_EXIT: | 668 | case PERF_RECORD_EXIT: |
624 | return ops->exit(event, self); | 669 | return ops->exit(event, &sample, self); |
625 | case PERF_RECORD_LOST: | 670 | case PERF_RECORD_LOST: |
626 | return ops->lost(event, self); | 671 | return ops->lost(event, &sample, self); |
627 | case PERF_RECORD_READ: | 672 | case PERF_RECORD_READ: |
628 | return ops->read(event, self); | 673 | return ops->read(event, &sample, self); |
629 | case PERF_RECORD_THROTTLE: | 674 | case PERF_RECORD_THROTTLE: |
630 | return ops->throttle(event, self); | 675 | return ops->throttle(event, &sample, self); |
631 | case PERF_RECORD_UNTHROTTLE: | 676 | case PERF_RECORD_UNTHROTTLE: |
632 | return ops->unthrottle(event, self); | 677 | return ops->unthrottle(event, &sample, self); |
633 | case PERF_RECORD_HEADER_ATTR: | 678 | case PERF_RECORD_HEADER_ATTR: |
634 | return ops->attr(event, self); | 679 | return ops->attr(event, self); |
635 | case PERF_RECORD_HEADER_EVENT_TYPE: | 680 | case PERF_RECORD_HEADER_EVENT_TYPE: |
@@ -894,6 +939,14 @@ out_err: | |||
894 | session->hists.stats.nr_unknown_events); | 939 | session->hists.stats.nr_unknown_events); |
895 | } | 940 | } |
896 | 941 | ||
942 | if (session->hists.stats.nr_invalid_chains != 0) { | ||
943 | ui__warning("Found invalid callchains!\n\n" | ||
944 | "%u out of %u events were discarded for this reason.\n\n" | ||
945 | "Consider reporting to linux-kernel@vger.kernel.org.\n\n", | ||
946 | session->hists.stats.nr_invalid_chains, | ||
947 | session->hists.stats.nr_events[PERF_RECORD_SAMPLE]); | ||
948 | } | ||
949 | |||
897 | perf_session_free_sample_buffers(session); | 950 | perf_session_free_sample_buffers(session); |
898 | return err; | 951 | return err; |
899 | } | 952 | } |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 5bf6efa3788a..4578f86a6209 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -54,7 +54,9 @@ struct perf_session { | |||
54 | 54 | ||
55 | struct perf_event_ops; | 55 | struct perf_event_ops; |
56 | 56 | ||
57 | typedef int (*event_op)(event_t *self, struct perf_session *session); | 57 | typedef int (*event_op)(event_t *self, struct sample_data *sample, |
58 | struct perf_session *session); | ||
59 | typedef int (*event_synth_op)(event_t *self, struct perf_session *session); | ||
58 | typedef int (*event_op2)(event_t *self, struct perf_session *session, | 60 | typedef int (*event_op2)(event_t *self, struct perf_session *session, |
59 | struct perf_event_ops *ops); | 61 | struct perf_event_ops *ops); |
60 | 62 | ||
@@ -67,8 +69,8 @@ struct perf_event_ops { | |||
67 | lost, | 69 | lost, |
68 | read, | 70 | read, |
69 | throttle, | 71 | throttle, |
70 | unthrottle, | 72 | unthrottle; |
71 | attr, | 73 | event_synth_op attr, |
72 | event_type, | 74 | event_type, |
73 | tracing_data, | 75 | tracing_data, |
74 | build_id; | 76 | build_id; |
@@ -104,6 +106,7 @@ int perf_session__create_kernel_maps(struct perf_session *self); | |||
104 | 106 | ||
105 | int do_read(int fd, void *buf, size_t size); | 107 | int do_read(int fd, void *buf, size_t size); |
106 | void perf_session__update_sample_type(struct perf_session *self); | 108 | void perf_session__update_sample_type(struct perf_session *self); |
109 | void perf_session__set_sample_type(struct perf_session *session, u64 type); | ||
107 | void perf_session__remove_thread(struct perf_session *self, struct thread *th); | 110 | void perf_session__remove_thread(struct perf_session *self, struct thread *th); |
108 | 111 | ||
109 | static inline | 112 | static inline |