diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-12-07 23:23:09 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-12-07 23:23:09 -0500 |
commit | 803ca41856a26b98150a669290c50adc9bfc648e (patch) | |
tree | 53148198f44c9a68efd82fca60133d0ba4903406 | |
parent | f1ad44884a4c421ceaa9a4a8242aeeee6f686670 (diff) | |
parent | cfef25b8daf7e4b49c84e174a904af9d89dc7c46 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
- Fixes and improvements for supporting annotating ARM binaries, support ARM
call and jump instructions, more work needed to have arch specific stuff
separated into tools/perf/arch/*/annotate/ (Russell King)
- Fix several 'perf test' entries broken by recent perf/core changes (Jiri Olsa)
Infrastructure changes:
- Consolidate perf_ev{list,sel}__{enable,disable}() calls (Jiri Olsa)
- Pass correct string to dso__adjust_kmod_long_name() (Wang Nan)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | tools/perf/builtin-stat.c | 44 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 14 | ||||
-rw-r--r-- | tools/perf/tests/dwarf-unwind.c | 8 | ||||
-rw-r--r-- | tools/perf/tests/evsel-roundtrip-name.c | 3 | ||||
-rw-r--r-- | tools/perf/tests/hists_common.c | 5 | ||||
-rw-r--r-- | tools/perf/tests/mmap-thread-lookup.c | 6 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 23 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 32 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 15 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 3 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 2 |
11 files changed, 95 insertions, 60 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index df2fbf046ee2..e74712dee242 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -168,15 +168,25 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) | |||
168 | attr->sample_period = 0; | 168 | attr->sample_period = 0; |
169 | attr->sample_type = 0; | 169 | attr->sample_type = 0; |
170 | 170 | ||
171 | if (target__has_cpu(&target)) | 171 | /* |
172 | return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); | 172 | * Disabling all counters initially, they will be enabled |
173 | 173 | * either manually by us or by kernel via enable_on_exec | |
174 | if (!target__has_task(&target) && perf_evsel__is_group_leader(evsel)) { | 174 | * set later. |
175 | */ | ||
176 | if (perf_evsel__is_group_leader(evsel)) { | ||
175 | attr->disabled = 1; | 177 | attr->disabled = 1; |
176 | if (!initial_delay) | 178 | |
179 | /* | ||
180 | * In case of initial_delay we enable tracee | ||
181 | * events manually. | ||
182 | */ | ||
183 | if (target__none(&target) && !initial_delay) | ||
177 | attr->enable_on_exec = 1; | 184 | attr->enable_on_exec = 1; |
178 | } | 185 | } |
179 | 186 | ||
187 | if (target__has_cpu(&target)) | ||
188 | return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); | ||
189 | |||
180 | return perf_evsel__open_per_thread(evsel, evsel_list->threads); | 190 | return perf_evsel__open_per_thread(evsel, evsel_list->threads); |
181 | } | 191 | } |
182 | 192 | ||
@@ -251,18 +261,18 @@ static void process_interval(void) | |||
251 | print_counters(&rs, 0, NULL); | 261 | print_counters(&rs, 0, NULL); |
252 | } | 262 | } |
253 | 263 | ||
254 | static void handle_initial_delay(void) | 264 | static void enable_counters(void) |
255 | { | 265 | { |
256 | struct perf_evsel *counter; | 266 | if (initial_delay) |
257 | |||
258 | if (initial_delay) { | ||
259 | const int ncpus = cpu_map__nr(evsel_list->cpus), | ||
260 | nthreads = thread_map__nr(evsel_list->threads); | ||
261 | |||
262 | usleep(initial_delay * 1000); | 267 | usleep(initial_delay * 1000); |
263 | evlist__for_each(evsel_list, counter) | 268 | |
264 | perf_evsel__enable(counter, ncpus, nthreads); | 269 | /* |
265 | } | 270 | * We need to enable counters only if: |
271 | * - we don't have tracee (attaching to task or cpu) | ||
272 | * - we have initial delay configured | ||
273 | */ | ||
274 | if (!target__none(&target) || initial_delay) | ||
275 | perf_evlist__enable(evsel_list); | ||
266 | } | 276 | } |
267 | 277 | ||
268 | static volatile int workload_exec_errno; | 278 | static volatile int workload_exec_errno; |
@@ -359,7 +369,7 @@ static int __run_perf_stat(int argc, const char **argv) | |||
359 | 369 | ||
360 | if (forks) { | 370 | if (forks) { |
361 | perf_evlist__start_workload(evsel_list); | 371 | perf_evlist__start_workload(evsel_list); |
362 | handle_initial_delay(); | 372 | enable_counters(); |
363 | 373 | ||
364 | if (interval) { | 374 | if (interval) { |
365 | while (!waitpid(child_pid, &status, WNOHANG)) { | 375 | while (!waitpid(child_pid, &status, WNOHANG)) { |
@@ -378,7 +388,7 @@ static int __run_perf_stat(int argc, const char **argv) | |||
378 | if (WIFSIGNALED(status)) | 388 | if (WIFSIGNALED(status)) |
379 | psignal(WTERMSIG(status), argv[0]); | 389 | psignal(WTERMSIG(status), argv[0]); |
380 | } else { | 390 | } else { |
381 | handle_initial_delay(); | 391 | enable_counters(); |
382 | while (!done) { | 392 | while (!done) { |
383 | nanosleep(&ts, NULL); | 393 | nanosleep(&ts, NULL); |
384 | if (interval) | 394 | if (interval) |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 4417b6a079f0..313a48c6b2bc 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -433,7 +433,6 @@ enum { | |||
433 | 433 | ||
434 | static int do_test_code_reading(bool try_kcore) | 434 | static int do_test_code_reading(bool try_kcore) |
435 | { | 435 | { |
436 | struct machines machines; | ||
437 | struct machine *machine; | 436 | struct machine *machine; |
438 | struct thread *thread; | 437 | struct thread *thread; |
439 | struct record_opts opts = { | 438 | struct record_opts opts = { |
@@ -459,8 +458,7 @@ static int do_test_code_reading(bool try_kcore) | |||
459 | 458 | ||
460 | pid = getpid(); | 459 | pid = getpid(); |
461 | 460 | ||
462 | machines__init(&machines); | 461 | machine = machine__new_host(); |
463 | machine = &machines.host; | ||
464 | 462 | ||
465 | ret = machine__create_kernel_maps(machine); | 463 | ret = machine__create_kernel_maps(machine); |
466 | if (ret < 0) { | 464 | if (ret < 0) { |
@@ -549,6 +547,13 @@ static int do_test_code_reading(bool try_kcore) | |||
549 | if (ret < 0) { | 547 | if (ret < 0) { |
550 | if (!excl_kernel) { | 548 | if (!excl_kernel) { |
551 | excl_kernel = true; | 549 | excl_kernel = true; |
550 | /* | ||
551 | * Both cpus and threads are now owned by evlist | ||
552 | * and will be freed by following perf_evlist__set_maps | ||
553 | * call. Getting refference to keep them alive. | ||
554 | */ | ||
555 | cpu_map__get(cpus); | ||
556 | thread_map__get(threads); | ||
552 | perf_evlist__set_maps(evlist, NULL, NULL); | 557 | perf_evlist__set_maps(evlist, NULL, NULL); |
553 | perf_evlist__delete(evlist); | 558 | perf_evlist__delete(evlist); |
554 | evlist = NULL; | 559 | evlist = NULL; |
@@ -594,9 +599,8 @@ out_err: | |||
594 | cpu_map__put(cpus); | 599 | cpu_map__put(cpus); |
595 | thread_map__put(threads); | 600 | thread_map__put(threads); |
596 | } | 601 | } |
597 | machines__destroy_kernel_maps(&machines); | ||
598 | machine__delete_threads(machine); | 602 | machine__delete_threads(machine); |
599 | machines__exit(&machines); | 603 | machine__delete(machine); |
600 | 604 | ||
601 | return err; | 605 | return err; |
602 | } | 606 | } |
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index 3cce13b19cbb..1c5c0221cea2 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c | |||
@@ -160,14 +160,11 @@ static int krava_1(struct thread *thread) | |||
160 | 160 | ||
161 | int test__dwarf_unwind(int subtest __maybe_unused) | 161 | int test__dwarf_unwind(int subtest __maybe_unused) |
162 | { | 162 | { |
163 | struct machines machines; | ||
164 | struct machine *machine; | 163 | struct machine *machine; |
165 | struct thread *thread; | 164 | struct thread *thread; |
166 | int err = -1; | 165 | int err = -1; |
167 | 166 | ||
168 | machines__init(&machines); | 167 | machine = machine__new_host(); |
169 | |||
170 | machine = machines__find(&machines, HOST_KERNEL_ID); | ||
171 | if (!machine) { | 168 | if (!machine) { |
172 | pr_err("Could not get machine\n"); | 169 | pr_err("Could not get machine\n"); |
173 | return -1; | 170 | return -1; |
@@ -199,7 +196,6 @@ int test__dwarf_unwind(int subtest __maybe_unused) | |||
199 | 196 | ||
200 | out: | 197 | out: |
201 | machine__delete_threads(machine); | 198 | machine__delete_threads(machine); |
202 | machine__exit(machine); | 199 | machine__delete(machine); |
203 | machines__exit(&machines); | ||
204 | return err; | 200 | return err; |
205 | } | 201 | } |
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c index 1da92e1159ee..2de4a4f2c3ed 100644 --- a/tools/perf/tests/evsel-roundtrip-name.c +++ b/tools/perf/tests/evsel-roundtrip-name.c | |||
@@ -103,7 +103,8 @@ int test__perf_evsel__roundtrip_name_test(int subtest __maybe_unused) | |||
103 | if (err) | 103 | if (err) |
104 | ret = err; | 104 | ret = err; |
105 | 105 | ||
106 | err = perf_evsel__name_array_test(perf_evsel__sw_names); | 106 | err = __perf_evsel__name_array_test(perf_evsel__sw_names, |
107 | PERF_COUNT_SW_DUMMY + 1); | ||
107 | if (err) | 108 | if (err) |
108 | ret = err; | 109 | ret = err; |
109 | 110 | ||
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c index ce80b274b097..46f453b1de60 100644 --- a/tools/perf/tests/hists_common.c +++ b/tools/perf/tests/hists_common.c | |||
@@ -87,6 +87,11 @@ struct machine *setup_fake_machine(struct machines *machines) | |||
87 | return NULL; | 87 | return NULL; |
88 | } | 88 | } |
89 | 89 | ||
90 | if (machine__create_kernel_maps(machine)) { | ||
91 | pr_debug("Not enough memory for machine setup\n"); | ||
92 | goto out; | ||
93 | } | ||
94 | |||
90 | for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { | 95 | for (i = 0; i < ARRAY_SIZE(fake_threads); i++) { |
91 | struct thread *thread; | 96 | struct thread *thread; |
92 | 97 | ||
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 6cdb97579c45..0c5ce44f723f 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c | |||
@@ -149,7 +149,6 @@ static int synth_process(struct machine *machine) | |||
149 | 149 | ||
150 | static int mmap_events(synth_cb synth) | 150 | static int mmap_events(synth_cb synth) |
151 | { | 151 | { |
152 | struct machines machines; | ||
153 | struct machine *machine; | 152 | struct machine *machine; |
154 | int err, i; | 153 | int err, i; |
155 | 154 | ||
@@ -162,8 +161,7 @@ static int mmap_events(synth_cb synth) | |||
162 | */ | 161 | */ |
163 | TEST_ASSERT_VAL("failed to create threads", !threads_create()); | 162 | TEST_ASSERT_VAL("failed to create threads", !threads_create()); |
164 | 163 | ||
165 | machines__init(&machines); | 164 | machine = machine__new_host(); |
166 | machine = &machines.host; | ||
167 | 165 | ||
168 | dump_trace = verbose > 1 ? 1 : 0; | 166 | dump_trace = verbose > 1 ? 1 : 0; |
169 | 167 | ||
@@ -203,7 +201,7 @@ static int mmap_events(synth_cb synth) | |||
203 | } | 201 | } |
204 | 202 | ||
205 | machine__delete_threads(machine); | 203 | machine__delete_threads(machine); |
206 | machines__exit(&machines); | 204 | machine__delete(machine); |
207 | return err; | 205 | return err; |
208 | } | 206 | } |
209 | 207 | ||
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 1dd1949b0e79..b795b6994144 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -65,6 +65,11 @@ static int call__parse(struct ins_operands *ops) | |||
65 | 65 | ||
66 | name++; | 66 | name++; |
67 | 67 | ||
68 | #ifdef __arm__ | ||
69 | if (strchr(name, '+')) | ||
70 | return -1; | ||
71 | #endif | ||
72 | |||
68 | tok = strchr(name, '>'); | 73 | tok = strchr(name, '>'); |
69 | if (tok == NULL) | 74 | if (tok == NULL) |
70 | return -1; | 75 | return -1; |
@@ -246,7 +251,11 @@ static int mov__parse(struct ins_operands *ops) | |||
246 | return -1; | 251 | return -1; |
247 | 252 | ||
248 | target = ++s; | 253 | target = ++s; |
254 | #ifdef __arm__ | ||
255 | comment = strchr(s, ';'); | ||
256 | #else | ||
249 | comment = strchr(s, '#'); | 257 | comment = strchr(s, '#'); |
258 | #endif | ||
250 | 259 | ||
251 | if (comment != NULL) | 260 | if (comment != NULL) |
252 | s = comment - 1; | 261 | s = comment - 1; |
@@ -354,6 +363,20 @@ static struct ins instructions[] = { | |||
354 | { .name = "addq", .ops = &mov_ops, }, | 363 | { .name = "addq", .ops = &mov_ops, }, |
355 | { .name = "addw", .ops = &mov_ops, }, | 364 | { .name = "addw", .ops = &mov_ops, }, |
356 | { .name = "and", .ops = &mov_ops, }, | 365 | { .name = "and", .ops = &mov_ops, }, |
366 | #ifdef __arm__ | ||
367 | { .name = "b", .ops = &jump_ops, }, // might also be a call | ||
368 | { .name = "bcc", .ops = &jump_ops, }, | ||
369 | { .name = "bcs", .ops = &jump_ops, }, | ||
370 | { .name = "beq", .ops = &jump_ops, }, | ||
371 | { .name = "bge", .ops = &jump_ops, }, | ||
372 | { .name = "bgt", .ops = &jump_ops, }, | ||
373 | { .name = "bhi", .ops = &jump_ops, }, | ||
374 | { .name = "bl", .ops = &call_ops, }, | ||
375 | { .name = "blt", .ops = &jump_ops, }, | ||
376 | { .name = "bls", .ops = &jump_ops, }, | ||
377 | { .name = "blx", .ops = &call_ops, }, | ||
378 | { .name = "bne", .ops = &jump_ops, }, | ||
379 | #endif | ||
357 | { .name = "bts", .ops = &mov_ops, }, | 380 | { .name = "bts", .ops = &mov_ops, }, |
358 | { .name = "call", .ops = &call_ops, }, | 381 | { .name = "call", .ops = &call_ops, }, |
359 | { .name = "callq", .ops = &call_ops, }, | 382 | { .name = "callq", .ops = &call_ops, }, |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d1392194a9a9..d1b6c206bb93 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -336,20 +336,12 @@ static int perf_evlist__nr_threads(struct perf_evlist *evlist, | |||
336 | 336 | ||
337 | void perf_evlist__disable(struct perf_evlist *evlist) | 337 | void perf_evlist__disable(struct perf_evlist *evlist) |
338 | { | 338 | { |
339 | int cpu, thread; | ||
340 | struct perf_evsel *pos; | 339 | struct perf_evsel *pos; |
341 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
342 | int nr_threads; | ||
343 | 340 | ||
344 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 341 | evlist__for_each(evlist, pos) { |
345 | evlist__for_each(evlist, pos) { | 342 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
346 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 343 | continue; |
347 | continue; | 344 | perf_evsel__disable(pos); |
348 | nr_threads = perf_evlist__nr_threads(evlist, pos); | ||
349 | for (thread = 0; thread < nr_threads; thread++) | ||
350 | ioctl(FD(pos, cpu, thread), | ||
351 | PERF_EVENT_IOC_DISABLE, 0); | ||
352 | } | ||
353 | } | 345 | } |
354 | 346 | ||
355 | evlist->enabled = false; | 347 | evlist->enabled = false; |
@@ -357,20 +349,12 @@ void perf_evlist__disable(struct perf_evlist *evlist) | |||
357 | 349 | ||
358 | void perf_evlist__enable(struct perf_evlist *evlist) | 350 | void perf_evlist__enable(struct perf_evlist *evlist) |
359 | { | 351 | { |
360 | int cpu, thread; | ||
361 | struct perf_evsel *pos; | 352 | struct perf_evsel *pos; |
362 | int nr_cpus = cpu_map__nr(evlist->cpus); | ||
363 | int nr_threads; | ||
364 | 353 | ||
365 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 354 | evlist__for_each(evlist, pos) { |
366 | evlist__for_each(evlist, pos) { | 355 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) |
367 | if (!perf_evsel__is_group_leader(pos) || !pos->fd) | 356 | continue; |
368 | continue; | 357 | perf_evsel__enable(pos); |
369 | nr_threads = perf_evlist__nr_threads(evlist, pos); | ||
370 | for (thread = 0; thread < nr_threads; thread++) | ||
371 | ioctl(FD(pos, cpu, thread), | ||
372 | PERF_EVENT_IOC_ENABLE, 0); | ||
373 | } | ||
374 | } | 358 | } |
375 | 359 | ||
376 | evlist->enabled = true; | 360 | evlist->enabled = true; |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0a1f4d9e52fc..47f033089349 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -981,13 +981,26 @@ int perf_evsel__append_filter(struct perf_evsel *evsel, | |||
981 | return -1; | 981 | return -1; |
982 | } | 982 | } |
983 | 983 | ||
984 | int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads) | 984 | int perf_evsel__enable(struct perf_evsel *evsel) |
985 | { | 985 | { |
986 | int nthreads = thread_map__nr(evsel->threads); | ||
987 | int ncpus = cpu_map__nr(evsel->cpus); | ||
988 | |||
986 | return perf_evsel__run_ioctl(evsel, ncpus, nthreads, | 989 | return perf_evsel__run_ioctl(evsel, ncpus, nthreads, |
987 | PERF_EVENT_IOC_ENABLE, | 990 | PERF_EVENT_IOC_ENABLE, |
988 | 0); | 991 | 0); |
989 | } | 992 | } |
990 | 993 | ||
994 | int perf_evsel__disable(struct perf_evsel *evsel) | ||
995 | { | ||
996 | int nthreads = thread_map__nr(evsel->threads); | ||
997 | int ncpus = cpu_map__nr(evsel->cpus); | ||
998 | |||
999 | return perf_evsel__run_ioctl(evsel, ncpus, nthreads, | ||
1000 | PERF_EVENT_IOC_DISABLE, | ||
1001 | 0); | ||
1002 | } | ||
1003 | |||
991 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) | 1004 | int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) |
992 | { | 1005 | { |
993 | if (ncpus == 0 || nthreads == 0) | 1006 | if (ncpus == 0 || nthreads == 0) |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 0e49bd742c63..5ded1fc0341e 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -227,7 +227,8 @@ int perf_evsel__append_filter(struct perf_evsel *evsel, | |||
227 | const char *op, const char *filter); | 227 | const char *op, const char *filter); |
228 | int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, | 228 | int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, |
229 | const char *filter); | 229 | const char *filter); |
230 | int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads); | 230 | int perf_evsel__enable(struct perf_evsel *evsel); |
231 | int perf_evsel__disable(struct perf_evsel *evsel); | ||
231 | 232 | ||
232 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, | 233 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, |
233 | struct cpu_map *cpus); | 234 | struct cpu_map *cpus); |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 95a7f6087346..bfc289c73c22 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -576,7 +576,7 @@ static void dso__adjust_kmod_long_name(struct dso *dso, const char *filename) | |||
576 | if (!dup_filename) | 576 | if (!dup_filename) |
577 | return; | 577 | return; |
578 | 578 | ||
579 | dso__set_long_name(dso, filename, true); | 579 | dso__set_long_name(dso, dup_filename, true); |
580 | } | 580 | } |
581 | 581 | ||
582 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, | 582 | struct map *machine__findnew_module_map(struct machine *machine, u64 start, |