aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-12-02 11:10:21 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-12-04 20:05:19 -0500
commit640c03ce837fe8d4b56342aba376ea0da3960459 (patch)
treee954290ccacf032ab4d9052eac01710fda1b7fab
parentc980d1091810df13f21aabbce545fd98f545bbf7 (diff)
perf session: Parse sample earlier
At perf_session__process_event, so that we reduce the number of lines in eache tool sample processing routine that now receives a sample_data pointer already parsed. This will also be useful in the next patch, where we'll allow sample the identity fields in MMAP, FORK, EXIT, etc, when it will be possible to see (cpu, timestamp) just after before every event. Also validate callchains in perf_session__process_event, i.e. as early as possible, and keep a counter of the number of events discarded due to invalid callchains, warning the user about it if it happens. There is an assumption that was kept that all events have the same sample_type, that will be dealt with in the future, when this preexisting limitation will be removed. Tested-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Ian Munsie <imunsie@au1.ibm.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <1291318772-30880-4-git-send-email-acme@infradead.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/builtin-annotate.c6
-rw-r--r--tools/perf/builtin-diff.c11
-rw-r--r--tools/perf/builtin-inject.c39
-rw-r--r--tools/perf/builtin-kmem.c21
-rw-r--r--tools/perf/builtin-lock.c12
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/builtin-report.c15
-rw-r--r--tools/perf/builtin-sched.c21
-rw-r--r--tools/perf/builtin-script.c34
-rw-r--r--tools/perf/builtin-timechart.c40
-rw-r--r--tools/perf/builtin-top.c4
-rw-r--r--tools/perf/util/build-id.c7
-rw-r--r--tools/perf/util/event.c66
-rw-r--r--tools/perf/util/event.h20
-rw-r--r--tools/perf/util/header.c11
-rw-r--r--tools/perf/util/hist.h2
-rw-r--r--tools/perf/util/session.c103
-rw-r--r--tools/perf/util/session.h9
18 files changed, 236 insertions, 192 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6d5604d8df9..569a2761b90 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
61static int process_sample_event(event_t *event, struct perf_session *session) 61static 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 221b823bc26..5e1a043aae0 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
33static int diff__process_sample_event(event_t *event, struct perf_session *session) 33static 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 8e3e47b064c..4b66b857941 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
16static char const *input_name = "-"; 16static char const *input_name = "-";
17static bool inject_build_ids; 17static bool inject_build_ids;
18 18
19static int event__repipe(event_t *event __used, 19static 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
39static int event__repipe_mmap(event_t *self, struct perf_session *session) 39static 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
45static 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
49static int event__repipe_task(event_t *self, struct perf_session *session) 56static 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
114static int event__inject_buildid(event_t *event, struct perf_session *session) 122static 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
148repipe: 157repipe:
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
169extern volatile int session_done; 178extern volatile int session_done;
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 31f60a2535e..d0a652e9c70 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
307static int process_sample_event(event_t *event, struct perf_session *session) 307static 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 8452a2ae219..92d3da52a5c 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
837static int process_sample_event(event_t *self, struct perf_session *s) 837static 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 024e1441d76..b34de9291c2 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
37static u64 user_interval = ULLONG_MAX; 37static u64 user_interval = ULLONG_MAX;
38static u64 default_interval = 0; 38static u64 default_interval = 0;
39static u64 sample_type;
39 40
40static int nr_cpus = 0; 41static int nr_cpus = 0;
41static unsigned int page_size; 42static unsigned int page_size;
@@ -129,6 +130,7 @@ static void write_output(void *buf, size_t size)
129} 130}
130 131
131static int process_synthesized_event(event_t *event, 132static 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 5de405d4523..904519fba43 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
153static int process_sample_event(event_t *event, struct perf_session *session) 153static 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
183static int process_read_event(event_t *event, struct perf_session *session __used) 183static 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 26523c93979..73d1e30b0fe 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
1609static int process_sample_event(event_t *event, struct perf_session *session) 1609static 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 4539551ab40..683a30572cc 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -63,22 +63,11 @@ static int cleanup_scripting(void)
63 63
64static char const *input_name = "perf.data"; 64static char const *input_name = "perf.data";
65 65
66static int process_sample_event(event_t *event, struct perf_session *session) 66static 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
113static u64 nr_lost; 102static u64 nr_lost;
114 103
115static int process_lost_event(event_t *event, struct perf_session *session __used) 104static 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 9bcc38f0b70..1f158dc0334 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -272,19 +272,22 @@ static int cpus_cstate_state[MAX_CPUS];
272static u64 cpus_pstate_start_times[MAX_CPUS]; 272static u64 cpus_pstate_start_times[MAX_CPUS];
273static u64 cpus_pstate_state[MAX_CPUS]; 273static u64 cpus_pstate_state[MAX_CPUS];
274 274
275static int process_comm_event(event_t *event, struct perf_session *session __used) 275static 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
281static int process_fork_event(event_t *event, struct perf_session *session __used) 282static 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
287static int process_exit_event(event_t *event, struct perf_session *session __used) 289static 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
473static int process_sample_event(event_t *event, struct perf_session *session) 476static 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 3d2b47d5121..5aa29e1e855 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 e437edb7241..deffb8c9607 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
17static int build_id__mark_dso_hit(event_t *event, struct perf_session *session) 17static 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
38static int event__exit_del_thread(event_t *self, struct perf_session *session) 40static 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 7260db75b93..34510f44197 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
27static 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
27static pid_t event__synthesize_comm(pid_t pid, int full, 36static 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
337static void thread__comm_adjust(struct thread *self, struct hists *hists) 346static 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
364int event__process_comm(event_t *self, struct perf_session *session) 373int 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
379int event__process_lost(event_t *self, struct perf_session *session) 389int 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
488int event__process_mmap(event_t *self, struct perf_session *session) 499int 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
529int event__process_task(event_t *self, struct perf_session *session) 541int 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
551int event__process(event_t *event, struct perf_session *session) 564int 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 8e790dae702..08c400b83d5 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -135,7 +135,10 @@ void event__print_totals(void);
135 135
136struct perf_session; 136struct perf_session;
137 137
138typedef int (*event__handler_t)(event_t *event, struct perf_session *session); 138typedef int (*event__handler_synth_t)(event_t *event,
139 struct perf_session *session);
140typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
141 struct perf_session *session);
139 142
140int event__synthesize_thread(pid_t pid, event__handler_t process, 143int 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
153int event__process_comm(event_t *self, struct perf_session *session); 156int event__process_comm(event_t *self, struct sample_data *sample,
154int event__process_lost(event_t *self, struct perf_session *session); 157 struct perf_session *session);
155int event__process_mmap(event_t *self, struct perf_session *session); 158int event__process_lost(event_t *self, struct sample_data *sample,
156int event__process_task(event_t *self, struct perf_session *session); 159 struct perf_session *session);
157int event__process(event_t *event, struct perf_session *session); 160int event__process_mmap(event_t *self, struct sample_data *sample,
161 struct perf_session *session);
162int event__process_task(event_t *self, struct sample_data *sample,
163 struct perf_session *session);
164int event__process(event_t *event, struct sample_data *sample,
165 struct perf_session *session);
158 166
159struct addr_location; 167struct addr_location;
160int event__preprocess_sample(const event_t *self, struct perf_session *session, 168int 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 f65d7dc127b..fe652f3b0aa 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
1003int event__synthesize_attrs(struct perf_header *self, 1003int 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 587d375d343..ee789856a8c 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -52,8 +52,10 @@ struct sym_priv {
52struct events_stats { 52struct 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
59enum hist_column { 61enum hist_column {
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 52672dad1fe..08ec018966a 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
73void perf_session__set_sample_type(struct perf_session *session, u64 type)
74{
75 session->sample_type = type;
76}
77
73int perf_session__create_kernel_maps(struct perf_session *self) 78int 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
248static 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
243static int process_event_stub(event_t *event __used, 255static 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
581static int perf_session__process_sample(event_t *event, struct perf_session *s, 596static 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)); 608static 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
597static int perf_session__process_event(struct perf_session *self, 621static 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 5bf6efa3788..4578f86a620 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -54,7 +54,9 @@ struct perf_session {
54 54
55struct perf_event_ops; 55struct perf_event_ops;
56 56
57typedef int (*event_op)(event_t *self, struct perf_session *session); 57typedef int (*event_op)(event_t *self, struct sample_data *sample,
58 struct perf_session *session);
59typedef int (*event_synth_op)(event_t *self, struct perf_session *session);
58typedef int (*event_op2)(event_t *self, struct perf_session *session, 60typedef 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
105int do_read(int fd, void *buf, size_t size); 107int do_read(int fd, void *buf, size_t size);
106void perf_session__update_sample_type(struct perf_session *self); 108void perf_session__update_sample_type(struct perf_session *self);
109void perf_session__set_sample_type(struct perf_session *session, u64 type);
107void perf_session__remove_thread(struct perf_session *self, struct thread *th); 110void perf_session__remove_thread(struct perf_session *self, struct thread *th);
108 111
109static inline 112static inline