diff options
author | David Ahern <dsahern@gmail.com> | 2012-02-08 11:32:52 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-02-13 19:54:11 -0500 |
commit | b52956c961be3a04182ae7b776623531601e0fb7 (patch) | |
tree | 2f7ebf4a910dc8cd9014ac9df59f7e2441a5b034 /tools | |
parent | eca1c3e3f937307331fd1fd5ee5205e57f2131ca (diff) |
perf tools: Allow multiple threads or processes in record, stat, top
Allow a user to collect events for multiple threads or processes
using a comma separated list.
e.g., collect data on a VM and its vhost thread:
perf top -p 21483,21485
perf stat -p 21483,21485 -ddd
perf record -p 21483,21485
or monitoring vcpu threads
perf top -t 21488,21489
perf stat -t 21488,21489 -ddd
perf record -t 21488,21489
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1328718772-16688-1-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 4 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-stat.txt | 4 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-top.txt | 4 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 10 | ||||
-rw-r--r-- | tools/perf/builtin-stat.c | 31 | ||||
-rw-r--r-- | tools/perf/builtin-test.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 12 | ||||
-rw-r--r-- | tools/perf/perf.h | 4 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 10 | ||||
-rw-r--r-- | tools/perf/util/evlist.h | 4 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 2 | ||||
-rw-r--r-- | tools/perf/util/python-ext-sources | 2 | ||||
-rw-r--r-- | tools/perf/util/thread_map.c | 128 | ||||
-rw-r--r-- | tools/perf/util/thread_map.h | 4 | ||||
-rw-r--r-- | tools/perf/util/top.c | 10 | ||||
-rw-r--r-- | tools/perf/util/top.h | 2 | ||||
-rw-r--r-- | tools/perf/util/usage.c | 6 | ||||
-rw-r--r-- | tools/perf/util/util.h | 2 |
18 files changed, 185 insertions, 56 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/builtin-record.c b/tools/perf/builtin-record.c index d6d1c6cdcfe6..08ed24b66ffe 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -645,8 +645,6 @@ static const char * const record_usage[] = { | |||
645 | */ | 645 | */ |
646 | static struct perf_record record = { | 646 | static struct perf_record record = { |
647 | .opts = { | 647 | .opts = { |
648 | .target_pid = -1, | ||
649 | .target_tid = -1, | ||
650 | .mmap_pages = UINT_MAX, | 648 | .mmap_pages = UINT_MAX, |
651 | .user_freq = UINT_MAX, | 649 | .user_freq = UINT_MAX, |
652 | .user_interval = ULLONG_MAX, | 650 | .user_interval = ULLONG_MAX, |
@@ -670,9 +668,9 @@ const struct option record_options[] = { | |||
670 | parse_events_option), | 668 | parse_events_option), |
671 | OPT_CALLBACK(0, "filter", &record.evlist, "filter", | 669 | OPT_CALLBACK(0, "filter", &record.evlist, "filter", |
672 | "event filter", parse_filter), | 670 | "event filter", parse_filter), |
673 | OPT_INTEGER('p', "pid", &record.opts.target_pid, | 671 | OPT_STRING('p', "pid", &record.opts.target_pid, "pid", |
674 | "record events on existing process id"), | 672 | "record events on existing process id"), |
675 | OPT_INTEGER('t', "tid", &record.opts.target_tid, | 673 | OPT_STRING('t', "tid", &record.opts.target_tid, "tid", |
676 | "record events on existing thread id"), | 674 | "record events on existing thread id"), |
677 | OPT_INTEGER('r', "realtime", &record.realtime_prio, | 675 | OPT_INTEGER('r', "realtime", &record.realtime_prio, |
678 | "collect data with this RT SCHED_FIFO priority"), | 676 | "collect data with this RT SCHED_FIFO priority"), |
@@ -739,7 +737,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) | |||
739 | 737 | ||
740 | argc = parse_options(argc, argv, record_options, record_usage, | 738 | argc = parse_options(argc, argv, record_options, record_usage, |
741 | PARSE_OPT_STOP_AT_NON_OPTION); | 739 | PARSE_OPT_STOP_AT_NON_OPTION); |
742 | if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && | 740 | if (!argc && !rec->opts.target_pid && !rec->opts.target_tid && |
743 | !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str) | 741 | !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str) |
744 | usage_with_options(record_usage, record_options); | 742 | usage_with_options(record_usage, record_options); |
745 | 743 | ||
@@ -785,7 +783,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) | 783 | if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1) |
786 | goto out_free_fd; | 784 | goto out_free_fd; |
787 | 785 | ||
788 | if (rec->opts.target_pid != -1) | 786 | if (rec->opts.target_pid) |
789 | rec->opts.target_tid = rec->opts.target_pid; | 787 | rec->opts.target_tid = rec->opts.target_pid; |
790 | 788 | ||
791 | if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, | 789 | 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; | |||
182 | static bool no_inherit = false; | 182 | static bool no_inherit = false; |
183 | static bool scale = true; | 183 | static bool scale = true; |
184 | static bool no_aggr = false; | 184 | static bool no_aggr = false; |
185 | static pid_t target_pid = -1; | 185 | static const char *target_pid; |
186 | static pid_t target_tid = -1; | 186 | static const char *target_tid; |
187 | static pid_t child_pid = -1; | 187 | static pid_t child_pid = -1; |
188 | static bool null_run = false; | 188 | static bool null_run = false; |
189 | static int detailed_run = 0; | 189 | static 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..0f151952a770 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c | |||
@@ -1010,8 +1010,6 @@ realloc: | |||
1010 | static int test__PERF_RECORD(void) | 1010 | static 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, |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index d869b214ada2..94d55cb2048c 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -965,7 +965,7 @@ static int __cmd_top(struct perf_top *top) | |||
965 | if (ret) | 965 | if (ret) |
966 | goto out_delete; | 966 | goto out_delete; |
967 | 967 | ||
968 | if (top->target_tid != -1 || top->uid != UINT_MAX) | 968 | if (top->target_tid || top->uid != UINT_MAX) |
969 | perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, | 969 | perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, |
970 | perf_event__process, | 970 | perf_event__process, |
971 | &top->session->host_machine); | 971 | &top->session->host_machine); |
@@ -1103,8 +1103,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1103 | struct perf_top top = { | 1103 | struct perf_top top = { |
1104 | .count_filter = 5, | 1104 | .count_filter = 5, |
1105 | .delay_secs = 2, | 1105 | .delay_secs = 2, |
1106 | .target_pid = -1, | ||
1107 | .target_tid = -1, | ||
1108 | .uid = UINT_MAX, | 1106 | .uid = UINT_MAX, |
1109 | .freq = 1000, /* 1 KHz */ | 1107 | .freq = 1000, /* 1 KHz */ |
1110 | .sample_id_all_avail = true, | 1108 | .sample_id_all_avail = true, |
@@ -1118,9 +1116,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1118 | parse_events_option), | 1116 | parse_events_option), |
1119 | OPT_INTEGER('c', "count", &top.default_interval, | 1117 | OPT_INTEGER('c', "count", &top.default_interval, |
1120 | "event period to sample"), | 1118 | "event period to sample"), |
1121 | OPT_INTEGER('p', "pid", &top.target_pid, | 1119 | OPT_STRING('p', "pid", &top.target_pid, "pid", |
1122 | "profile events on existing process id"), | 1120 | "profile events on existing process id"), |
1123 | OPT_INTEGER('t', "tid", &top.target_tid, | 1121 | OPT_STRING('t', "tid", &top.target_tid, "tid", |
1124 | "profile events on existing thread id"), | 1122 | "profile events on existing thread id"), |
1125 | OPT_BOOLEAN('a', "all-cpus", &top.system_wide, | 1123 | OPT_BOOLEAN('a', "all-cpus", &top.system_wide, |
1126 | "system-wide collection from all CPUs"), | 1124 | "system-wide collection from all CPUs"), |
@@ -1210,13 +1208,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1210 | goto out_delete_evlist; | 1208 | goto out_delete_evlist; |
1211 | 1209 | ||
1212 | /* CPU and PID are mutually exclusive */ | 1210 | /* CPU and PID are mutually exclusive */ |
1213 | if (top.target_tid > 0 && top.cpu_list) { | 1211 | if (top.target_tid && top.cpu_list) { |
1214 | printf("WARNING: PID switch overriding CPU\n"); | 1212 | printf("WARNING: PID switch overriding CPU\n"); |
1215 | sleep(1); | 1213 | sleep(1); |
1216 | top.cpu_list = NULL; | 1214 | top.cpu_list = NULL; |
1217 | } | 1215 | } |
1218 | 1216 | ||
1219 | if (top.target_pid != -1) | 1217 | if (top.target_pid) |
1220 | top.target_tid = top.target_pid; | 1218 | top.target_tid = top.target_pid; |
1221 | 1219 | ||
1222 | if (perf_evlist__create_maps(top.evlist, top.target_pid, | 1220 | if (perf_evlist__create_maps(top.evlist, top.target_pid, |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 92af1688bae4..deb17dba4a5b 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -186,8 +186,8 @@ extern const char perf_version_string[]; | |||
186 | void pthread__unblock_sigwinch(void); | 186 | void pthread__unblock_sigwinch(void); |
187 | 187 | ||
188 | struct perf_record_opts { | 188 | struct perf_record_opts { |
189 | pid_t target_pid; | 189 | const char *target_pid; |
190 | pid_t target_tid; | 190 | const char *target_tid; |
191 | uid_t uid; | 191 | uid_t uid; |
192 | bool call_graph; | 192 | bool call_graph; |
193 | bool group; | 193 | bool group; |
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 | ||
596 | int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, | 596 | int 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 | ||
109 | int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, | 109 | int 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); |
111 | void perf_evlist__delete_maps(struct perf_evlist *evlist); | 111 | void perf_evlist__delete_maps(struct perf_evlist *evlist); |
112 | int perf_evlist__set_filters(struct perf_evlist *evlist); | 112 | int 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..f910f50136d0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -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/python-ext-sources b/tools/perf/util/python-ext-sources index ff606f482a7c..2884e67ee625 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources | |||
@@ -15,3 +15,5 @@ util/util.c | |||
15 | util/xyarray.c | 15 | util/xyarray.c |
16 | util/cgroup.c | 16 | util/cgroup.c |
17 | util/debugfs.c | 17 | util/debugfs.c |
18 | util/strlist.c | ||
19 | ../../lib/rbtree.c | ||
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 | ||
157 | static 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 | |||
209 | out: | ||
210 | strlist__delete(slist); | ||
211 | return threads; | ||
212 | |||
213 | out_free_threads: | ||
214 | free(threads); | ||
215 | threads = NULL; | ||
216 | goto out; | ||
217 | } | ||
218 | |||
219 | static 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 | } | ||
262 | out: | ||
263 | return threads; | ||
264 | |||
265 | out_free_threads: | ||
266 | free(threads); | ||
267 | threads = NULL; | ||
268 | goto out; | ||
269 | } | ||
270 | |||
271 | struct 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 | |||
155 | void thread_map__delete(struct thread_map *threads) | 283 | void 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); | |||
13 | struct thread_map *thread_map__new_by_tid(pid_t tid); | 13 | struct thread_map *thread_map__new_by_tid(pid_t tid); |
14 | struct thread_map *thread_map__new_by_uid(uid_t uid); | 14 | struct thread_map *thread_map__new_by_uid(uid_t uid); |
15 | struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); | 15 | struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); |
16 | |||
17 | struct thread_map *thread_map__new_str(const char *pid, | ||
18 | const char *tid, uid_t uid); | ||
19 | |||
16 | void thread_map__delete(struct thread_map *threads); | 20 | void thread_map__delete(struct thread_map *threads); |
17 | 21 | ||
18 | size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); | 22 | size_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..49eb8481f19f 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; |
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 | ||
86 | uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid) | 86 | uid_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.h b/tools/perf/util/util.h index 232d17ef3e60..7917b09430bd 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -245,7 +245,7 @@ struct perf_event_attr; | |||
245 | 245 | ||
246 | void event_attr_init(struct perf_event_attr *attr); | 246 | void event_attr_init(struct perf_event_attr *attr); |
247 | 247 | ||
248 | uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid); | 248 | uid_t parse_target_uid(const char *str, const char *tid, const char *pid); |
249 | 249 | ||
250 | #define _STR(x) #x | 250 | #define _STR(x) #x |
251 | #define STR(x) _STR(x) | 251 | #define STR(x) _STR(x) |