diff options
author | Ian Munsie <imunsie@au1.ibm.com> | 2010-12-09 22:09:16 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-12-21 17:17:51 -0500 |
commit | 21ef97f05a7da5bc23b26cb34d6746f83ca9bf20 (patch) | |
tree | c47c09c178f7929f01dcb7b302ceed21f3758ded /tools | |
parent | 7639dae0ca11038286bbbcda05f2bef601c1eb8d (diff) |
perf session: Fallback to unordered processing if no sample_id_all
If we are running the new perf on an old kernel without support for
sample_id_all, we should fall back to the old unordered processing of
events. If we didn't than we would *always* process events without
timestamps out of order, whether or not we hit a reordering race. In
other words, instead of there being a chance of not attributing samples
correctly, we would guarantee that samples would not be attributed.
While processing all events without timestamps before events with
timestamps may seem like an intuitive solution, it falls down as
PERF_RECORD_EXIT events would also be processed before any samples.
Even with a workaround for that case, samples before/after an exec would
not be attributed correctly.
This patch allows commands to indicate whether they need to fall back to
unordered processing, so that commands that do not care about timestamps
on every event will not be affected. If we do fallback, this will print
out a warning if report -D was invoked.
This patch adds the test in perf_session__new so that we only need to
test once per session. Commands that do not use an event_ops (such as
record and top) can simply pass NULL in it's place.
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <1291951882-sup-6069@au1.ibm.com>
Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-buildid-list.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-inject.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-lock.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 2 | ||||
-rw-r--r-- | tools/perf/util/session.c | 11 | ||||
-rw-r--r-- | tools/perf/util/session.h | 5 |
14 files changed, 31 insertions, 15 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 569a2761b90a..48dbab4b482f 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -382,7 +382,7 @@ static int __cmd_annotate(void) | |||
382 | int ret; | 382 | int ret; |
383 | struct perf_session *session; | 383 | struct perf_session *session; |
384 | 384 | ||
385 | session = perf_session__new(input_name, O_RDONLY, force, false); | 385 | session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); |
386 | if (session == NULL) | 386 | if (session == NULL) |
387 | return -ENOMEM; | 387 | return -ENOMEM; |
388 | 388 | ||
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 44a47e13bd67..3b06f9ca2638 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c | |||
@@ -39,7 +39,8 @@ static int __cmd_buildid_list(void) | |||
39 | int err = -1; | 39 | int err = -1; |
40 | struct perf_session *session; | 40 | struct perf_session *session; |
41 | 41 | ||
42 | session = perf_session__new(input_name, O_RDONLY, force, false); | 42 | session = perf_session__new(input_name, O_RDONLY, force, false, |
43 | &build_id__mark_dso_hit_ops); | ||
43 | if (session == NULL) | 44 | if (session == NULL) |
44 | return -1; | 45 | return -1; |
45 | 46 | ||
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 5e1a043aae03..af84e1c0519d 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -142,8 +142,8 @@ static int __cmd_diff(void) | |||
142 | int ret, i; | 142 | int ret, i; |
143 | struct perf_session *session[2]; | 143 | struct perf_session *session[2]; |
144 | 144 | ||
145 | session[0] = perf_session__new(input_old, O_RDONLY, force, false); | 145 | session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops); |
146 | session[1] = perf_session__new(input_new, O_RDONLY, force, false); | 146 | session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops); |
147 | if (session[0] == NULL || session[1] == NULL) | 147 | if (session[0] == NULL || session[1] == NULL) |
148 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | 149 | ||
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 4b66b8579410..0c78ffa7bf67 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -196,7 +196,7 @@ static int __cmd_inject(void) | |||
196 | inject_ops.tracing_data = event__repipe_tracing_data; | 196 | inject_ops.tracing_data = event__repipe_tracing_data; |
197 | } | 197 | } |
198 | 198 | ||
199 | session = perf_session__new(input_name, O_RDONLY, false, true); | 199 | session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops); |
200 | if (session == NULL) | 200 | if (session == NULL) |
201 | return -ENOMEM; | 201 | return -ENOMEM; |
202 | 202 | ||
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index c9620ff6496f..def7ddc2fd4f 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -481,7 +481,8 @@ static void sort_result(void) | |||
481 | static int __cmd_kmem(void) | 481 | static int __cmd_kmem(void) |
482 | { | 482 | { |
483 | int err = -EINVAL; | 483 | int err = -EINVAL; |
484 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); | 484 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, |
485 | 0, false, &event_ops); | ||
485 | if (session == NULL) | 486 | if (session == NULL) |
486 | return -ENOMEM; | 487 | return -ENOMEM; |
487 | 488 | ||
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index b41b4492b1cc..b9c6e5432971 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c | |||
@@ -858,7 +858,7 @@ static struct perf_event_ops eops = { | |||
858 | 858 | ||
859 | static int read_events(void) | 859 | static int read_events(void) |
860 | { | 860 | { |
861 | session = perf_session__new(input_name, O_RDONLY, 0, false); | 861 | session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); |
862 | if (!session) | 862 | if (!session) |
863 | die("Initializing perf session failed\n"); | 863 | die("Initializing perf session failed\n"); |
864 | 864 | ||
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index e9be6ae87a27..efd1b3c3d4a0 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -572,7 +572,7 @@ static int __cmd_record(int argc, const char **argv) | |||
572 | } | 572 | } |
573 | 573 | ||
574 | session = perf_session__new(output_name, O_WRONLY, | 574 | session = perf_session__new(output_name, O_WRONLY, |
575 | write_mode == WRITE_FORCE, false); | 575 | write_mode == WRITE_FORCE, false, NULL); |
576 | if (session == NULL) { | 576 | if (session == NULL) { |
577 | pr_err("Not enough memory for reading perf file header\n"); | 577 | pr_err("Not enough memory for reading perf file header\n"); |
578 | return -1; | 578 | return -1; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b6a2a899aa8f..fd4c4500cd15 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -308,7 +308,7 @@ static int __cmd_report(void) | |||
308 | 308 | ||
309 | signal(SIGINT, sig_handler); | 309 | signal(SIGINT, sig_handler); |
310 | 310 | ||
311 | session = perf_session__new(input_name, O_RDONLY, force, false); | 311 | session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); |
312 | if (session == NULL) | 312 | if (session == NULL) |
313 | return -ENOMEM; | 313 | return -ENOMEM; |
314 | 314 | ||
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index c7753940aea0..7a4ebeb8b016 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1643,7 +1643,8 @@ static struct perf_event_ops event_ops = { | |||
1643 | static int read_events(void) | 1643 | static int read_events(void) |
1644 | { | 1644 | { |
1645 | int err = -EINVAL; | 1645 | int err = -EINVAL; |
1646 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); | 1646 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, |
1647 | 0, false, &event_ops); | ||
1647 | if (session == NULL) | 1648 | if (session == NULL) |
1648 | return -ENOMEM; | 1649 | return -ENOMEM; |
1649 | 1650 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 54f1ea808db5..6ef65c04ab9a 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -779,7 +779,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) | |||
779 | if (!script_name) | 779 | if (!script_name) |
780 | setup_pager(); | 780 | setup_pager(); |
781 | 781 | ||
782 | session = perf_session__new(input_name, O_RDONLY, 0, false); | 782 | session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops); |
783 | if (session == NULL) | 783 | if (session == NULL) |
784 | return -ENOMEM; | 784 | return -ENOMEM; |
785 | 785 | ||
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index d2fc46103f83..459b5e3db267 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -937,7 +937,8 @@ static struct perf_event_ops event_ops = { | |||
937 | 937 | ||
938 | static int __cmd_timechart(void) | 938 | static int __cmd_timechart(void) |
939 | { | 939 | { |
940 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); | 940 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, |
941 | 0, false, &event_ops); | ||
941 | int ret = -EINVAL; | 942 | int ret = -EINVAL; |
942 | 943 | ||
943 | if (session == NULL) | 944 | if (session == NULL) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 0515ce9d3d3e..ae15f046c405 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -1272,7 +1272,7 @@ static int __cmd_top(void) | |||
1272 | * FIXME: perf_session__new should allow passing a O_MMAP, so that all this | 1272 | * FIXME: perf_session__new should allow passing a O_MMAP, so that all this |
1273 | * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. | 1273 | * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. |
1274 | */ | 1274 | */ |
1275 | struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false); | 1275 | struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL); |
1276 | if (session == NULL) | 1276 | if (session == NULL) |
1277 | return -ENOMEM; | 1277 | return -ENOMEM; |
1278 | 1278 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b59abf5aba36..0f7e544544f5 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -125,7 +125,9 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self) | |||
125 | machines__destroy_guest_kernel_maps(&self->machines); | 125 | machines__destroy_guest_kernel_maps(&self->machines); |
126 | } | 126 | } |
127 | 127 | ||
128 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) | 128 | struct perf_session *perf_session__new(const char *filename, int mode, |
129 | bool force, bool repipe, | ||
130 | struct perf_event_ops *ops) | ||
129 | { | 131 | { |
130 | size_t len = filename ? strlen(filename) + 1 : 0; | 132 | size_t len = filename ? strlen(filename) + 1 : 0; |
131 | struct perf_session *self = zalloc(sizeof(*self) + len); | 133 | struct perf_session *self = zalloc(sizeof(*self) + len); |
@@ -170,6 +172,13 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc | |||
170 | } | 172 | } |
171 | 173 | ||
172 | perf_session__update_sample_type(self); | 174 | perf_session__update_sample_type(self); |
175 | |||
176 | if (ops && ops->ordering_requires_timestamps && | ||
177 | ops->ordered_samples && !self->sample_id_all) { | ||
178 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); | ||
179 | ops->ordered_samples = false; | ||
180 | } | ||
181 | |||
173 | out: | 182 | out: |
174 | return self; | 183 | return self; |
175 | out_free: | 184 | out_free: |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index ac36f99f14af..ffe4b98db8f0 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -78,9 +78,12 @@ struct perf_event_ops { | |||
78 | build_id; | 78 | build_id; |
79 | event_op2 finished_round; | 79 | event_op2 finished_round; |
80 | bool ordered_samples; | 80 | bool ordered_samples; |
81 | bool ordering_requires_timestamps; | ||
81 | }; | 82 | }; |
82 | 83 | ||
83 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); | 84 | struct perf_session *perf_session__new(const char *filename, int mode, |
85 | bool force, bool repipe, | ||
86 | struct perf_event_ops *ops); | ||
84 | void perf_session__delete(struct perf_session *self); | 87 | void perf_session__delete(struct perf_session *self); |
85 | 88 | ||
86 | void perf_event_header__bswap(struct perf_event_header *self); | 89 | void perf_event_header__bswap(struct perf_event_header *self); |