aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-02-17 03:02:28 -0500
committerIngo Molnar <mingo@elte.hu>2012-02-17 03:02:28 -0500
commitd1e169da9e20efc0762da6ec160dd7740d0103f5 (patch)
treeea1ec5ae77b11dc180724a51c61ad5695b2dbaa7
parentf8d98f1095210da708a59f3a0b6fd267ad8f3f03 (diff)
parent808e122630d45a7f036d25582474d70548a87e2c (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Includes smaller fixes and improvements plus the exclude_{host,guest} feature test and fallback to handle older kernels. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/Documentation/perf-stat.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt4
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile7
-rw-r--r--tools/perf/builtin-record.c46
-rw-r--r--tools/perf/builtin-stat.c31
-rw-r--r--tools/perf/builtin-test.c3
-rw-r--r--tools/perf/builtin-top.c44
-rw-r--r--tools/perf/perf.h8
-rw-r--r--tools/perf/util/bitmap.c10
-rw-r--r--tools/perf/util/ctype.c2
-rw-r--r--tools/perf/util/debugfs.c141
-rw-r--r--tools/perf/util/debugfs.h6
-rw-r--r--tools/perf/util/evlist.c10
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c6
-rw-r--r--tools/perf/util/header.c421
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/include/linux/bitmap.h11
-rw-r--r--tools/perf/util/python-ext-sources19
-rw-r--r--tools/perf/util/session.c10
-rw-r--r--tools/perf/util/setup.py8
-rw-r--r--tools/perf/util/symbol.c2
-rw-r--r--tools/perf/util/sysfs.c60
-rw-r--r--tools/perf/util/sysfs.h6
-rw-r--r--tools/perf/util/thread_map.c128
-rw-r--r--tools/perf/util/thread_map.h4
-rw-r--r--tools/perf/util/top.c10
-rw-r--r--tools/perf/util/top.h5
-rw-r--r--tools/perf/util/usage.c6
-rw-r--r--tools/perf/util/util.c4
-rw-r--r--tools/perf/util/util.h6
33 files changed, 616 insertions, 416 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index ff9a66e0d4e4..a5766b4b0125 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -52,11 +52,11 @@ OPTIONS
52 52
53-p:: 53-p::
54--pid=:: 54--pid=::
55 Record events on existing process ID. 55 Record events on existing process ID (comma separated list).
56 56
57-t:: 57-t::
58--tid=:: 58--tid=::
59 Record events on existing thread ID. 59 Record events on existing thread ID (comma separated list).
60 60
61-u:: 61-u::
62--uid=:: 62--uid=::
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 8966b9ab2014..2fa173b51970 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -35,11 +35,11 @@ OPTIONS
35 child tasks do not inherit counters 35 child tasks do not inherit counters
36-p:: 36-p::
37--pid=<pid>:: 37--pid=<pid>::
38 stat events on existing process id 38 stat events on existing process id (comma separated list)
39 39
40-t:: 40-t::
41--tid=<tid>:: 41--tid=<tid>::
42 stat events on existing thread id 42 stat events on existing thread id (comma separated list)
43 43
44 44
45-a:: 45-a::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index ab1454ed450f..4a5680cb242e 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -72,11 +72,11 @@ Default is to monitor all CPUS.
72 72
73-p <pid>:: 73-p <pid>::
74--pid=<pid>:: 74--pid=<pid>::
75 Profile events on existing Process ID. 75 Profile events on existing Process ID (comma separated list).
76 76
77-t <tid>:: 77-t <tid>::
78--tid=<tid>:: 78--tid=<tid>::
79 Profile events on existing thread ID. 79 Profile events on existing thread ID (comma separated list).
80 80
81-u:: 81-u::
82--uid=:: 82--uid=::
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 1078c5fadd5b..5476bc0a1eac 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -9,6 +9,7 @@ lib/rbtree.c
9include/linux/swab.h 9include/linux/swab.h
10arch/*/include/asm/unistd*.h 10arch/*/include/asm/unistd*.h
11arch/*/lib/memcpy*.S 11arch/*/lib/memcpy*.S
12arch/*/lib/memset*.S
12include/linux/poison.h 13include/linux/poison.h
13include/linux/magic.h 14include/linux/magic.h
14include/linux/hw_breakpoint.h 15include/linux/hw_breakpoint.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 64df5de12ca8..e011b5060f92 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -183,7 +183,10 @@ SCRIPT_SH += perf-archive.sh
183grep-libs = $(filter -l%,$(1)) 183grep-libs = $(filter -l%,$(1))
184strip-libs = $(filter-out -l%,$(1)) 184strip-libs = $(filter-out -l%,$(1))
185 185
186$(OUTPUT)python/perf.so: $(PYRF_OBJS) 186PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
187PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
188
189$(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
187 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \ 190 $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
188 --quiet build_ext; \ 191 --quiet build_ext; \
189 mkdir -p $(OUTPUT)python && \ 192 mkdir -p $(OUTPUT)python && \
@@ -256,6 +259,7 @@ LIB_H += util/callchain.h
256LIB_H += util/build-id.h 259LIB_H += util/build-id.h
257LIB_H += util/debug.h 260LIB_H += util/debug.h
258LIB_H += util/debugfs.h 261LIB_H += util/debugfs.h
262LIB_H += util/sysfs.h
259LIB_H += util/event.h 263LIB_H += util/event.h
260LIB_H += util/evsel.h 264LIB_H += util/evsel.h
261LIB_H += util/evlist.h 265LIB_H += util/evlist.h
@@ -302,6 +306,7 @@ LIB_OBJS += $(OUTPUT)util/build-id.o
302LIB_OBJS += $(OUTPUT)util/config.o 306LIB_OBJS += $(OUTPUT)util/config.o
303LIB_OBJS += $(OUTPUT)util/ctype.o 307LIB_OBJS += $(OUTPUT)util/ctype.o
304LIB_OBJS += $(OUTPUT)util/debugfs.o 308LIB_OBJS += $(OUTPUT)util/debugfs.o
309LIB_OBJS += $(OUTPUT)util/sysfs.o
305LIB_OBJS += $(OUTPUT)util/environment.o 310LIB_OBJS += $(OUTPUT)util/environment.o
306LIB_OBJS += $(OUTPUT)util/event.o 311LIB_OBJS += $(OUTPUT)util/event.o
307LIB_OBJS += $(OUTPUT)util/evlist.o 312LIB_OBJS += $(OUTPUT)util/evlist.o
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f8d9a545dd6e..75d230fef202 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -205,8 +205,11 @@ static void perf_record__open(struct perf_record *rec)
205 205
206 if (opts->group && pos != first) 206 if (opts->group && pos != first)
207 group_fd = first->fd; 207 group_fd = first->fd;
208fallback_missing_features:
209 if (opts->exclude_guest_missing)
210 attr->exclude_guest = attr->exclude_host = 0;
208retry_sample_id: 211retry_sample_id:
209 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 212 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
210try_again: 213try_again:
211 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, 214 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
212 opts->group, group_fd) < 0) { 215 opts->group, group_fd) < 0) {
@@ -218,15 +221,23 @@ try_again:
218 } else if (err == ENODEV && opts->cpu_list) { 221 } else if (err == ENODEV && opts->cpu_list) {
219 die("No such device - did you specify" 222 die("No such device - did you specify"
220 " an out-of-range profile CPU?\n"); 223 " an out-of-range profile CPU?\n");
221 } else if (err == EINVAL && opts->sample_id_all_avail) { 224 } else if (err == EINVAL) {
222 /* 225 if (!opts->exclude_guest_missing &&
223 * Old kernel, no attr->sample_id_type_all field 226 (attr->exclude_guest || attr->exclude_host)) {
224 */ 227 pr_debug("Old kernel, cannot exclude "
225 opts->sample_id_all_avail = false; 228 "guest or host samples.\n");
226 if (!opts->sample_time && !opts->raw_samples && !time_needed) 229 opts->exclude_guest_missing = true;
227 attr->sample_type &= ~PERF_SAMPLE_TIME; 230 goto fallback_missing_features;
228 231 } else if (!opts->sample_id_all_missing) {
229 goto retry_sample_id; 232 /*
233 * Old kernel, no attr->sample_id_type_all field
234 */
235 opts->sample_id_all_missing = true;
236 if (!opts->sample_time && !opts->raw_samples && !time_needed)
237 attr->sample_type &= ~PERF_SAMPLE_TIME;
238
239 goto retry_sample_id;
240 }
230 } 241 }
231 242
232 /* 243 /*
@@ -494,9 +505,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
494 return err; 505 return err;
495 } 506 }
496 507
497 if (!!rec->no_buildid 508 if (!rec->no_buildid
498 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { 509 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
499 pr_err("Couldn't generating buildids. " 510 pr_err("Couldn't generate buildids. "
500 "Use --no-buildid to profile anyway.\n"); 511 "Use --no-buildid to profile anyway.\n");
501 return -1; 512 return -1;
502 } 513 }
@@ -645,13 +656,10 @@ static const char * const record_usage[] = {
645 */ 656 */
646static struct perf_record record = { 657static struct perf_record record = {
647 .opts = { 658 .opts = {
648 .target_pid = -1,
649 .target_tid = -1,
650 .mmap_pages = UINT_MAX, 659 .mmap_pages = UINT_MAX,
651 .user_freq = UINT_MAX, 660 .user_freq = UINT_MAX,
652 .user_interval = ULLONG_MAX, 661 .user_interval = ULLONG_MAX,
653 .freq = 1000, 662 .freq = 1000,
654 .sample_id_all_avail = true,
655 }, 663 },
656 .write_mode = WRITE_FORCE, 664 .write_mode = WRITE_FORCE,
657 .file_new = true, 665 .file_new = true,
@@ -670,9 +678,9 @@ const struct option record_options[] = {
670 parse_events_option), 678 parse_events_option),
671 OPT_CALLBACK(0, "filter", &record.evlist, "filter", 679 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
672 "event filter", parse_filter), 680 "event filter", parse_filter),
673 OPT_INTEGER('p', "pid", &record.opts.target_pid, 681 OPT_STRING('p', "pid", &record.opts.target_pid, "pid",
674 "record events on existing process id"), 682 "record events on existing process id"),
675 OPT_INTEGER('t', "tid", &record.opts.target_tid, 683 OPT_STRING('t', "tid", &record.opts.target_tid, "tid",
676 "record events on existing thread id"), 684 "record events on existing thread id"),
677 OPT_INTEGER('r', "realtime", &record.realtime_prio, 685 OPT_INTEGER('r', "realtime", &record.realtime_prio,
678 "collect data with this RT SCHED_FIFO priority"), 686 "collect data with this RT SCHED_FIFO priority"),
@@ -739,7 +747,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
739 747
740 argc = parse_options(argc, argv, record_options, record_usage, 748 argc = parse_options(argc, argv, record_options, record_usage,
741 PARSE_OPT_STOP_AT_NON_OPTION); 749 PARSE_OPT_STOP_AT_NON_OPTION);
742 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 750 if (!argc && !rec->opts.target_pid && !rec->opts.target_tid &&
743 !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str) 751 !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
744 usage_with_options(record_usage, record_options); 752 usage_with_options(record_usage, record_options);
745 753
@@ -785,7 +793,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
785 if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1) 793 if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1)
786 goto out_free_fd; 794 goto out_free_fd;
787 795
788 if (rec->opts.target_pid != -1) 796 if (rec->opts.target_pid)
789 rec->opts.target_tid = rec->opts.target_pid; 797 rec->opts.target_tid = rec->opts.target_pid;
790 798
791 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 799 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index d14b37ad7638..ea40e4e8b227 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -182,8 +182,8 @@ static int run_count = 1;
182static bool no_inherit = false; 182static bool no_inherit = false;
183static bool scale = true; 183static bool scale = true;
184static bool no_aggr = false; 184static bool no_aggr = false;
185static pid_t target_pid = -1; 185static const char *target_pid;
186static pid_t target_tid = -1; 186static const char *target_tid;
187static pid_t child_pid = -1; 187static pid_t child_pid = -1;
188static bool null_run = false; 188static bool null_run = false;
189static int detailed_run = 0; 189static int detailed_run = 0;
@@ -296,7 +296,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
296 if (system_wide) 296 if (system_wide)
297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
298 group, group_fd); 298 group, group_fd);
299 if (target_pid == -1 && target_tid == -1) { 299 if (!target_pid && !target_tid) {
300 attr->disabled = 1; 300 attr->disabled = 1;
301 attr->enable_on_exec = 1; 301 attr->enable_on_exec = 1;
302 } 302 }
@@ -446,7 +446,7 @@ static int run_perf_stat(int argc __used, const char **argv)
446 exit(-1); 446 exit(-1);
447 } 447 }
448 448
449 if (target_tid == -1 && target_pid == -1 && !system_wide) 449 if (!target_tid && !target_pid && !system_wide)
450 evsel_list->threads->map[0] = child_pid; 450 evsel_list->threads->map[0] = child_pid;
451 451
452 /* 452 /*
@@ -968,14 +968,14 @@ static void print_stat(int argc, const char **argv)
968 if (!csv_output) { 968 if (!csv_output) {
969 fprintf(output, "\n"); 969 fprintf(output, "\n");
970 fprintf(output, " Performance counter stats for "); 970 fprintf(output, " Performance counter stats for ");
971 if(target_pid == -1 && target_tid == -1) { 971 if (!target_pid && !target_tid) {
972 fprintf(output, "\'%s", argv[0]); 972 fprintf(output, "\'%s", argv[0]);
973 for (i = 1; i < argc; i++) 973 for (i = 1; i < argc; i++)
974 fprintf(output, " %s", argv[i]); 974 fprintf(output, " %s", argv[i]);
975 } else if (target_pid != -1) 975 } else if (target_pid)
976 fprintf(output, "process id \'%d", target_pid); 976 fprintf(output, "process id \'%s", target_pid);
977 else 977 else
978 fprintf(output, "thread id \'%d", target_tid); 978 fprintf(output, "thread id \'%s", target_tid);
979 979
980 fprintf(output, "\'"); 980 fprintf(output, "\'");
981 if (run_count > 1) 981 if (run_count > 1)
@@ -1049,10 +1049,10 @@ static const struct option options[] = {
1049 "event filter", parse_filter), 1049 "event filter", parse_filter),
1050 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 1050 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1051 "child tasks do not inherit counters"), 1051 "child tasks do not inherit counters"),
1052 OPT_INTEGER('p', "pid", &target_pid, 1052 OPT_STRING('p', "pid", &target_pid, "pid",
1053 "stat events on existing process id"), 1053 "stat events on existing process id"),
1054 OPT_INTEGER('t', "tid", &target_tid, 1054 OPT_STRING('t', "tid", &target_tid, "tid",
1055 "stat events on existing thread id"), 1055 "stat events on existing thread id"),
1056 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1056 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1057 "system-wide collection from all CPUs"), 1057 "system-wide collection from all CPUs"),
1058 OPT_BOOLEAN('g', "group", &group, 1058 OPT_BOOLEAN('g', "group", &group,
@@ -1190,7 +1190,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1190 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1190 } else if (big_num_opt == 0) /* User passed --no-big-num */
1191 big_num = false; 1191 big_num = false;
1192 1192
1193 if (!argc && target_pid == -1 && target_tid == -1) 1193 if (!argc && !target_pid && !target_tid)
1194 usage_with_options(stat_usage, options); 1194 usage_with_options(stat_usage, options);
1195 if (run_count <= 0) 1195 if (run_count <= 0)
1196 usage_with_options(stat_usage, options); 1196 usage_with_options(stat_usage, options);
@@ -1206,10 +1206,11 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1206 if (add_default_attributes()) 1206 if (add_default_attributes())
1207 goto out; 1207 goto out;
1208 1208
1209 if (target_pid != -1) 1209 if (target_pid)
1210 target_tid = target_pid; 1210 target_tid = target_pid;
1211 1211
1212 evsel_list->threads = thread_map__new(target_pid, target_tid, UINT_MAX); 1212 evsel_list->threads = thread_map__new_str(target_pid,
1213 target_tid, UINT_MAX);
1213 if (evsel_list->threads == NULL) { 1214 if (evsel_list->threads == NULL) {
1214 pr_err("Problems finding threads of monitor\n"); 1215 pr_err("Problems finding threads of monitor\n");
1215 usage_with_options(stat_usage, options); 1216 usage_with_options(stat_usage, options);
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 70c4eb2bdf72..3e087ce8daa6 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -1010,12 +1010,9 @@ realloc:
1010static int test__PERF_RECORD(void) 1010static int test__PERF_RECORD(void)
1011{ 1011{
1012 struct perf_record_opts opts = { 1012 struct perf_record_opts opts = {
1013 .target_pid = -1,
1014 .target_tid = -1,
1015 .no_delay = true, 1013 .no_delay = true,
1016 .freq = 10, 1014 .freq = 10,
1017 .mmap_pages = 256, 1015 .mmap_pages = 256,
1018 .sample_id_all_avail = true,
1019 }; 1016 };
1020 cpu_set_t *cpu_mask = NULL; 1017 cpu_set_t *cpu_mask = NULL;
1021 size_t cpu_mask_size = 0; 1018 size_t cpu_mask_size = 0;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index d869b214ada2..e3c63aef8efc 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -677,6 +677,12 @@ static void perf_event__process_sample(struct perf_tool *tool,
677 return; 677 return;
678 } 678 }
679 679
680 if (!machine) {
681 pr_err("%u unprocessable samples recorded.",
682 top->session->hists.stats.nr_unprocessable_samples++);
683 return;
684 }
685
680 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 686 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
681 top->exact_samples++; 687 top->exact_samples++;
682 688
@@ -866,8 +872,11 @@ static void perf_top__start_counters(struct perf_top *top)
866 attr->mmap = 1; 872 attr->mmap = 1;
867 attr->comm = 1; 873 attr->comm = 1;
868 attr->inherit = top->inherit; 874 attr->inherit = top->inherit;
875fallback_missing_features:
876 if (top->exclude_guest_missing)
877 attr->exclude_guest = attr->exclude_host = 0;
869retry_sample_id: 878retry_sample_id:
870 attr->sample_id_all = top->sample_id_all_avail ? 1 : 0; 879 attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
871try_again: 880try_again:
872 if (perf_evsel__open(counter, top->evlist->cpus, 881 if (perf_evsel__open(counter, top->evlist->cpus,
873 top->evlist->threads, top->group, 882 top->evlist->threads, top->group,
@@ -877,12 +886,20 @@ try_again:
877 if (err == EPERM || err == EACCES) { 886 if (err == EPERM || err == EACCES) {
878 ui__error_paranoid(); 887 ui__error_paranoid();
879 goto out_err; 888 goto out_err;
880 } else if (err == EINVAL && top->sample_id_all_avail) { 889 } else if (err == EINVAL) {
881 /* 890 if (!top->exclude_guest_missing &&
882 * Old kernel, no attr->sample_id_type_all field 891 (attr->exclude_guest || attr->exclude_host)) {
883 */ 892 pr_debug("Old kernel, cannot exclude "
884 top->sample_id_all_avail = false; 893 "guest or host samples.\n");
885 goto retry_sample_id; 894 top->exclude_guest_missing = true;
895 goto fallback_missing_features;
896 } else if (!top->sample_id_all_missing) {
897 /*
898 * Old kernel, no attr->sample_id_type_all field
899 */
900 top->sample_id_all_missing = true;
901 goto retry_sample_id;
902 }
886 } 903 }
887 /* 904 /*
888 * If it's cycles then fall back to hrtimer 905 * If it's cycles then fall back to hrtimer
@@ -965,7 +982,7 @@ static int __cmd_top(struct perf_top *top)
965 if (ret) 982 if (ret)
966 goto out_delete; 983 goto out_delete;
967 984
968 if (top->target_tid != -1 || top->uid != UINT_MAX) 985 if (top->target_tid || top->uid != UINT_MAX)
969 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 986 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
970 perf_event__process, 987 perf_event__process,
971 &top->session->host_machine); 988 &top->session->host_machine);
@@ -1103,11 +1120,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1103 struct perf_top top = { 1120 struct perf_top top = {
1104 .count_filter = 5, 1121 .count_filter = 5,
1105 .delay_secs = 2, 1122 .delay_secs = 2,
1106 .target_pid = -1,
1107 .target_tid = -1,
1108 .uid = UINT_MAX, 1123 .uid = UINT_MAX,
1109 .freq = 1000, /* 1 KHz */ 1124 .freq = 1000, /* 1 KHz */
1110 .sample_id_all_avail = true,
1111 .mmap_pages = 128, 1125 .mmap_pages = 128,
1112 .sym_pcnt_filter = 5, 1126 .sym_pcnt_filter = 5,
1113 }; 1127 };
@@ -1118,9 +1132,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1118 parse_events_option), 1132 parse_events_option),
1119 OPT_INTEGER('c', "count", &top.default_interval, 1133 OPT_INTEGER('c', "count", &top.default_interval,
1120 "event period to sample"), 1134 "event period to sample"),
1121 OPT_INTEGER('p', "pid", &top.target_pid, 1135 OPT_STRING('p', "pid", &top.target_pid, "pid",
1122 "profile events on existing process id"), 1136 "profile events on existing process id"),
1123 OPT_INTEGER('t', "tid", &top.target_tid, 1137 OPT_STRING('t', "tid", &top.target_tid, "tid",
1124 "profile events on existing thread id"), 1138 "profile events on existing thread id"),
1125 OPT_BOOLEAN('a', "all-cpus", &top.system_wide, 1139 OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
1126 "system-wide collection from all CPUs"), 1140 "system-wide collection from all CPUs"),
@@ -1210,13 +1224,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1210 goto out_delete_evlist; 1224 goto out_delete_evlist;
1211 1225
1212 /* CPU and PID are mutually exclusive */ 1226 /* CPU and PID are mutually exclusive */
1213 if (top.target_tid > 0 && top.cpu_list) { 1227 if (top.target_tid && top.cpu_list) {
1214 printf("WARNING: PID switch overriding CPU\n"); 1228 printf("WARNING: PID switch overriding CPU\n");
1215 sleep(1); 1229 sleep(1);
1216 top.cpu_list = NULL; 1230 top.cpu_list = NULL;
1217 } 1231 }
1218 1232
1219 if (top.target_pid != -1) 1233 if (top.target_pid)
1220 top.target_tid = top.target_pid; 1234 top.target_tid = top.target_pid;
1221 1235
1222 if (perf_evlist__create_maps(top.evlist, top.target_pid, 1236 if (perf_evlist__create_maps(top.evlist, top.target_pid,
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 92af1688bae4..f0227e93665d 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -167,7 +167,6 @@ sys_perf_event_open(struct perf_event_attr *attr,
167 pid_t pid, int cpu, int group_fd, 167 pid_t pid, int cpu, int group_fd,
168 unsigned long flags) 168 unsigned long flags)
169{ 169{
170 attr->size = sizeof(*attr);
171 return syscall(__NR_perf_event_open, attr, pid, cpu, 170 return syscall(__NR_perf_event_open, attr, pid, cpu,
172 group_fd, flags); 171 group_fd, flags);
173} 172}
@@ -186,8 +185,8 @@ extern const char perf_version_string[];
186void pthread__unblock_sigwinch(void); 185void pthread__unblock_sigwinch(void);
187 186
188struct perf_record_opts { 187struct perf_record_opts {
189 pid_t target_pid; 188 const char *target_pid;
190 pid_t target_tid; 189 const char *target_tid;
191 uid_t uid; 190 uid_t uid;
192 bool call_graph; 191 bool call_graph;
193 bool group; 192 bool group;
@@ -199,7 +198,8 @@ struct perf_record_opts {
199 bool raw_samples; 198 bool raw_samples;
200 bool sample_address; 199 bool sample_address;
201 bool sample_time; 200 bool sample_time;
202 bool sample_id_all_avail; 201 bool sample_id_all_missing;
202 bool exclude_guest_missing;
203 bool system_wide; 203 bool system_wide;
204 bool period; 204 bool period;
205 unsigned int freq; 205 unsigned int freq;
diff --git a/tools/perf/util/bitmap.c b/tools/perf/util/bitmap.c
index 5e230acae1e9..0a1adc1111fd 100644
--- a/tools/perf/util/bitmap.c
+++ b/tools/perf/util/bitmap.c
@@ -19,3 +19,13 @@ int __bitmap_weight(const unsigned long *bitmap, int bits)
19 19
20 return w; 20 return w;
21} 21}
22
23void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
24 const unsigned long *bitmap2, int bits)
25{
26 int k;
27 int nr = BITS_TO_LONGS(bits);
28
29 for (k = 0; k < nr; k++)
30 dst[k] = bitmap1[k] | bitmap2[k];
31}
diff --git a/tools/perf/util/ctype.c b/tools/perf/util/ctype.c
index 35073621e5de..aada3ac5e891 100644
--- a/tools/perf/util/ctype.c
+++ b/tools/perf/util/ctype.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * No surprises, and works with signed and unsigned chars. 4 * No surprises, and works with signed and unsigned chars.
5 */ 5 */
6#include "cache.h" 6#include "util.h"
7 7
8enum { 8enum {
9 S = GIT_SPACE, 9 S = GIT_SPACE,
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index ffc35e748e89..dd8b19319c03 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -15,32 +15,6 @@ static const char *debugfs_known_mountpoints[] = {
15 0, 15 0,
16}; 16};
17 17
18/* use this to force a umount */
19void debugfs_force_cleanup(void)
20{
21 debugfs_find_mountpoint();
22 debugfs_premounted = 0;
23 debugfs_umount();
24}
25
26/* construct a full path to a debugfs element */
27int debugfs_make_path(const char *element, char *buffer, int size)
28{
29 int len;
30
31 if (strlen(debugfs_mountpoint) == 0) {
32 buffer[0] = '\0';
33 return -1;
34 }
35
36 len = strlen(debugfs_mountpoint) + strlen(element) + 1;
37 if (len >= size)
38 return len+1;
39
40 snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
41 return 0;
42}
43
44static int debugfs_found; 18static int debugfs_found;
45 19
46/* find the path to the mounted debugfs */ 20/* find the path to the mounted debugfs */
@@ -97,17 +71,6 @@ int debugfs_valid_mountpoint(const char *debugfs)
97 return 0; 71 return 0;
98} 72}
99 73
100
101int debugfs_valid_entry(const char *path)
102{
103 struct stat st;
104
105 if (stat(path, &st))
106 return -errno;
107
108 return 0;
109}
110
111static void debugfs_set_tracing_events_path(const char *mountpoint) 74static void debugfs_set_tracing_events_path(const char *mountpoint)
112{ 75{
113 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 76 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -149,107 +112,3 @@ void debugfs_set_path(const char *mountpoint)
149 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint); 112 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
150 debugfs_set_tracing_events_path(mountpoint); 113 debugfs_set_tracing_events_path(mountpoint);
151} 114}
152
153/* umount the debugfs */
154
155int debugfs_umount(void)
156{
157 char umountcmd[128];
158 int ret;
159
160 /* if it was already mounted, leave it */
161 if (debugfs_premounted)
162 return 0;
163
164 /* make sure it's a valid mount point */
165 ret = debugfs_valid_mountpoint(debugfs_mountpoint);
166 if (ret)
167 return ret;
168
169 snprintf(umountcmd, sizeof(umountcmd),
170 "/bin/umount %s", debugfs_mountpoint);
171 return system(umountcmd);
172}
173
174int debugfs_write(const char *entry, const char *value)
175{
176 char path[PATH_MAX + 1];
177 int ret, count;
178 int fd;
179
180 /* construct the path */
181 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
182
183 /* verify that it exists */
184 ret = debugfs_valid_entry(path);
185 if (ret)
186 return ret;
187
188 /* get how many chars we're going to write */
189 count = strlen(value);
190
191 /* open the debugfs entry */
192 fd = open(path, O_RDWR);
193 if (fd < 0)
194 return -errno;
195
196 while (count > 0) {
197 /* write it */
198 ret = write(fd, value, count);
199 if (ret <= 0) {
200 if (ret == EAGAIN)
201 continue;
202 close(fd);
203 return -errno;
204 }
205 count -= ret;
206 }
207
208 /* close it */
209 close(fd);
210
211 /* return success */
212 return 0;
213}
214
215/*
216 * read a debugfs entry
217 * returns the number of chars read or a negative errno
218 */
219int debugfs_read(const char *entry, char *buffer, size_t size)
220{
221 char path[PATH_MAX + 1];
222 int ret;
223 int fd;
224
225 /* construct the path */
226 snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
227
228 /* verify that it exists */
229 ret = debugfs_valid_entry(path);
230 if (ret)
231 return ret;
232
233 /* open the debugfs entry */
234 fd = open(path, O_RDONLY);
235 if (fd < 0)
236 return -errno;
237
238 do {
239 /* read it */
240 ret = read(fd, buffer, size);
241 if (ret == 0) {
242 close(fd);
243 return EOF;
244 }
245 } while (ret < 0 && errno == EAGAIN);
246
247 /* close it */
248 close(fd);
249
250 /* make *sure* there's a null character at the end */
251 buffer[ret] = '\0';
252
253 /* return the number of chars read */
254 return ret;
255}
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 4a878f735eb0..68f3e87ec57f 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -3,14 +3,8 @@
3 3
4const char *debugfs_find_mountpoint(void); 4const char *debugfs_find_mountpoint(void);
5int debugfs_valid_mountpoint(const char *debugfs); 5int debugfs_valid_mountpoint(const char *debugfs);
6int debugfs_valid_entry(const char *path);
7char *debugfs_mount(const char *mountpoint); 6char *debugfs_mount(const char *mountpoint);
8int debugfs_umount(void);
9void debugfs_set_path(const char *mountpoint); 7void debugfs_set_path(const char *mountpoint);
10int debugfs_write(const char *entry, const char *value);
11int debugfs_read(const char *entry, char *buffer, size_t size);
12void debugfs_force_cleanup(void);
13int debugfs_make_path(const char *element, char *buffer, int size);
14 8
15extern char debugfs_mountpoint[]; 9extern char debugfs_mountpoint[];
16extern char tracing_events_path[]; 10extern char tracing_events_path[];
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a57a8cfc5d90..5c61dc57d7c7 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -593,15 +593,15 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
593 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 593 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
594} 594}
595 595
596int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 596int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
597 pid_t target_tid, uid_t uid, const char *cpu_list) 597 const char *target_tid, uid_t uid, const char *cpu_list)
598{ 598{
599 evlist->threads = thread_map__new(target_pid, target_tid, uid); 599 evlist->threads = thread_map__new_str(target_pid, target_tid, uid);
600 600
601 if (evlist->threads == NULL) 601 if (evlist->threads == NULL)
602 return -1; 602 return -1;
603 603
604 if (uid != UINT_MAX || (cpu_list == NULL && target_tid != -1)) 604 if (uid != UINT_MAX || (cpu_list == NULL && target_tid))
605 evlist->cpus = cpu_map__dummy_new(); 605 evlist->cpus = cpu_map__dummy_new();
606 else 606 else
607 evlist->cpus = cpu_map__new(cpu_list); 607 evlist->cpus = cpu_map__new(cpu_list);
@@ -820,7 +820,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
820 exit(-1); 820 exit(-1);
821 } 821 }
822 822
823 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1) 823 if (!opts->system_wide && !opts->target_tid && !opts->target_pid)
824 evlist->threads->map[0] = evlist->workload.pid; 824 evlist->threads->map[0] = evlist->workload.pid;
825 825
826 close(child_ready_pipe[1]); 826 close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 1b4282be8fe7..21f1c9e57f13 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -106,8 +106,8 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
106 evlist->threads = threads; 106 evlist->threads = threads;
107} 107}
108 108
109int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 109int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid,
110 pid_t tid, uid_t uid, const char *cpu_list); 110 const char *tid, uid_t uid, const char *cpu_list);
111void perf_evlist__delete_maps(struct perf_evlist *evlist); 111void perf_evlist__delete_maps(struct perf_evlist *evlist);
112int perf_evlist__set_filters(struct perf_evlist *evlist); 112int perf_evlist__set_filters(struct perf_evlist *evlist);
113 113
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 9a11f9edac12..302d49a9f985 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -68,7 +68,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
68 struct perf_event_attr *attr = &evsel->attr; 68 struct perf_event_attr *attr = &evsel->attr;
69 int track = !evsel->idx; /* only the first counter needs these */ 69 int track = !evsel->idx; /* only the first counter needs these */
70 70
71 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0; 71 attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
72 attr->inherit = !opts->no_inherit; 72 attr->inherit = !opts->no_inherit;
73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
74 PERF_FORMAT_TOTAL_TIME_RUNNING | 74 PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -111,7 +111,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
111 if (opts->period) 111 if (opts->period)
112 attr->sample_type |= PERF_SAMPLE_PERIOD; 112 attr->sample_type |= PERF_SAMPLE_PERIOD;
113 113
114 if (opts->sample_id_all_avail && 114 if (!opts->sample_id_all_missing &&
115 (opts->sample_time || opts->system_wide || 115 (opts->sample_time || opts->system_wide ||
116 !opts->no_inherit || opts->cpu_list)) 116 !opts->no_inherit || opts->cpu_list))
117 attr->sample_type |= PERF_SAMPLE_TIME; 117 attr->sample_type |= PERF_SAMPLE_TIME;
@@ -130,7 +130,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
130 attr->mmap = track; 130 attr->mmap = track;
131 attr->comm = track; 131 attr->comm = track;
132 132
133 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) { 133 if (!opts->target_pid && !opts->target_tid && !opts->system_wide) {
134 attr->disabled = 1; 134 attr->disabled = 1;
135 attr->enable_on_exec = 1; 135 attr->enable_on_exec = 1;
136 } 136 }
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ecd7f4dd7eea..9f867d96c6a5 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -63,9 +63,20 @@ char *perf_header__find_event(u64 id)
63 return NULL; 63 return NULL;
64} 64}
65 65
66static const char *__perf_magic = "PERFFILE"; 66/*
67 * magic2 = "PERFILE2"
68 * must be a numerical value to let the endianness
69 * determine the memory layout. That way we are able
70 * to detect endianness when reading the perf.data file
71 * back.
72 *
73 * we check for legacy (PERFFILE) format.
74 */
75static const char *__perf_magic1 = "PERFFILE";
76static const u64 __perf_magic2 = 0x32454c4946524550ULL;
77static const u64 __perf_magic2_sw = 0x50455246494c4532ULL;
67 78
68#define PERF_MAGIC (*(u64 *)__perf_magic) 79#define PERF_MAGIC __perf_magic2
69 80
70struct perf_file_attr { 81struct perf_file_attr {
71 struct perf_event_attr attr; 82 struct perf_event_attr attr;
@@ -1305,25 +1316,198 @@ static void print_cpuid(struct perf_header *ph, int fd, FILE *fp)
1305 free(str); 1316 free(str);
1306} 1317}
1307 1318
1319static int __event_process_build_id(struct build_id_event *bev,
1320 char *filename,
1321 struct perf_session *session)
1322{
1323 int err = -1;
1324 struct list_head *head;
1325 struct machine *machine;
1326 u16 misc;
1327 struct dso *dso;
1328 enum dso_kernel_type dso_type;
1329
1330 machine = perf_session__findnew_machine(session, bev->pid);
1331 if (!machine)
1332 goto out;
1333
1334 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1335
1336 switch (misc) {
1337 case PERF_RECORD_MISC_KERNEL:
1338 dso_type = DSO_TYPE_KERNEL;
1339 head = &machine->kernel_dsos;
1340 break;
1341 case PERF_RECORD_MISC_GUEST_KERNEL:
1342 dso_type = DSO_TYPE_GUEST_KERNEL;
1343 head = &machine->kernel_dsos;
1344 break;
1345 case PERF_RECORD_MISC_USER:
1346 case PERF_RECORD_MISC_GUEST_USER:
1347 dso_type = DSO_TYPE_USER;
1348 head = &machine->user_dsos;
1349 break;
1350 default:
1351 goto out;
1352 }
1353
1354 dso = __dsos__findnew(head, filename);
1355 if (dso != NULL) {
1356 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1357
1358 dso__set_build_id(dso, &bev->build_id);
1359
1360 if (filename[0] == '[')
1361 dso->kernel = dso_type;
1362
1363 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1364 sbuild_id);
1365 pr_debug("build id event received for %s: %s\n",
1366 dso->long_name, sbuild_id);
1367 }
1368
1369 err = 0;
1370out:
1371 return err;
1372}
1373
1374static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1375 int input, u64 offset, u64 size)
1376{
1377 struct perf_session *session = container_of(header, struct perf_session, header);
1378 struct {
1379 struct perf_event_header header;
1380 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1381 char filename[0];
1382 } old_bev;
1383 struct build_id_event bev;
1384 char filename[PATH_MAX];
1385 u64 limit = offset + size;
1386
1387 while (offset < limit) {
1388 ssize_t len;
1389
1390 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
1391 return -1;
1392
1393 if (header->needs_swap)
1394 perf_event_header__bswap(&old_bev.header);
1395
1396 len = old_bev.header.size - sizeof(old_bev);
1397 if (read(input, filename, len) != len)
1398 return -1;
1399
1400 bev.header = old_bev.header;
1401
1402 /*
1403 * As the pid is the missing value, we need to fill
1404 * it properly. The header.misc value give us nice hint.
1405 */
1406 bev.pid = HOST_KERNEL_ID;
1407 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1408 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1409 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1410
1411 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1412 __event_process_build_id(&bev, filename, session);
1413
1414 offset += bev.header.size;
1415 }
1416
1417 return 0;
1418}
1419
1420static int perf_header__read_build_ids(struct perf_header *header,
1421 int input, u64 offset, u64 size)
1422{
1423 struct perf_session *session = container_of(header, struct perf_session, header);
1424 struct build_id_event bev;
1425 char filename[PATH_MAX];
1426 u64 limit = offset + size, orig_offset = offset;
1427 int err = -1;
1428
1429 while (offset < limit) {
1430 ssize_t len;
1431
1432 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
1433 goto out;
1434
1435 if (header->needs_swap)
1436 perf_event_header__bswap(&bev.header);
1437
1438 len = bev.header.size - sizeof(bev);
1439 if (read(input, filename, len) != len)
1440 goto out;
1441 /*
1442 * The a1645ce1 changeset:
1443 *
1444 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1445 *
1446 * Added a field to struct build_id_event that broke the file
1447 * format.
1448 *
1449 * Since the kernel build-id is the first entry, process the
1450 * table using the old format if the well known
1451 * '[kernel.kallsyms]' string for the kernel build-id has the
1452 * first 4 characters chopped off (where the pid_t sits).
1453 */
1454 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1455 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1456 return -1;
1457 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1458 }
1459
1460 __event_process_build_id(&bev, filename, session);
1461
1462 offset += bev.header.size;
1463 }
1464 err = 0;
1465out:
1466 return err;
1467}
1468
1469static int process_trace_info(struct perf_file_section *section __unused,
1470 struct perf_header *ph __unused,
1471 int feat __unused, int fd)
1472{
1473 trace_report(fd, false);
1474 return 0;
1475}
1476
1477static int process_build_id(struct perf_file_section *section,
1478 struct perf_header *ph,
1479 int feat __unused, int fd)
1480{
1481 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1482 pr_debug("Failed to read buildids, continuing...\n");
1483 return 0;
1484}
1485
1308struct feature_ops { 1486struct feature_ops {
1309 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); 1487 int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
1310 void (*print)(struct perf_header *h, int fd, FILE *fp); 1488 void (*print)(struct perf_header *h, int fd, FILE *fp);
1489 int (*process)(struct perf_file_section *section,
1490 struct perf_header *h, int feat, int fd);
1311 const char *name; 1491 const char *name;
1312 bool full_only; 1492 bool full_only;
1313}; 1493};
1314 1494
1315#define FEAT_OPA(n, func) \ 1495#define FEAT_OPA(n, func) \
1316 [n] = { .name = #n, .write = write_##func, .print = print_##func } 1496 [n] = { .name = #n, .write = write_##func, .print = print_##func }
1497#define FEAT_OPP(n, func) \
1498 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1499 .process = process_##func }
1317#define FEAT_OPF(n, func) \ 1500#define FEAT_OPF(n, func) \
1318 [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true } 1501 [n] = { .name = #n, .write = write_##func, .print = print_##func, \
1502 .full_only = true }
1319 1503
1320/* feature_ops not implemented: */ 1504/* feature_ops not implemented: */
1321#define print_trace_info NULL 1505#define print_trace_info NULL
1322#define print_build_id NULL 1506#define print_build_id NULL
1323 1507
1324static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { 1508static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
1325 FEAT_OPA(HEADER_TRACE_INFO, trace_info), 1509 FEAT_OPP(HEADER_TRACE_INFO, trace_info),
1326 FEAT_OPA(HEADER_BUILD_ID, build_id), 1510 FEAT_OPP(HEADER_BUILD_ID, build_id),
1327 FEAT_OPA(HEADER_HOSTNAME, hostname), 1511 FEAT_OPA(HEADER_HOSTNAME, hostname),
1328 FEAT_OPA(HEADER_OSRELEASE, osrelease), 1512 FEAT_OPA(HEADER_OSRELEASE, osrelease),
1329 FEAT_OPA(HEADER_VERSION, version), 1513 FEAT_OPA(HEADER_VERSION, version),
@@ -1620,24 +1804,59 @@ out_free:
1620 return err; 1804 return err;
1621} 1805}
1622 1806
1807static int check_magic_endian(u64 *magic, struct perf_file_header *header,
1808 struct perf_header *ph)
1809{
1810 int ret;
1811
1812 /* check for legacy format */
1813 ret = memcmp(magic, __perf_magic1, sizeof(*magic));
1814 if (ret == 0) {
1815 pr_debug("legacy perf.data format\n");
1816 if (!header)
1817 return -1;
1818
1819 if (header->attr_size != sizeof(struct perf_file_attr)) {
1820 u64 attr_size = bswap_64(header->attr_size);
1821
1822 if (attr_size != sizeof(struct perf_file_attr))
1823 return -1;
1824
1825 ph->needs_swap = true;
1826 }
1827 return 0;
1828 }
1829
1830 /* check magic number with same endianness */
1831 if (*magic == __perf_magic2)
1832 return 0;
1833
1834 /* check magic number but opposite endianness */
1835 if (*magic != __perf_magic2_sw)
1836 return -1;
1837
1838 ph->needs_swap = true;
1839
1840 return 0;
1841}
1842
1623int perf_file_header__read(struct perf_file_header *header, 1843int perf_file_header__read(struct perf_file_header *header,
1624 struct perf_header *ph, int fd) 1844 struct perf_header *ph, int fd)
1625{ 1845{
1846 int ret;
1847
1626 lseek(fd, 0, SEEK_SET); 1848 lseek(fd, 0, SEEK_SET);
1627 1849
1628 if (readn(fd, header, sizeof(*header)) <= 0 || 1850 ret = readn(fd, header, sizeof(*header));
1629 memcmp(&header->magic, __perf_magic, sizeof(header->magic))) 1851 if (ret <= 0)
1630 return -1; 1852 return -1;
1631 1853
1632 if (header->attr_size != sizeof(struct perf_file_attr)) { 1854 if (check_magic_endian(&header->magic, header, ph) < 0)
1633 u64 attr_size = bswap_64(header->attr_size); 1855 return -1;
1634
1635 if (attr_size != sizeof(struct perf_file_attr))
1636 return -1;
1637 1856
1857 if (ph->needs_swap) {
1638 mem_bswap_64(header, offsetof(struct perf_file_header, 1858 mem_bswap_64(header, offsetof(struct perf_file_header,
1639 adds_features)); 1859 adds_features));
1640 ph->needs_swap = true;
1641 } 1860 }
1642 1861
1643 if (header->size != sizeof(*header)) { 1862 if (header->size != sizeof(*header)) {
@@ -1689,156 +1908,6 @@ int perf_file_header__read(struct perf_file_header *header,
1689 return 0; 1908 return 0;
1690} 1909}
1691 1910
1692static int __event_process_build_id(struct build_id_event *bev,
1693 char *filename,
1694 struct perf_session *session)
1695{
1696 int err = -1;
1697 struct list_head *head;
1698 struct machine *machine;
1699 u16 misc;
1700 struct dso *dso;
1701 enum dso_kernel_type dso_type;
1702
1703 machine = perf_session__findnew_machine(session, bev->pid);
1704 if (!machine)
1705 goto out;
1706
1707 misc = bev->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1708
1709 switch (misc) {
1710 case PERF_RECORD_MISC_KERNEL:
1711 dso_type = DSO_TYPE_KERNEL;
1712 head = &machine->kernel_dsos;
1713 break;
1714 case PERF_RECORD_MISC_GUEST_KERNEL:
1715 dso_type = DSO_TYPE_GUEST_KERNEL;
1716 head = &machine->kernel_dsos;
1717 break;
1718 case PERF_RECORD_MISC_USER:
1719 case PERF_RECORD_MISC_GUEST_USER:
1720 dso_type = DSO_TYPE_USER;
1721 head = &machine->user_dsos;
1722 break;
1723 default:
1724 goto out;
1725 }
1726
1727 dso = __dsos__findnew(head, filename);
1728 if (dso != NULL) {
1729 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1730
1731 dso__set_build_id(dso, &bev->build_id);
1732
1733 if (filename[0] == '[')
1734 dso->kernel = dso_type;
1735
1736 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
1737 sbuild_id);
1738 pr_debug("build id event received for %s: %s\n",
1739 dso->long_name, sbuild_id);
1740 }
1741
1742 err = 0;
1743out:
1744 return err;
1745}
1746
1747static int perf_header__read_build_ids_abi_quirk(struct perf_header *header,
1748 int input, u64 offset, u64 size)
1749{
1750 struct perf_session *session = container_of(header, struct perf_session, header);
1751 struct {
1752 struct perf_event_header header;
1753 u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))];
1754 char filename[0];
1755 } old_bev;
1756 struct build_id_event bev;
1757 char filename[PATH_MAX];
1758 u64 limit = offset + size;
1759
1760 while (offset < limit) {
1761 ssize_t len;
1762
1763 if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev))
1764 return -1;
1765
1766 if (header->needs_swap)
1767 perf_event_header__bswap(&old_bev.header);
1768
1769 len = old_bev.header.size - sizeof(old_bev);
1770 if (read(input, filename, len) != len)
1771 return -1;
1772
1773 bev.header = old_bev.header;
1774
1775 /*
1776 * As the pid is the missing value, we need to fill
1777 * it properly. The header.misc value give us nice hint.
1778 */
1779 bev.pid = HOST_KERNEL_ID;
1780 if (bev.header.misc == PERF_RECORD_MISC_GUEST_USER ||
1781 bev.header.misc == PERF_RECORD_MISC_GUEST_KERNEL)
1782 bev.pid = DEFAULT_GUEST_KERNEL_ID;
1783
1784 memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id));
1785 __event_process_build_id(&bev, filename, session);
1786
1787 offset += bev.header.size;
1788 }
1789
1790 return 0;
1791}
1792
1793static int perf_header__read_build_ids(struct perf_header *header,
1794 int input, u64 offset, u64 size)
1795{
1796 struct perf_session *session = container_of(header, struct perf_session, header);
1797 struct build_id_event bev;
1798 char filename[PATH_MAX];
1799 u64 limit = offset + size, orig_offset = offset;
1800 int err = -1;
1801
1802 while (offset < limit) {
1803 ssize_t len;
1804
1805 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
1806 goto out;
1807
1808 if (header->needs_swap)
1809 perf_event_header__bswap(&bev.header);
1810
1811 len = bev.header.size - sizeof(bev);
1812 if (read(input, filename, len) != len)
1813 goto out;
1814 /*
1815 * The a1645ce1 changeset:
1816 *
1817 * "perf: 'perf kvm' tool for monitoring guest performance from host"
1818 *
1819 * Added a field to struct build_id_event that broke the file
1820 * format.
1821 *
1822 * Since the kernel build-id is the first entry, process the
1823 * table using the old format if the well known
1824 * '[kernel.kallsyms]' string for the kernel build-id has the
1825 * first 4 characters chopped off (where the pid_t sits).
1826 */
1827 if (memcmp(filename, "nel.kallsyms]", 13) == 0) {
1828 if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1)
1829 return -1;
1830 return perf_header__read_build_ids_abi_quirk(header, input, offset, size);
1831 }
1832
1833 __event_process_build_id(&bev, filename, session);
1834
1835 offset += bev.header.size;
1836 }
1837 err = 0;
1838out:
1839 return err;
1840}
1841
1842static int perf_file_section__process(struct perf_file_section *section, 1911static int perf_file_section__process(struct perf_file_section *section,
1843 struct perf_header *ph, 1912 struct perf_header *ph,
1844 int feat, int fd, void *data __used) 1913 int feat, int fd, void *data __used)
@@ -1854,27 +1923,23 @@ static int perf_file_section__process(struct perf_file_section *section,
1854 return 0; 1923 return 0;
1855 } 1924 }
1856 1925
1857 switch (feat) { 1926 if (!feat_ops[feat].process)
1858 case HEADER_TRACE_INFO: 1927 return 0;
1859 trace_report(fd, false);
1860 break;
1861 case HEADER_BUILD_ID:
1862 if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
1863 pr_debug("Failed to read buildids, continuing...\n");
1864 break;
1865 default:
1866 break;
1867 }
1868 1928
1869 return 0; 1929 return feat_ops[feat].process(section, ph, feat, fd);
1870} 1930}
1871 1931
1872static int perf_file_header__read_pipe(struct perf_pipe_file_header *header, 1932static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
1873 struct perf_header *ph, int fd, 1933 struct perf_header *ph, int fd,
1874 bool repipe) 1934 bool repipe)
1875{ 1935{
1876 if (readn(fd, header, sizeof(*header)) <= 0 || 1936 int ret;
1877 memcmp(&header->magic, __perf_magic, sizeof(header->magic))) 1937
1938 ret = readn(fd, header, sizeof(*header));
1939 if (ret <= 0)
1940 return -1;
1941
1942 if (check_magic_endian(&header->magic, NULL, ph) < 0)
1878 return -1; 1943 return -1;
1879 1944
1880 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0) 1945 if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 0d486135d10f..48e5acd1e862 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -32,6 +32,7 @@ struct events_stats {
32 u32 nr_unknown_events; 32 u32 nr_unknown_events;
33 u32 nr_invalid_chains; 33 u32 nr_invalid_chains;
34 u32 nr_unknown_id; 34 u32 nr_unknown_id;
35 u32 nr_unprocessable_samples;
35}; 36};
36 37
37enum hist_column { 38enum hist_column {
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index eda4416efa0a..bb162e40c76c 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -5,6 +5,8 @@
5#include <linux/bitops.h> 5#include <linux/bitops.h>
6 6
7int __bitmap_weight(const unsigned long *bitmap, int bits); 7int __bitmap_weight(const unsigned long *bitmap, int bits);
8void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
9 const unsigned long *bitmap2, int bits);
8 10
9#define BITMAP_LAST_WORD_MASK(nbits) \ 11#define BITMAP_LAST_WORD_MASK(nbits) \
10( \ 12( \
@@ -32,4 +34,13 @@ static inline int bitmap_weight(const unsigned long *src, int nbits)
32 return __bitmap_weight(src, nbits); 34 return __bitmap_weight(src, nbits);
33} 35}
34 36
37static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
38 const unsigned long *src2, int nbits)
39{
40 if (small_const_nbits(nbits))
41 *dst = *src1 | *src2;
42 else
43 __bitmap_or(dst, src1, src2, nbits);
44}
45
35#endif /* _PERF_BITOPS_H */ 46#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
new file mode 100644
index 000000000000..2884e67ee625
--- /dev/null
+++ b/tools/perf/util/python-ext-sources
@@ -0,0 +1,19 @@
1#
2# List of files needed by perf python extention
3#
4# Each source file must be placed on its own line so that it can be
5# processed by Makefile and util/setup.py accordingly.
6#
7
8util/python.c
9util/ctype.c
10util/evlist.c
11util/evsel.c
12util/cpumap.c
13util/thread_map.c
14util/util.c
15util/xyarray.c
16util/cgroup.c
17util/debugfs.c
18util/strlist.c
19../../lib/rbtree.c
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 552c1c50eea1..9f833cf9c6a9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -796,6 +796,10 @@ static int perf_session_deliver_event(struct perf_session *session,
796 ++session->hists.stats.nr_unknown_id; 796 ++session->hists.stats.nr_unknown_id;
797 return -1; 797 return -1;
798 } 798 }
799 if (machine == NULL) {
800 ++session->hists.stats.nr_unprocessable_samples;
801 return -1;
802 }
799 return tool->sample(tool, event, sample, evsel, machine); 803 return tool->sample(tool, event, sample, evsel, machine);
800 case PERF_RECORD_MMAP: 804 case PERF_RECORD_MMAP:
801 return tool->mmap(tool, event, sample, machine); 805 return tool->mmap(tool, event, sample, machine);
@@ -964,6 +968,12 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
964 session->hists.stats.nr_invalid_chains, 968 session->hists.stats.nr_invalid_chains,
965 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]); 969 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
966 } 970 }
971
972 if (session->hists.stats.nr_unprocessable_samples != 0) {
973 ui__warning("%u unprocessable samples recorded.\n"
974 "Do you have a KVM guest running and not using 'perf kvm'?\n",
975 session->hists.stats.nr_unprocessable_samples);
976 }
967} 977}
968 978
969#define session_done() (*(volatile int *)(&session_done)) 979#define session_done() (*(volatile int *)(&session_done))
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 36d4c5619575..d0f9f29cf181 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -24,11 +24,11 @@ cflags += getenv('CFLAGS', '').split()
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 24build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 25build_tmp = getenv('PYTHON_EXTBUILD_TMP')
26 26
27ext_sources = [f.strip() for f in file('util/python-ext-sources')
28 if len(f.strip()) > 0 and f[0] != '#']
29
27perf = Extension('perf', 30perf = Extension('perf',
28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 31 sources = ext_sources,
29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
31 'util/debugfs.c'],
32 include_dirs = ['util/include'], 32 include_dirs = ['util/include'],
33 extra_compile_args = cflags, 33 extra_compile_args = cflags,
34 ) 34 )
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index fc6e12fe4b44..5dd83c3e2c0c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,4 +1,3 @@
1#include <ctype.h>
2#include <dirent.h> 1#include <dirent.h>
3#include <errno.h> 2#include <errno.h>
4#include <libgen.h> 3#include <libgen.h>
@@ -12,6 +11,7 @@
12#include <unistd.h> 11#include <unistd.h>
13#include <inttypes.h> 12#include <inttypes.h>
14#include "build-id.h" 13#include "build-id.h"
14#include "util.h"
15#include "debug.h" 15#include "debug.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
diff --git a/tools/perf/util/sysfs.c b/tools/perf/util/sysfs.c
new file mode 100644
index 000000000000..48c6902e749f
--- /dev/null
+++ b/tools/perf/util/sysfs.c
@@ -0,0 +1,60 @@
1
2#include "util.h"
3#include "sysfs.h"
4
5static const char * const sysfs_known_mountpoints[] = {
6 "/sys",
7 0,
8};
9
10static int sysfs_found;
11char sysfs_mountpoint[PATH_MAX];
12
13static int sysfs_valid_mountpoint(const char *sysfs)
14{
15 struct statfs st_fs;
16
17 if (statfs(sysfs, &st_fs) < 0)
18 return -ENOENT;
19 else if (st_fs.f_type != (long) SYSFS_MAGIC)
20 return -ENOENT;
21
22 return 0;
23}
24
25const char *sysfs_find_mountpoint(void)
26{
27 const char * const *ptr;
28 char type[100];
29 FILE *fp;
30
31 if (sysfs_found)
32 return (const char *) sysfs_mountpoint;
33
34 ptr = sysfs_known_mountpoints;
35 while (*ptr) {
36 if (sysfs_valid_mountpoint(*ptr) == 0) {
37 sysfs_found = 1;
38 strcpy(sysfs_mountpoint, *ptr);
39 return sysfs_mountpoint;
40 }
41 ptr++;
42 }
43
44 /* give up and parse /proc/mounts */
45 fp = fopen("/proc/mounts", "r");
46 if (fp == NULL)
47 return NULL;
48
49 while (!sysfs_found &&
50 fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
51 sysfs_mountpoint, type) == 2) {
52
53 if (strcmp(type, "sysfs") == 0)
54 sysfs_found = 1;
55 }
56
57 fclose(fp);
58
59 return sysfs_found ? sysfs_mountpoint : NULL;
60}
diff --git a/tools/perf/util/sysfs.h b/tools/perf/util/sysfs.h
new file mode 100644
index 000000000000..a813b7203938
--- /dev/null
+++ b/tools/perf/util/sysfs.h
@@ -0,0 +1,6 @@
1#ifndef __SYSFS_H__
2#define __SYSFS_H__
3
4const char *sysfs_find_mountpoint(void);
5
6#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 3d4b6c5931b9..e15983cf077d 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -6,6 +6,8 @@
6#include <sys/types.h> 6#include <sys/types.h>
7#include <sys/stat.h> 7#include <sys/stat.h>
8#include <unistd.h> 8#include <unistd.h>
9#include "strlist.h"
10#include <string.h>
9#include "thread_map.h" 11#include "thread_map.h"
10 12
11/* Skip "." and ".." directories */ 13/* Skip "." and ".." directories */
@@ -152,6 +154,132 @@ struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
152 return thread_map__new_by_tid(tid); 154 return thread_map__new_by_tid(tid);
153} 155}
154 156
157static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
158{
159 struct thread_map *threads = NULL, *nt;
160 char name[256];
161 int items, total_tasks = 0;
162 struct dirent **namelist = NULL;
163 int i, j = 0;
164 pid_t pid, prev_pid = INT_MAX;
165 char *end_ptr;
166 struct str_node *pos;
167 struct strlist *slist = strlist__new(false, pid_str);
168
169 if (!slist)
170 return NULL;
171
172 strlist__for_each(pos, slist) {
173 pid = strtol(pos->s, &end_ptr, 10);
174
175 if (pid == INT_MIN || pid == INT_MAX ||
176 (*end_ptr != '\0' && *end_ptr != ','))
177 goto out_free_threads;
178
179 if (pid == prev_pid)
180 continue;
181
182 sprintf(name, "/proc/%d/task", pid);
183 items = scandir(name, &namelist, filter, NULL);
184 if (items <= 0)
185 goto out_free_threads;
186
187 total_tasks += items;
188 nt = realloc(threads, (sizeof(*threads) +
189 sizeof(pid_t) * total_tasks));
190 if (nt == NULL)
191 goto out_free_threads;
192
193 threads = nt;
194
195 if (threads) {
196 for (i = 0; i < items; i++)
197 threads->map[j++] = atoi(namelist[i]->d_name);
198 threads->nr = total_tasks;
199 }
200
201 for (i = 0; i < items; i++)
202 free(namelist[i]);
203 free(namelist);
204
205 if (!threads)
206 break;
207 }
208
209out:
210 strlist__delete(slist);
211 return threads;
212
213out_free_threads:
214 free(threads);
215 threads = NULL;
216 goto out;
217}
218
219static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
220{
221 struct thread_map *threads = NULL, *nt;
222 int ntasks = 0;
223 pid_t tid, prev_tid = INT_MAX;
224 char *end_ptr;
225 struct str_node *pos;
226 struct strlist *slist;
227
228 /* perf-stat expects threads to be generated even if tid not given */
229 if (!tid_str) {
230 threads = malloc(sizeof(*threads) + sizeof(pid_t));
231 if (threads != NULL) {
232 threads->map[1] = -1;
233 threads->nr = 1;
234 }
235 return threads;
236 }
237
238 slist = strlist__new(false, tid_str);
239 if (!slist)
240 return NULL;
241
242 strlist__for_each(pos, slist) {
243 tid = strtol(pos->s, &end_ptr, 10);
244
245 if (tid == INT_MIN || tid == INT_MAX ||
246 (*end_ptr != '\0' && *end_ptr != ','))
247 goto out_free_threads;
248
249 if (tid == prev_tid)
250 continue;
251
252 ntasks++;
253 nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks);
254
255 if (nt == NULL)
256 goto out_free_threads;
257
258 threads = nt;
259 threads->map[ntasks - 1] = tid;
260 threads->nr = ntasks;
261 }
262out:
263 return threads;
264
265out_free_threads:
266 free(threads);
267 threads = NULL;
268 goto out;
269}
270
271struct thread_map *thread_map__new_str(const char *pid, const char *tid,
272 uid_t uid)
273{
274 if (pid)
275 return thread_map__new_by_pid_str(pid);
276
277 if (!tid && uid != UINT_MAX)
278 return thread_map__new_by_uid(uid);
279
280 return thread_map__new_by_tid_str(tid);
281}
282
155void thread_map__delete(struct thread_map *threads) 283void thread_map__delete(struct thread_map *threads)
156{ 284{
157 free(threads); 285 free(threads);
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index c75ddbaba005..7da80f14418b 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -13,6 +13,10 @@ struct thread_map *thread_map__new_by_pid(pid_t pid);
13struct thread_map *thread_map__new_by_tid(pid_t tid); 13struct thread_map *thread_map__new_by_tid(pid_t tid);
14struct thread_map *thread_map__new_by_uid(uid_t uid); 14struct thread_map *thread_map__new_by_uid(uid_t uid);
15struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); 15struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
16
17struct thread_map *thread_map__new_str(const char *pid,
18 const char *tid, uid_t uid);
19
16void thread_map__delete(struct thread_map *threads); 20void thread_map__delete(struct thread_map *threads);
17 21
18size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); 22size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index e4370ca27193..09fe579ccafb 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -69,11 +69,11 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
69 69
70 ret += SNPRINTF(bf + ret, size - ret, "], "); 70 ret += SNPRINTF(bf + ret, size - ret, "], ");
71 71
72 if (top->target_pid != -1) 72 if (top->target_pid)
73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %d", 73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
74 top->target_pid); 74 top->target_pid);
75 else if (top->target_tid != -1) 75 else if (top->target_tid)
76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d", 76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s",
77 top->target_tid); 77 top->target_tid);
78 else if (top->uid_str != NULL) 78 else if (top->uid_str != NULL)
79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", 79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
@@ -85,7 +85,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
85 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)", 85 ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
86 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list); 86 top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list);
87 else { 87 else {
88 if (top->target_tid != -1) 88 if (top->target_tid)
89 ret += SNPRINTF(bf + ret, size - ret, ")"); 89 ret += SNPRINTF(bf + ret, size - ret, ")");
90 else 90 else
91 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", 91 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index def3e53e0fe0..ce61cb2d1acf 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -23,7 +23,7 @@ struct perf_top {
23 u64 guest_us_samples, guest_kernel_samples; 23 u64 guest_us_samples, guest_kernel_samples;
24 int print_entries, count_filter, delay_secs; 24 int print_entries, count_filter, delay_secs;
25 int freq; 25 int freq;
26 pid_t target_pid, target_tid; 26 const char *target_pid, *target_tid;
27 uid_t uid; 27 uid_t uid;
28 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
29 bool system_wide; 29 bool system_wide;
@@ -34,7 +34,8 @@ struct perf_top {
34 bool vmlinux_warned; 34 bool vmlinux_warned;
35 bool inherit; 35 bool inherit;
36 bool group; 36 bool group;
37 bool sample_id_all_avail; 37 bool sample_id_all_missing;
38 bool exclude_guest_missing;
38 bool dump_symtab; 39 bool dump_symtab;
39 const char *cpu_list; 40 const char *cpu_list;
40 struct hist_entry *sym_filter_entry; 41 struct hist_entry *sym_filter_entry;
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index d0c013934f30..52bb07c6442a 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -83,7 +83,7 @@ void warning(const char *warn, ...)
83 va_end(params); 83 va_end(params);
84} 84}
85 85
86uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid) 86uid_t parse_target_uid(const char *str, const char *tid, const char *pid)
87{ 87{
88 struct passwd pwd, *result; 88 struct passwd pwd, *result;
89 char buf[1024]; 89 char buf[1024];
@@ -91,8 +91,8 @@ uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid)
91 if (str == NULL) 91 if (str == NULL)
92 return UINT_MAX; 92 return UINT_MAX;
93 93
94 /* CPU and PID are mutually exclusive */ 94 /* UID and PID are mutually exclusive */
95 if (tid > 0 || pid > 0) { 95 if (tid || pid) {
96 ui__warning("PID/TID switch overriding UID\n"); 96 ui__warning("PID/TID switch overriding UID\n");
97 sleep(1); 97 sleep(1);
98 return UINT_MAX; 98 return UINT_MAX;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 813141047fc2..8109a907841e 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -6,7 +6,7 @@
6 * XXX We need to find a better place for these things... 6 * XXX We need to find a better place for these things...
7 */ 7 */
8bool perf_host = true; 8bool perf_host = true;
9bool perf_guest = true; 9bool perf_guest = false;
10 10
11void event_attr_init(struct perf_event_attr *attr) 11void event_attr_init(struct perf_event_attr *attr)
12{ 12{
@@ -14,6 +14,8 @@ void event_attr_init(struct perf_event_attr *attr)
14 attr->exclude_host = 1; 14 attr->exclude_host = 1;
15 if (!perf_guest) 15 if (!perf_guest)
16 attr->exclude_guest = 1; 16 attr->exclude_guest = 1;
17 /* to capture ABI version */
18 attr->size = sizeof(*attr);
17} 19}
18 20
19int mkdir_p(char *path, mode_t mode) 21int mkdir_p(char *path, mode_t mode)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 232d17ef3e60..0f99f394d8e0 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -199,6 +199,8 @@ static inline int has_extension(const char *filename, const char *ext)
199#undef isalpha 199#undef isalpha
200#undef isprint 200#undef isprint
201#undef isalnum 201#undef isalnum
202#undef islower
203#undef isupper
202#undef tolower 204#undef tolower
203#undef toupper 205#undef toupper
204 206
@@ -219,6 +221,8 @@ extern unsigned char sane_ctype[256];
219#define isalpha(x) sane_istest(x,GIT_ALPHA) 221#define isalpha(x) sane_istest(x,GIT_ALPHA)
220#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 222#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
221#define isprint(x) sane_istest(x,GIT_PRINT) 223#define isprint(x) sane_istest(x,GIT_PRINT)
224#define islower(x) (sane_istest(x,GIT_ALPHA) && sane_istest(x,0x20))
225#define isupper(x) (sane_istest(x,GIT_ALPHA) && !sane_istest(x,0x20))
222#define tolower(x) sane_case((unsigned char)(x), 0x20) 226#define tolower(x) sane_case((unsigned char)(x), 0x20)
223#define toupper(x) sane_case((unsigned char)(x), 0) 227#define toupper(x) sane_case((unsigned char)(x), 0)
224 228
@@ -245,7 +249,7 @@ struct perf_event_attr;
245 249
246void event_attr_init(struct perf_event_attr *attr); 250void event_attr_init(struct perf_event_attr *attr);
247 251
248uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid); 252uid_t parse_target_uid(const char *str, const char *tid, const char *pid);
249 253
250#define _STR(x) #x 254#define _STR(x) #x
251#define STR(x) _STR(x) 255#define STR(x) _STR(x)