diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-06-08 13:42:08 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-06-08 13:42:08 -0400 |
commit | becf6c97a3abaefb2f01415c0b908a268c92b2c3 (patch) | |
tree | 6b53ef8f7ae31f2b2701495bad61c03e20e6c1c8 | |
parent | 6113e45f831616de98c54a005260223b21bcb6b9 (diff) | |
parent | bafb67470b294810f62db40b348643062255702b (diff) |
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
30 files changed, 328 insertions, 96 deletions
@@ -411,7 +411,7 @@ endif | |||
411 | no-dot-config-targets := clean mrproper distclean \ | 411 | no-dot-config-targets := clean mrproper distclean \ |
412 | cscope TAGS tags help %docs check% \ | 412 | cscope TAGS tags help %docs check% \ |
413 | include/linux/version.h headers_% \ | 413 | include/linux/version.h headers_% \ |
414 | kernelrelease kernelversion | 414 | kernelrelease kernelversion %src-pkg |
415 | 415 | ||
416 | config-targets := 0 | 416 | config-targets := 0 |
417 | mixed-targets := 0 | 417 | mixed-targets := 0 |
@@ -1215,6 +1215,8 @@ distclean: mrproper | |||
1215 | # rpm target kept for backward compatibility | 1215 | # rpm target kept for backward compatibility |
1216 | package-dir := $(srctree)/scripts/package | 1216 | package-dir := $(srctree)/scripts/package |
1217 | 1217 | ||
1218 | %src-pkg: FORCE | ||
1219 | $(Q)$(MAKE) $(build)=$(package-dir) $@ | ||
1218 | %pkg: include/config/kernel.release FORCE | 1220 | %pkg: include/config/kernel.release FORCE |
1219 | $(Q)$(MAKE) $(build)=$(package-dir) $@ | 1221 | $(Q)$(MAKE) $(build)=$(package-dir) $@ |
1220 | rpm: include/config/kernel.release FORCE | 1222 | rpm: include/config/kernel.release FORCE |
diff --git a/scripts/package/Makefile b/scripts/package/Makefile index 62fcc3a7f4d3..18513b0191db 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile | |||
@@ -111,13 +111,38 @@ tar%pkg: FORCE | |||
111 | clean-dirs += $(objtree)/tar-install/ | 111 | clean-dirs += $(objtree)/tar-install/ |
112 | 112 | ||
113 | 113 | ||
114 | # perf-pkg - generate a source tarball with perf source | ||
115 | # --------------------------------------------------------------------------- | ||
116 | |||
117 | perf-tar=perf-$(KERNELVERSION) | ||
118 | |||
119 | quiet_cmd_perf_tar = TAR | ||
120 | cmd_perf_tar = \ | ||
121 | git archive --prefix=$(perf-tar)/ HEAD^{tree} \ | ||
122 | $$(cat $(srctree)/tools/perf/MANIFEST) -o $(perf-tar).tar; \ | ||
123 | mkdir -p $(perf-tar); \ | ||
124 | git rev-parse HEAD > $(perf-tar)/HEAD; \ | ||
125 | tar rf $(perf-tar).tar $(perf-tar)/HEAD; \ | ||
126 | rm -r $(perf-tar); \ | ||
127 | $(if $(findstring tar-src,$@),, \ | ||
128 | $(if $(findstring bz2,$@),bzip2, \ | ||
129 | $(if $(findstring gz,$@),gzip, \ | ||
130 | $(error unknown target $@))) \ | ||
131 | -f -9 $(perf-tar).tar) | ||
132 | |||
133 | perf-%pkg: FORCE | ||
134 | $(call cmd,perf_tar) | ||
135 | |||
114 | # Help text displayed when executing 'make help' | 136 | # Help text displayed when executing 'make help' |
115 | # --------------------------------------------------------------------------- | 137 | # --------------------------------------------------------------------------- |
116 | help: FORCE | 138 | help: FORCE |
117 | @echo ' rpm-pkg - Build both source and binary RPM kernel packages' | 139 | @echo ' rpm-pkg - Build both source and binary RPM kernel packages' |
118 | @echo ' binrpm-pkg - Build only the binary kernel package' | 140 | @echo ' binrpm-pkg - Build only the binary kernel package' |
119 | @echo ' deb-pkg - Build the kernel as an deb package' | 141 | @echo ' deb-pkg - Build the kernel as an deb package' |
120 | @echo ' tar-pkg - Build the kernel as an uncompressed tarball' | 142 | @echo ' tar-pkg - Build the kernel as an uncompressed tarball' |
121 | @echo ' targz-pkg - Build the kernel as a gzip compressed tarball' | 143 | @echo ' targz-pkg - Build the kernel as a gzip compressed tarball' |
122 | @echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball' | 144 | @echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball' |
145 | @echo ' perf-tar-src-pkg - Build $(perf-tar).tar source tarball' | ||
146 | @echo ' perf-targz-src-pkg - Build $(perf-tar).tar.gz source tarball' | ||
147 | @echo ' perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball' | ||
123 | 148 | ||
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 34e255fc3e2f..25576b477c83 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -103,6 +103,13 @@ OPTIONS | |||
103 | --raw-samples:: | 103 | --raw-samples:: |
104 | Collect raw sample records from all opened counters (default for tracepoint counters). | 104 | Collect raw sample records from all opened counters (default for tracepoint counters). |
105 | 105 | ||
106 | -C:: | ||
107 | --cpu:: | ||
108 | Collect samples only on the list of cpus provided. Multiple CPUs can be provided as a | ||
109 | comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. | ||
110 | In per-thread mode with inheritance mode on (default), samples are captured only when | ||
111 | the thread executes on the designated CPUs. Default is to monitor all CPUs. | ||
112 | |||
106 | SEE ALSO | 113 | SEE ALSO |
107 | -------- | 114 | -------- |
108 | linkperf:perf-stat[1], linkperf:perf-list[1] | 115 | linkperf:perf-stat[1], linkperf:perf-list[1] |
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 909fa766fa1c..4b3a2d46b437 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt | |||
@@ -46,6 +46,13 @@ OPTIONS | |||
46 | -B:: | 46 | -B:: |
47 | print large numbers with thousands' separators according to locale | 47 | print large numbers with thousands' separators according to locale |
48 | 48 | ||
49 | -C:: | ||
50 | --cpu=:: | ||
51 | Count only on the list of cpus provided. Multiple CPUs can be provided as a | ||
52 | comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. | ||
53 | In per-thread mode, this option is ignored. The -a option is still necessary | ||
54 | to activate system-wide monitoring. Default is to count on all CPUs. | ||
55 | |||
49 | EXAMPLES | 56 | EXAMPLES |
50 | -------- | 57 | -------- |
51 | 58 | ||
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 785b9fc32a46..1f9687663f2a 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -25,9 +25,11 @@ OPTIONS | |||
25 | --count=<count>:: | 25 | --count=<count>:: |
26 | Event period to sample. | 26 | Event period to sample. |
27 | 27 | ||
28 | -C <cpu>:: | 28 | -C <cpu-list>:: |
29 | --CPU=<cpu>:: | 29 | --cpu=<cpu>:: |
30 | CPU to profile. | 30 | Monitor only on the list of cpus provided. Multiple CPUs can be provided as a |
31 | comma-sperated list with no space: 0,1. Ranges of CPUs are specified with -: 0-2. | ||
32 | Default is to monitor all CPUS. | ||
31 | 33 | ||
32 | -d <seconds>:: | 34 | -d <seconds>:: |
33 | --delay=<seconds>:: | 35 | --delay=<seconds>:: |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST new file mode 100644 index 000000000000..8c7fc0c8f0b8 --- /dev/null +++ b/tools/perf/MANIFEST | |||
@@ -0,0 +1,12 @@ | |||
1 | tools/perf | ||
2 | include/linux/perf_event.h | ||
3 | include/linux/rbtree.h | ||
4 | include/linux/list.h | ||
5 | include/linux/hash.h | ||
6 | include/linux/stringify.h | ||
7 | lib/rbtree.c | ||
8 | include/linux/swab.h | ||
9 | arch/*/include/asm/unistd*.h | ||
10 | include/linux/poison.h | ||
11 | include/linux/magic.h | ||
12 | include/linux/hw_breakpoint.h | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 96db5248e995..fd20670ce986 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -61,11 +61,9 @@ static int hists__add_entry(struct hists *self, struct addr_location *al) | |||
61 | static int process_sample_event(event_t *event, struct perf_session *session) | 61 | static int process_sample_event(event_t *event, struct perf_session *session) |
62 | { | 62 | { |
63 | struct addr_location al; | 63 | struct addr_location al; |
64 | struct sample_data data; | ||
64 | 65 | ||
65 | dump_printf("(IP, %d): %d: %#Lx\n", event->header.misc, | 66 | if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { |
66 | event->ip.pid, event->ip.ip); | ||
67 | |||
68 | if (event__preprocess_sample(event, session, &al, NULL) < 0) { | ||
69 | pr_warning("problem processing %d event, skipping it.\n", | 67 | pr_warning("problem processing %d event, skipping it.\n", |
70 | event->header.type); | 68 | event->header.type); |
71 | return -1; | 69 | return -1; |
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index f8e3d1852029..29ad20e67919 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -78,8 +78,7 @@ static int __cmd_buildid_cache(void) | |||
78 | struct str_node *pos; | 78 | struct str_node *pos; |
79 | char debugdir[PATH_MAX]; | 79 | char debugdir[PATH_MAX]; |
80 | 80 | ||
81 | snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), | 81 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); |
82 | DEBUG_CACHE_DIR); | ||
83 | 82 | ||
84 | if (add_name_list_str) { | 83 | if (add_name_list_str) { |
85 | list = strlist__new(true, add_name_list_str); | 84 | list = strlist__new(true, add_name_list_str); |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index a6e2fdc7a04e..39e6627ebb96 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -35,10 +35,7 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi | |||
35 | struct addr_location al; | 35 | struct addr_location al; |
36 | struct sample_data data = { .period = 1, }; | 36 | struct sample_data data = { .period = 1, }; |
37 | 37 | ||
38 | dump_printf("(IP, %d): %d: %#Lx\n", event->header.misc, | 38 | if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { |
39 | event->ip.pid, event->ip.ip); | ||
40 | |||
41 | if (event__preprocess_sample(event, session, &al, NULL) < 0) { | ||
42 | pr_warning("problem processing %d event, skipping it.\n", | 39 | pr_warning("problem processing %d event, skipping it.\n", |
43 | event->header.type); | 40 | event->header.type); |
44 | return -1; | 41 | return -1; |
@@ -47,8 +44,6 @@ static int diff__process_sample_event(event_t *event, struct perf_session *sessi | |||
47 | if (al.filtered || al.sym == NULL) | 44 | if (al.filtered || al.sym == NULL) |
48 | return 0; | 45 | return 0; |
49 | 46 | ||
50 | event__parse_sample(event, session->sample_type, &data); | ||
51 | |||
52 | if (hists__add_entry(&session->hists, &al, data.period)) { | 47 | if (hists__add_entry(&session->hists, &al, data.period)) { |
53 | pr_warning("problem incrementing symbol period, skipping event\n"); | 48 | pr_warning("problem incrementing symbol period, skipping event\n"); |
54 | return -1; | 49 | return -1; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index dc3435e18bde..5e5c6403a315 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -49,7 +49,6 @@ static int group = 0; | |||
49 | static int realtime_prio = 0; | 49 | static int realtime_prio = 0; |
50 | static bool raw_samples = false; | 50 | static bool raw_samples = false; |
51 | static bool system_wide = false; | 51 | static bool system_wide = false; |
52 | static int profile_cpu = -1; | ||
53 | static pid_t target_pid = -1; | 52 | static pid_t target_pid = -1; |
54 | static pid_t target_tid = -1; | 53 | static pid_t target_tid = -1; |
55 | static pid_t *all_tids = NULL; | 54 | static pid_t *all_tids = NULL; |
@@ -74,6 +73,7 @@ static int file_new = 1; | |||
74 | static off_t post_processing_offset; | 73 | static off_t post_processing_offset; |
75 | 74 | ||
76 | static struct perf_session *session; | 75 | static struct perf_session *session; |
76 | static const char *cpu_list; | ||
77 | 77 | ||
78 | struct mmap_data { | 78 | struct mmap_data { |
79 | int counter; | 79 | int counter; |
@@ -274,6 +274,9 @@ static void create_counter(int counter, int cpu) | |||
274 | if (call_graph) | 274 | if (call_graph) |
275 | attr->sample_type |= PERF_SAMPLE_CALLCHAIN; | 275 | attr->sample_type |= PERF_SAMPLE_CALLCHAIN; |
276 | 276 | ||
277 | if (system_wide) | ||
278 | attr->sample_type |= PERF_SAMPLE_CPU; | ||
279 | |||
277 | if (raw_samples) { | 280 | if (raw_samples) { |
278 | attr->sample_type |= PERF_SAMPLE_TIME; | 281 | attr->sample_type |= PERF_SAMPLE_TIME; |
279 | attr->sample_type |= PERF_SAMPLE_RAW; | 282 | attr->sample_type |= PERF_SAMPLE_RAW; |
@@ -300,7 +303,7 @@ try_again: | |||
300 | die("Permission error - are you root?\n" | 303 | die("Permission error - are you root?\n" |
301 | "\t Consider tweaking" | 304 | "\t Consider tweaking" |
302 | " /proc/sys/kernel/perf_event_paranoid.\n"); | 305 | " /proc/sys/kernel/perf_event_paranoid.\n"); |
303 | else if (err == ENODEV && profile_cpu != -1) { | 306 | else if (err == ENODEV && cpu_list) { |
304 | die("No such device - did you specify" | 307 | die("No such device - did you specify" |
305 | " an out-of-range profile CPU?\n"); | 308 | " an out-of-range profile CPU?\n"); |
306 | } | 309 | } |
@@ -622,10 +625,15 @@ static int __cmd_record(int argc, const char **argv) | |||
622 | close(child_ready_pipe[0]); | 625 | close(child_ready_pipe[0]); |
623 | } | 626 | } |
624 | 627 | ||
625 | if ((!system_wide && no_inherit) || profile_cpu != -1) { | 628 | nr_cpus = read_cpu_map(cpu_list); |
626 | open_counters(profile_cpu); | 629 | if (nr_cpus < 1) { |
630 | perror("failed to collect number of CPUs\n"); | ||
631 | return -1; | ||
632 | } | ||
633 | |||
634 | if (!system_wide && no_inherit && !cpu_list) { | ||
635 | open_counters(-1); | ||
627 | } else { | 636 | } else { |
628 | nr_cpus = read_cpu_map(); | ||
629 | for (i = 0; i < nr_cpus; i++) | 637 | for (i = 0; i < nr_cpus; i++) |
630 | open_counters(cpumap[i]); | 638 | open_counters(cpumap[i]); |
631 | } | 639 | } |
@@ -704,7 +712,7 @@ static int __cmd_record(int argc, const char **argv) | |||
704 | if (perf_guest) | 712 | if (perf_guest) |
705 | perf_session__process_machines(session, event__synthesize_guest_os); | 713 | perf_session__process_machines(session, event__synthesize_guest_os); |
706 | 714 | ||
707 | if (!system_wide && profile_cpu == -1) | 715 | if (!system_wide && cpu_list) |
708 | event__synthesize_thread(target_tid, process_synthesized_event, | 716 | event__synthesize_thread(target_tid, process_synthesized_event, |
709 | session); | 717 | session); |
710 | else | 718 | else |
@@ -794,8 +802,8 @@ static const struct option options[] = { | |||
794 | "system-wide collection from all CPUs"), | 802 | "system-wide collection from all CPUs"), |
795 | OPT_BOOLEAN('A', "append", &append_file, | 803 | OPT_BOOLEAN('A', "append", &append_file, |
796 | "append to the output file to do incremental profiling"), | 804 | "append to the output file to do incremental profiling"), |
797 | OPT_INTEGER('C', "profile_cpu", &profile_cpu, | 805 | OPT_STRING('C', "cpu", &cpu_list, "cpu", |
798 | "CPU to profile on"), | 806 | "list of cpus to monitor"), |
799 | OPT_BOOLEAN('f', "force", &force, | 807 | OPT_BOOLEAN('f', "force", &force, |
800 | "overwrite existing data file (deprecated)"), | 808 | "overwrite existing data file (deprecated)"), |
801 | OPT_U64('c', "count", &user_interval, "event period to sample"), | 809 | OPT_U64('c', "count", &user_interval, "event period to sample"), |
@@ -825,7 +833,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) | |||
825 | argc = parse_options(argc, argv, options, record_usage, | 833 | argc = parse_options(argc, argv, options, record_usage, |
826 | PARSE_OPT_STOP_AT_NON_OPTION); | 834 | PARSE_OPT_STOP_AT_NON_OPTION); |
827 | if (!argc && target_pid == -1 && target_tid == -1 && | 835 | if (!argc && target_pid == -1 && target_tid == -1 && |
828 | !system_wide && profile_cpu == -1) | 836 | !system_wide && !cpu_list) |
829 | usage_with_options(record_usage, options); | 837 | usage_with_options(record_usage, options); |
830 | 838 | ||
831 | if (force && append_file) { | 839 | if (force && append_file) { |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 359205782964..371a3c995806 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -155,30 +155,7 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
155 | struct addr_location al; | 155 | struct addr_location al; |
156 | struct perf_event_attr *attr; | 156 | struct perf_event_attr *attr; |
157 | 157 | ||
158 | event__parse_sample(event, session->sample_type, &data); | 158 | if (event__preprocess_sample(event, session, &al, &data, NULL) < 0) { |
159 | |||
160 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc, | ||
161 | data.pid, data.tid, data.ip, data.period); | ||
162 | |||
163 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
164 | unsigned int i; | ||
165 | |||
166 | dump_printf("... chain: nr:%Lu\n", data.callchain->nr); | ||
167 | |||
168 | if (!ip_callchain__valid(data.callchain, event)) { | ||
169 | pr_debug("call-chain problem with event, " | ||
170 | "skipping it.\n"); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | if (dump_trace) { | ||
175 | for (i = 0; i < data.callchain->nr; i++) | ||
176 | dump_printf("..... %2d: %016Lx\n", | ||
177 | i, data.callchain->ips[i]); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | if (event__preprocess_sample(event, session, &al, NULL) < 0) { | ||
182 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 159 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
183 | event->header.type); | 160 | event->header.type); |
184 | return -1; | 161 | return -1; |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 9a39ca3c3ac4..a6b4d44f9502 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -69,7 +69,7 @@ static struct perf_event_attr default_attrs[] = { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | static bool system_wide = false; | 71 | static bool system_wide = false; |
72 | static unsigned int nr_cpus = 0; | 72 | static int nr_cpus = 0; |
73 | static int run_idx = 0; | 73 | static int run_idx = 0; |
74 | 74 | ||
75 | static int run_count = 1; | 75 | static int run_count = 1; |
@@ -82,6 +82,7 @@ static int thread_num = 0; | |||
82 | static pid_t child_pid = -1; | 82 | static pid_t child_pid = -1; |
83 | static bool null_run = false; | 83 | static bool null_run = false; |
84 | static bool big_num = false; | 84 | static bool big_num = false; |
85 | static const char *cpu_list; | ||
85 | 86 | ||
86 | 87 | ||
87 | static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; | 88 | static int *fd[MAX_NR_CPUS][MAX_COUNTERS]; |
@@ -158,7 +159,7 @@ static int create_perf_stat_counter(int counter) | |||
158 | PERF_FORMAT_TOTAL_TIME_RUNNING; | 159 | PERF_FORMAT_TOTAL_TIME_RUNNING; |
159 | 160 | ||
160 | if (system_wide) { | 161 | if (system_wide) { |
161 | unsigned int cpu; | 162 | int cpu; |
162 | 163 | ||
163 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 164 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
164 | fd[cpu][counter][0] = sys_perf_event_open(attr, | 165 | fd[cpu][counter][0] = sys_perf_event_open(attr, |
@@ -208,7 +209,7 @@ static inline int nsec_counter(int counter) | |||
208 | static void read_counter(int counter) | 209 | static void read_counter(int counter) |
209 | { | 210 | { |
210 | u64 count[3], single_count[3]; | 211 | u64 count[3], single_count[3]; |
211 | unsigned int cpu; | 212 | int cpu; |
212 | size_t res, nv; | 213 | size_t res, nv; |
213 | int scaled; | 214 | int scaled; |
214 | int i, thread; | 215 | int i, thread; |
@@ -542,6 +543,8 @@ static const struct option options[] = { | |||
542 | "null run - dont start any counters"), | 543 | "null run - dont start any counters"), |
543 | OPT_BOOLEAN('B', "big-num", &big_num, | 544 | OPT_BOOLEAN('B', "big-num", &big_num, |
544 | "print large numbers with thousands\' separators"), | 545 | "print large numbers with thousands\' separators"), |
546 | OPT_STRING('C', "cpu", &cpu_list, "cpu", | ||
547 | "list of cpus to monitor in system-wide"), | ||
545 | OPT_END() | 548 | OPT_END() |
546 | }; | 549 | }; |
547 | 550 | ||
@@ -566,10 +569,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) | |||
566 | } | 569 | } |
567 | 570 | ||
568 | if (system_wide) | 571 | if (system_wide) |
569 | nr_cpus = read_cpu_map(); | 572 | nr_cpus = read_cpu_map(cpu_list); |
570 | else | 573 | else |
571 | nr_cpus = 1; | 574 | nr_cpus = 1; |
572 | 575 | ||
576 | if (nr_cpus < 1) | ||
577 | usage_with_options(stat_usage, options); | ||
578 | |||
573 | if (target_pid != -1) { | 579 | if (target_pid != -1) { |
574 | target_tid = target_pid; | 580 | target_tid = target_pid; |
575 | thread_num = find_all_tid(target_pid, &all_tids); | 581 | thread_num = find_all_tid(target_pid, &all_tids); |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index a66f4272b994..1e8e92e317b9 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -102,6 +102,7 @@ struct sym_entry *sym_filter_entry_sched = NULL; | |||
102 | static int sym_pcnt_filter = 5; | 102 | static int sym_pcnt_filter = 5; |
103 | static int sym_counter = 0; | 103 | static int sym_counter = 0; |
104 | static int display_weighted = -1; | 104 | static int display_weighted = -1; |
105 | static const char *cpu_list; | ||
105 | 106 | ||
106 | /* | 107 | /* |
107 | * Symbols | 108 | * Symbols |
@@ -982,6 +983,7 @@ static void event__process_sample(const event_t *self, | |||
982 | u64 ip = self->ip.ip; | 983 | u64 ip = self->ip.ip; |
983 | struct sym_entry *syme; | 984 | struct sym_entry *syme; |
984 | struct addr_location al; | 985 | struct addr_location al; |
986 | struct sample_data data; | ||
985 | struct machine *machine; | 987 | struct machine *machine; |
986 | u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 988 | u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
987 | 989 | ||
@@ -1024,7 +1026,8 @@ static void event__process_sample(const event_t *self, | |||
1024 | if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) | 1026 | if (self->header.misc & PERF_RECORD_MISC_EXACT_IP) |
1025 | exact_samples++; | 1027 | exact_samples++; |
1026 | 1028 | ||
1027 | if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 || | 1029 | if (event__preprocess_sample(self, session, &al, &data, |
1030 | symbol_filter) < 0 || | ||
1028 | al.filtered) | 1031 | al.filtered) |
1029 | return; | 1032 | return; |
1030 | 1033 | ||
@@ -1351,8 +1354,8 @@ static const struct option options[] = { | |||
1351 | "profile events on existing thread id"), | 1354 | "profile events on existing thread id"), |
1352 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 1355 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
1353 | "system-wide collection from all CPUs"), | 1356 | "system-wide collection from all CPUs"), |
1354 | OPT_INTEGER('C', "CPU", &profile_cpu, | 1357 | OPT_STRING('C', "cpu", &cpu_list, "cpu", |
1355 | "CPU to profile on"), | 1358 | "list of cpus to monitor"), |
1356 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, | 1359 | OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, |
1357 | "file", "vmlinux pathname"), | 1360 | "file", "vmlinux pathname"), |
1358 | OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, | 1361 | OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols, |
@@ -1428,10 +1431,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1428 | return -ENOMEM; | 1431 | return -ENOMEM; |
1429 | 1432 | ||
1430 | /* CPU and PID are mutually exclusive */ | 1433 | /* CPU and PID are mutually exclusive */ |
1431 | if (target_tid > 0 && profile_cpu != -1) { | 1434 | if (target_tid > 0 && cpu_list) { |
1432 | printf("WARNING: PID switch overriding CPU\n"); | 1435 | printf("WARNING: PID switch overriding CPU\n"); |
1433 | sleep(1); | 1436 | sleep(1); |
1434 | profile_cpu = -1; | 1437 | cpu_list = NULL; |
1435 | } | 1438 | } |
1436 | 1439 | ||
1437 | if (!nr_counters) | 1440 | if (!nr_counters) |
@@ -1469,10 +1472,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1469 | attrs[counter].sample_period = default_interval; | 1472 | attrs[counter].sample_period = default_interval; |
1470 | } | 1473 | } |
1471 | 1474 | ||
1472 | if (target_tid != -1 || profile_cpu != -1) | 1475 | if (target_tid != -1) |
1473 | nr_cpus = 1; | 1476 | nr_cpus = 1; |
1474 | else | 1477 | else |
1475 | nr_cpus = read_cpu_map(); | 1478 | nr_cpus = read_cpu_map(cpu_list); |
1479 | |||
1480 | if (nr_cpus < 1) | ||
1481 | usage_with_options(top_usage, options); | ||
1476 | 1482 | ||
1477 | get_term_dimensions(&winsize); | 1483 | get_term_dimensions(&winsize); |
1478 | if (print_entries == 0) { | 1484 | if (print_entries == 0) { |
diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh index 2e7a4f417e20..677e59d62a8d 100644 --- a/tools/perf/perf-archive.sh +++ b/tools/perf/perf-archive.sh | |||
@@ -7,7 +7,17 @@ if [ $# -ne 0 ] ; then | |||
7 | PERF_DATA=$1 | 7 | PERF_DATA=$1 |
8 | fi | 8 | fi |
9 | 9 | ||
10 | DEBUGDIR=~/.debug/ | 10 | # |
11 | # PERF_BUILDID_DIR environment variable set by perf | ||
12 | # path to buildid directory, default to $HOME/.debug | ||
13 | # | ||
14 | if [ -z $PERF_BUILDID_DIR ]; then | ||
15 | PERF_BUILDID_DIR=~/.debug/ | ||
16 | else | ||
17 | # append / to make substitutions work | ||
18 | PERF_BUILDID_DIR=$PERF_BUILDID_DIR/ | ||
19 | fi | ||
20 | |||
11 | BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX) | 21 | BUILDIDS=$(mktemp /tmp/perf-archive-buildids.XXXXXX) |
12 | NOBUILDID=0000000000000000000000000000000000000000 | 22 | NOBUILDID=0000000000000000000000000000000000000000 |
13 | 23 | ||
@@ -22,13 +32,13 @@ MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX) | |||
22 | 32 | ||
23 | cut -d ' ' -f 1 $BUILDIDS | \ | 33 | cut -d ' ' -f 1 $BUILDIDS | \ |
24 | while read build_id ; do | 34 | while read build_id ; do |
25 | linkname=$DEBUGDIR.build-id/${build_id:0:2}/${build_id:2} | 35 | linkname=$PERF_BUILDID_DIR.build-id/${build_id:0:2}/${build_id:2} |
26 | filename=$(readlink -f $linkname) | 36 | filename=$(readlink -f $linkname) |
27 | echo ${linkname#$DEBUGDIR} >> $MANIFEST | 37 | echo ${linkname#$PERF_BUILDID_DIR} >> $MANIFEST |
28 | echo ${filename#$DEBUGDIR} >> $MANIFEST | 38 | echo ${filename#$PERF_BUILDID_DIR} >> $MANIFEST |
29 | done | 39 | done |
30 | 40 | ||
31 | tar cfj $PERF_DATA.tar.bz2 -C $DEBUGDIR -T $MANIFEST | 41 | tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST |
32 | rm -f $MANIFEST $BUILDIDS | 42 | rm -f $MANIFEST $BUILDIDS |
33 | echo -e "Now please run:\n" | 43 | echo -e "Now please run:\n" |
34 | echo -e "$ tar xvf $PERF_DATA.tar.bz2 -C ~/.debug\n" | 44 | echo -e "$ tar xvf $PERF_DATA.tar.bz2 -C ~/.debug\n" |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 6e4871191138..cdd6c03f1e14 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -458,6 +458,8 @@ int main(int argc, const char **argv) | |||
458 | handle_options(&argv, &argc, NULL); | 458 | handle_options(&argv, &argc, NULL); |
459 | commit_pager_choice(); | 459 | commit_pager_choice(); |
460 | set_debugfs_path(); | 460 | set_debugfs_path(); |
461 | set_buildid_dir(); | ||
462 | |||
461 | if (argc > 0) { | 463 | if (argc > 0) { |
462 | if (!prefixcmp(argv[0], "--")) | 464 | if (!prefixcmp(argv[0], "--")) |
463 | argv[0] += 2; | 465 | argv[0] += 2; |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 70c5cf87d020..5c26e2d314af 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -43,19 +43,17 @@ struct perf_event_ops build_id__mark_dso_hit_ops = { | |||
43 | char *dso__build_id_filename(struct dso *self, char *bf, size_t size) | 43 | char *dso__build_id_filename(struct dso *self, char *bf, size_t size) |
44 | { | 44 | { |
45 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 45 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
46 | const char *home; | ||
47 | 46 | ||
48 | if (!self->has_build_id) | 47 | if (!self->has_build_id) |
49 | return NULL; | 48 | return NULL; |
50 | 49 | ||
51 | build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); | 50 | build_id__sprintf(self->build_id, sizeof(self->build_id), build_id_hex); |
52 | home = getenv("HOME"); | ||
53 | if (bf == NULL) { | 51 | if (bf == NULL) { |
54 | if (asprintf(&bf, "%s/%s/.build-id/%.2s/%s", home, | 52 | if (asprintf(&bf, "%s/.build-id/%.2s/%s", buildid_dir, |
55 | DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2) < 0) | 53 | build_id_hex, build_id_hex + 2) < 0) |
56 | return NULL; | 54 | return NULL; |
57 | } else | 55 | } else |
58 | snprintf(bf, size, "%s/%s/.build-id/%.2s/%s", home, | 56 | snprintf(bf, size, "%s/.build-id/%.2s/%s", buildid_dir, |
59 | DEBUG_CACHE_DIR, build_id_hex, build_id_hex + 2); | 57 | build_id_hex, build_id_hex + 2); |
60 | return bf; | 58 | return bf; |
61 | } | 59 | } |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 65fe664fddf6..27e9ebe4076e 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -23,6 +23,7 @@ extern int perf_config(config_fn_t fn, void *); | |||
23 | extern int perf_config_int(const char *, const char *); | 23 | extern int perf_config_int(const char *, const char *); |
24 | extern int perf_config_bool(const char *, const char *); | 24 | extern int perf_config_bool(const char *, const char *); |
25 | extern int config_error_nonbool(const char *); | 25 | extern int config_error_nonbool(const char *); |
26 | extern const char *perf_config_dirname(const char *, const char *); | ||
26 | 27 | ||
27 | /* pager.c */ | 28 | /* pager.c */ |
28 | extern void setup_pager(void); | 29 | extern void setup_pager(void); |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 62b69ad4aa73..e63c997d6c1b 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include "util.h" | 18 | #include "util.h" |
19 | #include "callchain.h" | 19 | #include "callchain.h" |
20 | 20 | ||
21 | bool ip_callchain__valid(struct ip_callchain *chain, event_t *event) | 21 | bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event) |
22 | { | 22 | { |
23 | unsigned int chain_size = event->header.size; | 23 | unsigned int chain_size = event->header.size; |
24 | chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; | 24 | chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 1ca73e4a2723..809850fb75fb 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -60,5 +60,5 @@ int register_callchain_param(struct callchain_param *param); | |||
60 | int append_chain(struct callchain_node *root, struct ip_callchain *chain, | 60 | int append_chain(struct callchain_node *root, struct ip_callchain *chain, |
61 | struct map_symbol *syms); | 61 | struct map_symbol *syms); |
62 | 62 | ||
63 | bool ip_callchain__valid(struct ip_callchain *chain, event_t *event); | 63 | bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); |
64 | #endif /* __PERF_CALLCHAIN_H */ | 64 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index dabe892d0e53..e02d78cae70f 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c | |||
@@ -11,6 +11,11 @@ | |||
11 | 11 | ||
12 | #define MAXNAME (256) | 12 | #define MAXNAME (256) |
13 | 13 | ||
14 | #define DEBUG_CACHE_DIR ".debug" | ||
15 | |||
16 | |||
17 | char buildid_dir[MAXPATHLEN]; /* root dir for buildid, binary cache */ | ||
18 | |||
14 | static FILE *config_file; | 19 | static FILE *config_file; |
15 | static const char *config_file_name; | 20 | static const char *config_file_name; |
16 | static int config_linenr; | 21 | static int config_linenr; |
@@ -127,7 +132,7 @@ static int get_value(config_fn_t fn, void *data, char *name, unsigned int len) | |||
127 | break; | 132 | break; |
128 | if (!iskeychar(c)) | 133 | if (!iskeychar(c)) |
129 | break; | 134 | break; |
130 | name[len++] = tolower(c); | 135 | name[len++] = c; |
131 | if (len >= MAXNAME) | 136 | if (len >= MAXNAME) |
132 | return -1; | 137 | return -1; |
133 | } | 138 | } |
@@ -327,6 +332,13 @@ int perf_config_bool(const char *name, const char *value) | |||
327 | return !!perf_config_bool_or_int(name, value, &discard); | 332 | return !!perf_config_bool_or_int(name, value, &discard); |
328 | } | 333 | } |
329 | 334 | ||
335 | const char *perf_config_dirname(const char *name, const char *value) | ||
336 | { | ||
337 | if (!name) | ||
338 | return NULL; | ||
339 | return value; | ||
340 | } | ||
341 | |||
330 | static int perf_default_core_config(const char *var __used, const char *value __used) | 342 | static int perf_default_core_config(const char *var __used, const char *value __used) |
331 | { | 343 | { |
332 | /* Add other config variables here and to Documentation/config.txt. */ | 344 | /* Add other config variables here and to Documentation/config.txt. */ |
@@ -428,3 +440,53 @@ int config_error_nonbool(const char *var) | |||
428 | { | 440 | { |
429 | return error("Missing value for '%s'", var); | 441 | return error("Missing value for '%s'", var); |
430 | } | 442 | } |
443 | |||
444 | struct buildid_dir_config { | ||
445 | char *dir; | ||
446 | }; | ||
447 | |||
448 | static int buildid_dir_command_config(const char *var, const char *value, | ||
449 | void *data) | ||
450 | { | ||
451 | struct buildid_dir_config *c = data; | ||
452 | const char *v; | ||
453 | |||
454 | /* same dir for all commands */ | ||
455 | if (!prefixcmp(var, "buildid.") && !strcmp(var + 8, "dir")) { | ||
456 | v = perf_config_dirname(var, value); | ||
457 | if (!v) | ||
458 | return -1; | ||
459 | strncpy(c->dir, v, MAXPATHLEN-1); | ||
460 | c->dir[MAXPATHLEN-1] = '\0'; | ||
461 | } | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static void check_buildid_dir_config(void) | ||
466 | { | ||
467 | struct buildid_dir_config c; | ||
468 | c.dir = buildid_dir; | ||
469 | perf_config(buildid_dir_command_config, &c); | ||
470 | } | ||
471 | |||
472 | void set_buildid_dir(void) | ||
473 | { | ||
474 | buildid_dir[0] = '\0'; | ||
475 | |||
476 | /* try config file */ | ||
477 | check_buildid_dir_config(); | ||
478 | |||
479 | /* default to $HOME/.debug */ | ||
480 | if (buildid_dir[0] == '\0') { | ||
481 | char *v = getenv("HOME"); | ||
482 | if (v) { | ||
483 | snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", | ||
484 | v, DEBUG_CACHE_DIR); | ||
485 | } else { | ||
486 | strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); | ||
487 | } | ||
488 | buildid_dir[MAXPATHLEN-1] = '\0'; | ||
489 | } | ||
490 | /* for communicating with external commands */ | ||
491 | setenv("PERF_BUILDID_DIR", buildid_dir, 1); | ||
492 | } | ||
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c index 4e01490e51e5..0f9b8d7a7d7e 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -20,7 +20,7 @@ static int default_cpu_map(void) | |||
20 | return nr_cpus; | 20 | return nr_cpus; |
21 | } | 21 | } |
22 | 22 | ||
23 | int read_cpu_map(void) | 23 | static int read_all_cpu_map(void) |
24 | { | 24 | { |
25 | FILE *onlnf; | 25 | FILE *onlnf; |
26 | int nr_cpus = 0; | 26 | int nr_cpus = 0; |
@@ -57,3 +57,58 @@ int read_cpu_map(void) | |||
57 | 57 | ||
58 | return default_cpu_map(); | 58 | return default_cpu_map(); |
59 | } | 59 | } |
60 | |||
61 | int read_cpu_map(const char *cpu_list) | ||
62 | { | ||
63 | unsigned long start_cpu, end_cpu = 0; | ||
64 | char *p = NULL; | ||
65 | int i, nr_cpus = 0; | ||
66 | |||
67 | if (!cpu_list) | ||
68 | return read_all_cpu_map(); | ||
69 | |||
70 | if (!isdigit(*cpu_list)) | ||
71 | goto invalid; | ||
72 | |||
73 | while (isdigit(*cpu_list)) { | ||
74 | p = NULL; | ||
75 | start_cpu = strtoul(cpu_list, &p, 0); | ||
76 | if (start_cpu >= INT_MAX | ||
77 | || (*p != '\0' && *p != ',' && *p != '-')) | ||
78 | goto invalid; | ||
79 | |||
80 | if (*p == '-') { | ||
81 | cpu_list = ++p; | ||
82 | p = NULL; | ||
83 | end_cpu = strtoul(cpu_list, &p, 0); | ||
84 | |||
85 | if (end_cpu >= INT_MAX || (*p != '\0' && *p != ',')) | ||
86 | goto invalid; | ||
87 | |||
88 | if (end_cpu < start_cpu) | ||
89 | goto invalid; | ||
90 | } else { | ||
91 | end_cpu = start_cpu; | ||
92 | } | ||
93 | |||
94 | for (; start_cpu <= end_cpu; start_cpu++) { | ||
95 | /* check for duplicates */ | ||
96 | for (i = 0; i < nr_cpus; i++) | ||
97 | if (cpumap[i] == (int)start_cpu) | ||
98 | goto invalid; | ||
99 | |||
100 | assert(nr_cpus < MAX_NR_CPUS); | ||
101 | cpumap[nr_cpus++] = (int)start_cpu; | ||
102 | } | ||
103 | if (*p) | ||
104 | ++p; | ||
105 | |||
106 | cpu_list = p; | ||
107 | } | ||
108 | if (nr_cpus > 0) | ||
109 | return nr_cpus; | ||
110 | |||
111 | return default_cpu_map(); | ||
112 | invalid: | ||
113 | return -1; | ||
114 | } | ||
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 86c78bb33098..3e60f56e490e 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef __PERF_CPUMAP_H | 1 | #ifndef __PERF_CPUMAP_H |
2 | #define __PERF_CPUMAP_H | 2 | #define __PERF_CPUMAP_H |
3 | 3 | ||
4 | extern int read_cpu_map(void); | 4 | extern int read_cpu_map(const char *cpu_list); |
5 | extern int cpumap[]; | 5 | extern int cpumap[]; |
6 | 6 | ||
7 | #endif /* __PERF_CPUMAP_H */ | 7 | #endif /* __PERF_CPUMAP_H */ |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 1f08f008d289..a7460868124b 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -655,11 +655,36 @@ static void dso__calc_col_width(struct dso *self) | |||
655 | } | 655 | } |
656 | 656 | ||
657 | int event__preprocess_sample(const event_t *self, struct perf_session *session, | 657 | int event__preprocess_sample(const event_t *self, struct perf_session *session, |
658 | struct addr_location *al, symbol_filter_t filter) | 658 | struct addr_location *al, struct sample_data *data, |
659 | symbol_filter_t filter) | ||
659 | { | 660 | { |
660 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 661 | u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
661 | struct thread *thread = perf_session__findnew(session, self->ip.pid); | 662 | struct thread *thread; |
663 | |||
664 | event__parse_sample(self, session->sample_type, data); | ||
665 | |||
666 | dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld cpu:%d\n", | ||
667 | self->header.misc, data->pid, data->tid, data->ip, | ||
668 | data->period, data->cpu); | ||
669 | |||
670 | if (session->sample_type & PERF_SAMPLE_CALLCHAIN) { | ||
671 | unsigned int i; | ||
672 | |||
673 | dump_printf("... chain: nr:%Lu\n", data->callchain->nr); | ||
674 | |||
675 | if (!ip_callchain__valid(data->callchain, self)) { | ||
676 | pr_debug("call-chain problem with event, " | ||
677 | "skipping it.\n"); | ||
678 | goto out_filtered; | ||
679 | } | ||
662 | 680 | ||
681 | if (dump_trace) { | ||
682 | for (i = 0; i < data->callchain->nr; i++) | ||
683 | dump_printf("..... %2d: %016Lx\n", | ||
684 | i, data->callchain->ips[i]); | ||
685 | } | ||
686 | } | ||
687 | thread = perf_session__findnew(session, self->ip.pid); | ||
663 | if (thread == NULL) | 688 | if (thread == NULL) |
664 | return -1; | 689 | return -1; |
665 | 690 | ||
@@ -685,6 +710,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session, | |||
685 | al->map ? al->map->dso->long_name : | 710 | al->map ? al->map->dso->long_name : |
686 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 711 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
687 | al->sym = NULL; | 712 | al->sym = NULL; |
713 | al->cpu = data->cpu; | ||
688 | 714 | ||
689 | if (al->map) { | 715 | if (al->map) { |
690 | if (symbol_conf.dso_list && | 716 | if (symbol_conf.dso_list && |
@@ -724,9 +750,9 @@ out_filtered: | |||
724 | return 0; | 750 | return 0; |
725 | } | 751 | } |
726 | 752 | ||
727 | int event__parse_sample(event_t *event, u64 type, struct sample_data *data) | 753 | int event__parse_sample(const event_t *event, u64 type, struct sample_data *data) |
728 | { | 754 | { |
729 | u64 *array = event->sample.array; | 755 | const u64 *array = event->sample.array; |
730 | 756 | ||
731 | if (type & PERF_SAMPLE_IP) { | 757 | if (type & PERF_SAMPLE_IP) { |
732 | data->ip = event->ip.ip; | 758 | data->ip = event->ip.ip; |
@@ -765,7 +791,8 @@ int event__parse_sample(event_t *event, u64 type, struct sample_data *data) | |||
765 | u32 *p = (u32 *)array; | 791 | u32 *p = (u32 *)array; |
766 | data->cpu = *p; | 792 | data->cpu = *p; |
767 | array++; | 793 | array++; |
768 | } | 794 | } else |
795 | data->cpu = -1; | ||
769 | 796 | ||
770 | if (type & PERF_SAMPLE_PERIOD) { | 797 | if (type & PERF_SAMPLE_PERIOD) { |
771 | data->period = *array; | 798 | data->period = *array; |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 8577085db067..887ee63bbb62 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -157,8 +157,9 @@ int event__process_task(event_t *self, struct perf_session *session); | |||
157 | 157 | ||
158 | struct addr_location; | 158 | struct addr_location; |
159 | int event__preprocess_sample(const event_t *self, struct perf_session *session, | 159 | int event__preprocess_sample(const event_t *self, struct perf_session *session, |
160 | struct addr_location *al, symbol_filter_t filter); | 160 | struct addr_location *al, struct sample_data *data, |
161 | int event__parse_sample(event_t *event, u64 type, struct sample_data *data); | 161 | symbol_filter_t filter); |
162 | int event__parse_sample(const event_t *event, u64 type, struct sample_data *data); | ||
162 | 163 | ||
163 | extern const char *event__name[]; | 164 | extern const char *event__name[]; |
164 | 165 | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 1f62435f96c2..4a6a4b3a4ab7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -385,8 +385,7 @@ static int perf_session__cache_build_ids(struct perf_session *self) | |||
385 | int ret; | 385 | int ret; |
386 | char debugdir[PATH_MAX]; | 386 | char debugdir[PATH_MAX]; |
387 | 387 | ||
388 | snprintf(debugdir, sizeof(debugdir), "%s/%s", getenv("HOME"), | 388 | snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); |
389 | DEBUG_CACHE_DIR); | ||
390 | 389 | ||
391 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) | 390 | if (mkdir(debugdir, 0755) != 0 && errno != EEXIST) |
392 | return -1; | 391 | return -1; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 07f89b66b318..68d288c975de 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -70,6 +70,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, | |||
70 | .map = al->map, | 70 | .map = al->map, |
71 | .sym = al->sym, | 71 | .sym = al->sym, |
72 | }, | 72 | }, |
73 | .cpu = al->cpu, | ||
73 | .ip = al->addr, | 74 | .ip = al->addr, |
74 | .level = al->level, | 75 | .level = al->level, |
75 | .period = period, | 76 | .period = period, |
@@ -1037,7 +1038,7 @@ fallback: | |||
1037 | dso, dso->long_name, sym, sym->name); | 1038 | dso, dso->long_name, sym, sym->name); |
1038 | 1039 | ||
1039 | snprintf(command, sizeof(command), | 1040 | snprintf(command, sizeof(command), |
1040 | "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s|expand", | 1041 | "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand", |
1041 | map__rip_2objdump(map, sym->start), | 1042 | map__rip_2objdump(map, sym->start), |
1042 | map__rip_2objdump(map, sym->end), | 1043 | map__rip_2objdump(map, sym->end), |
1043 | filename, filename); | 1044 | filename, filename); |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 2316cb5a4116..c27b4b03fbc1 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -13,6 +13,7 @@ enum sort_type sort__first_dimension; | |||
13 | unsigned int dsos__col_width; | 13 | unsigned int dsos__col_width; |
14 | unsigned int comms__col_width; | 14 | unsigned int comms__col_width; |
15 | unsigned int threads__col_width; | 15 | unsigned int threads__col_width; |
16 | unsigned int cpus__col_width; | ||
16 | static unsigned int parent_symbol__col_width; | 17 | static unsigned int parent_symbol__col_width; |
17 | char * field_sep; | 18 | char * field_sep; |
18 | 19 | ||
@@ -28,6 +29,8 @@ static int hist_entry__sym_snprintf(struct hist_entry *self, char *bf, | |||
28 | size_t size, unsigned int width); | 29 | size_t size, unsigned int width); |
29 | static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, | 30 | static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, |
30 | size_t size, unsigned int width); | 31 | size_t size, unsigned int width); |
32 | static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, | ||
33 | size_t size, unsigned int width); | ||
31 | 34 | ||
32 | struct sort_entry sort_thread = { | 35 | struct sort_entry sort_thread = { |
33 | .se_header = "Command: Pid", | 36 | .se_header = "Command: Pid", |
@@ -63,6 +66,13 @@ struct sort_entry sort_parent = { | |||
63 | .se_snprintf = hist_entry__parent_snprintf, | 66 | .se_snprintf = hist_entry__parent_snprintf, |
64 | .se_width = &parent_symbol__col_width, | 67 | .se_width = &parent_symbol__col_width, |
65 | }; | 68 | }; |
69 | |||
70 | struct sort_entry sort_cpu = { | ||
71 | .se_header = "CPU", | ||
72 | .se_cmp = sort__cpu_cmp, | ||
73 | .se_snprintf = hist_entry__cpu_snprintf, | ||
74 | .se_width = &cpus__col_width, | ||
75 | }; | ||
66 | 76 | ||
67 | struct sort_dimension { | 77 | struct sort_dimension { |
68 | const char *name; | 78 | const char *name; |
@@ -76,6 +86,7 @@ static struct sort_dimension sort_dimensions[] = { | |||
76 | { .name = "dso", .entry = &sort_dso, }, | 86 | { .name = "dso", .entry = &sort_dso, }, |
77 | { .name = "symbol", .entry = &sort_sym, }, | 87 | { .name = "symbol", .entry = &sort_sym, }, |
78 | { .name = "parent", .entry = &sort_parent, }, | 88 | { .name = "parent", .entry = &sort_parent, }, |
89 | { .name = "cpu", .entry = &sort_cpu, }, | ||
79 | }; | 90 | }; |
80 | 91 | ||
81 | int64_t cmp_null(void *l, void *r) | 92 | int64_t cmp_null(void *l, void *r) |
@@ -242,6 +253,20 @@ static int hist_entry__parent_snprintf(struct hist_entry *self, char *bf, | |||
242 | self->parent ? self->parent->name : "[other]"); | 253 | self->parent ? self->parent->name : "[other]"); |
243 | } | 254 | } |
244 | 255 | ||
256 | /* --sort cpu */ | ||
257 | |||
258 | int64_t | ||
259 | sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right) | ||
260 | { | ||
261 | return right->cpu - left->cpu; | ||
262 | } | ||
263 | |||
264 | static int hist_entry__cpu_snprintf(struct hist_entry *self, char *bf, | ||
265 | size_t size, unsigned int width) | ||
266 | { | ||
267 | return repsep_snprintf(bf, size, "%-*d", width, self->cpu); | ||
268 | } | ||
269 | |||
245 | int sort_dimension__add(const char *tok) | 270 | int sort_dimension__add(const char *tok) |
246 | { | 271 | { |
247 | unsigned int i; | 272 | unsigned int i; |
@@ -281,6 +306,8 @@ int sort_dimension__add(const char *tok) | |||
281 | sort__first_dimension = SORT_SYM; | 306 | sort__first_dimension = SORT_SYM; |
282 | else if (!strcmp(sd->name, "parent")) | 307 | else if (!strcmp(sd->name, "parent")) |
283 | sort__first_dimension = SORT_PARENT; | 308 | sort__first_dimension = SORT_PARENT; |
309 | else if (!strcmp(sd->name, "cpu")) | ||
310 | sort__first_dimension = SORT_CPU; | ||
284 | } | 311 | } |
285 | 312 | ||
286 | list_add_tail(&sd->entry->list, &hist_entry__sort_list); | 313 | list_add_tail(&sd->entry->list, &hist_entry__sort_list); |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 0d61c4082f43..560c855417e4 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -39,6 +39,7 @@ extern struct sort_entry sort_parent; | |||
39 | extern unsigned int dsos__col_width; | 39 | extern unsigned int dsos__col_width; |
40 | extern unsigned int comms__col_width; | 40 | extern unsigned int comms__col_width; |
41 | extern unsigned int threads__col_width; | 41 | extern unsigned int threads__col_width; |
42 | extern unsigned int cpus__col_width; | ||
42 | extern enum sort_type sort__first_dimension; | 43 | extern enum sort_type sort__first_dimension; |
43 | 44 | ||
44 | struct hist_entry { | 45 | struct hist_entry { |
@@ -51,6 +52,7 @@ struct hist_entry { | |||
51 | struct map_symbol ms; | 52 | struct map_symbol ms; |
52 | struct thread *thread; | 53 | struct thread *thread; |
53 | u64 ip; | 54 | u64 ip; |
55 | s32 cpu; | ||
54 | u32 nr_events; | 56 | u32 nr_events; |
55 | char level; | 57 | char level; |
56 | u8 filtered; | 58 | u8 filtered; |
@@ -68,7 +70,8 @@ enum sort_type { | |||
68 | SORT_COMM, | 70 | SORT_COMM, |
69 | SORT_DSO, | 71 | SORT_DSO, |
70 | SORT_SYM, | 72 | SORT_SYM, |
71 | SORT_PARENT | 73 | SORT_PARENT, |
74 | SORT_CPU, | ||
72 | }; | 75 | }; |
73 | 76 | ||
74 | /* | 77 | /* |
@@ -104,6 +107,7 @@ extern int64_t sort__comm_collapse(struct hist_entry *, struct hist_entry *); | |||
104 | extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *); | 107 | extern int64_t sort__dso_cmp(struct hist_entry *, struct hist_entry *); |
105 | extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *); | 108 | extern int64_t sort__sym_cmp(struct hist_entry *, struct hist_entry *); |
106 | extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *); | 109 | extern int64_t sort__parent_cmp(struct hist_entry *, struct hist_entry *); |
110 | int64_t sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right); | ||
107 | extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int); | 111 | extern size_t sort__parent_print(FILE *, struct hist_entry *, unsigned int); |
108 | extern int sort_dimension__add(const char *); | 112 | extern int sort_dimension__add(const char *); |
109 | void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, | 113 | void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 5e02d2c17154..10b7ff859ce0 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -9,8 +9,6 @@ | |||
9 | #include <linux/rbtree.h> | 9 | #include <linux/rbtree.h> |
10 | #include <stdio.h> | 10 | #include <stdio.h> |
11 | 11 | ||
12 | #define DEBUG_CACHE_DIR ".debug" | ||
13 | |||
14 | #ifdef HAVE_CPLUS_DEMANGLE | 12 | #ifdef HAVE_CPLUS_DEMANGLE |
15 | extern char *cplus_demangle(const char *, int); | 13 | extern char *cplus_demangle(const char *, int); |
16 | 14 | ||
@@ -112,7 +110,8 @@ struct addr_location { | |||
112 | u64 addr; | 110 | u64 addr; |
113 | char level; | 111 | char level; |
114 | bool filtered; | 112 | bool filtered; |
115 | unsigned int cpumode; | 113 | u8 cpumode; |
114 | s32 cpu; | ||
116 | }; | 115 | }; |
117 | 116 | ||
118 | enum dso_kernel_type { | 117 | enum dso_kernel_type { |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 4e8b6b0c551c..de61441b6dd7 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -89,6 +89,7 @@ | |||
89 | 89 | ||
90 | extern const char *graph_line; | 90 | extern const char *graph_line; |
91 | extern const char *graph_dotted_line; | 91 | extern const char *graph_dotted_line; |
92 | extern char buildid_dir[]; | ||
92 | 93 | ||
93 | /* On most systems <limits.h> would have given us this, but | 94 | /* On most systems <limits.h> would have given us this, but |
94 | * not on some systems (e.g. GNU/Hurd). | 95 | * not on some systems (e.g. GNU/Hurd). |
@@ -152,6 +153,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))) | |||
152 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); | 153 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); |
153 | 154 | ||
154 | extern int prefixcmp(const char *str, const char *prefix); | 155 | extern int prefixcmp(const char *str, const char *prefix); |
156 | extern void set_buildid_dir(void); | ||
155 | 157 | ||
156 | static inline const char *skip_prefix(const char *str, const char *prefix) | 158 | static inline const char *skip_prefix(const char *str, const char *prefix) |
157 | { | 159 | { |