aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-05-11 02:13:55 -0400
committerIngo Molnar <mingo@kernel.org>2012-05-11 02:13:55 -0400
commit5dcefda0fd87fefa440abc9b9d3f1089229f8911 (patch)
treef19697dc461b40e277109fbba659d614892bb0d2 /tools/perf
parentc4f400e837713f677de94390c57e7dc7567e0286 (diff)
parent5a5626b1b4bf8467891c9297ffda979db97ed5ec (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Fixes and improvements for perf/core: - perf_target: abstraction for --uid, --pid, --tid, --cpu, --all-cpus handling, eliminating code duplicated in the tools, having constraints that apply to all of them, from Namhyung Kim - Fixes for handling fallback to cpu-clock on PPC, from David Ahern - Fix for processing events with unknown size, from Jiri Olsa - Compilation fix on 32-bit, from Jiri Olsa Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile8
-rw-r--r--tools/perf/builtin-record.c60
-rw-r--r--tools/perf/builtin-report.c12
-rw-r--r--tools/perf/builtin-stat.c65
-rw-r--r--tools/perf/builtin-test.c12
-rw-r--r--tools/perf/builtin-top.c51
-rw-r--r--tools/perf/perf.h8
-rw-r--r--tools/perf/ui/browsers/annotate.c6
-rw-r--r--tools/perf/ui/browsers/hists.c4
-rw-r--r--tools/perf/ui/gtk/browser.c31
-rw-r--r--tools/perf/ui/gtk/setup.c12
-rw-r--r--tools/perf/ui/setup.c168
-rw-r--r--tools/perf/ui/tui/setup.c140
-rw-r--r--tools/perf/util/cache.h24
-rw-r--r--tools/perf/util/debug.c1
-rw-r--r--tools/perf/util/evlist.c16
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c9
-rw-r--r--tools/perf/util/header.c17
-rw-r--r--tools/perf/util/parse-events.h2
-rw-r--r--tools/perf/util/session.c30
-rw-r--r--tools/perf/util/target.c142
-rw-r--r--tools/perf/util/target.h64
-rw-r--r--tools/perf/util/top.c19
-rw-r--r--tools/perf/util/top.h6
-rw-r--r--tools/perf/util/usage.c38
-rw-r--r--tools/perf/util/util.h3
27 files changed, 583 insertions, 369 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index e98e14c88532..4734f41f801d 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -300,6 +300,7 @@ LIB_H += util/cpumap.h
300LIB_H += util/top.h 300LIB_H += util/top.h
301LIB_H += $(ARCH_INCLUDE) 301LIB_H += $(ARCH_INCLUDE)
302LIB_H += util/cgroup.h 302LIB_H += util/cgroup.h
303LIB_H += util/target.h
303 304
304LIB_OBJS += $(OUTPUT)util/abspath.o 305LIB_OBJS += $(OUTPUT)util/abspath.o
305LIB_OBJS += $(OUTPUT)util/alias.o 306LIB_OBJS += $(OUTPUT)util/alias.o
@@ -361,6 +362,7 @@ LIB_OBJS += $(OUTPUT)util/util.o
361LIB_OBJS += $(OUTPUT)util/xyarray.o 362LIB_OBJS += $(OUTPUT)util/xyarray.o
362LIB_OBJS += $(OUTPUT)util/cpumap.o 363LIB_OBJS += $(OUTPUT)util/cpumap.o
363LIB_OBJS += $(OUTPUT)util/cgroup.o 364LIB_OBJS += $(OUTPUT)util/cgroup.o
365LIB_OBJS += $(OUTPUT)util/target.o
364 366
365BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 367BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
366 368
@@ -481,6 +483,7 @@ else
481 LIB_OBJS += $(OUTPUT)ui/helpline.o 483 LIB_OBJS += $(OUTPUT)ui/helpline.o
482 LIB_OBJS += $(OUTPUT)ui/progress.o 484 LIB_OBJS += $(OUTPUT)ui/progress.o
483 LIB_OBJS += $(OUTPUT)ui/util.o 485 LIB_OBJS += $(OUTPUT)ui/util.o
486 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
484 LIB_H += ui/browser.h 487 LIB_H += ui/browser.h
485 LIB_H += ui/browsers/map.h 488 LIB_H += ui/browsers/map.h
486 LIB_H += ui/helpline.h 489 LIB_H += ui/helpline.h
@@ -503,6 +506,11 @@ else
503 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0) 506 BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
504 EXTLIBS += $(shell pkg-config --libs gtk+-2.0) 507 EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
505 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o 508 LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
509 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
510 # Make sure that it'd be included only once.
511 ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
512 LIB_OBJS += $(OUTPUT)ui/setup.o
513 endif
506 endif 514 endif
507endif 515endif
508 516
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 10b1f1f25ed7..d19058a7b84c 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -44,7 +44,6 @@ struct perf_record {
44 struct perf_evlist *evlist; 44 struct perf_evlist *evlist;
45 struct perf_session *session; 45 struct perf_session *session;
46 const char *progname; 46 const char *progname;
47 const char *uid_str;
48 int output; 47 int output;
49 unsigned int page_size; 48 unsigned int page_size;
50 int realtime_prio; 49 int realtime_prio;
@@ -218,7 +217,7 @@ try_again:
218 if (err == EPERM || err == EACCES) { 217 if (err == EPERM || err == EACCES) {
219 ui__error_paranoid(); 218 ui__error_paranoid();
220 exit(EXIT_FAILURE); 219 exit(EXIT_FAILURE);
221 } else if (err == ENODEV && opts->cpu_list) { 220 } else if (err == ENODEV && opts->target.cpu_list) {
222 die("No such device - did you specify" 221 die("No such device - did you specify"
223 " an out-of-range profile CPU?\n"); 222 " an out-of-range profile CPU?\n");
224 } else if (err == EINVAL) { 223 } else if (err == EINVAL) {
@@ -243,9 +242,13 @@ try_again:
243 /* 242 /*
244 * If it's cycles then fall back to hrtimer 243 * If it's cycles then fall back to hrtimer
245 * based cpu-clock-tick sw counter, which 244 * based cpu-clock-tick sw counter, which
246 * is always available even if no PMU support: 245 * is always available even if no PMU support.
246 *
247 * PPC returns ENXIO until 2.6.37 (behavior changed
248 * with commit b0a873e).
247 */ 249 */
248 if (err == ENOENT && attr->type == PERF_TYPE_HARDWARE 250 if ((err == ENOENT || err == ENXIO)
251 && attr->type == PERF_TYPE_HARDWARE
249 && attr->config == PERF_COUNT_HW_CPU_CYCLES) { 252 && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
250 253
251 if (verbose) 254 if (verbose)
@@ -253,6 +256,10 @@ try_again:
253 "trying to fall back to cpu-clock-ticks\n"); 256 "trying to fall back to cpu-clock-ticks\n");
254 attr->type = PERF_TYPE_SOFTWARE; 257 attr->type = PERF_TYPE_SOFTWARE;
255 attr->config = PERF_COUNT_SW_CPU_CLOCK; 258 attr->config = PERF_COUNT_SW_CPU_CLOCK;
259 if (pos->name) {
260 free(pos->name);
261 pos->name = NULL;
262 }
256 goto try_again; 263 goto try_again;
257 } 264 }
258 265
@@ -578,7 +585,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
578 perf_session__process_machines(session, tool, 585 perf_session__process_machines(session, tool,
579 perf_event__synthesize_guest_os); 586 perf_event__synthesize_guest_os);
580 587
581 if (!opts->system_wide) 588 if (!opts->target.system_wide)
582 perf_event__synthesize_thread_map(tool, evsel_list->threads, 589 perf_event__synthesize_thread_map(tool, evsel_list->threads,
583 process_synthesized_event, 590 process_synthesized_event,
584 machine); 591 machine);
@@ -765,9 +772,9 @@ const struct option record_options[] = {
765 parse_events_option), 772 parse_events_option),
766 OPT_CALLBACK(0, "filter", &record.evlist, "filter", 773 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
767 "event filter", parse_filter), 774 "event filter", parse_filter),
768 OPT_STRING('p', "pid", &record.opts.target_pid, "pid", 775 OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
769 "record events on existing process id"), 776 "record events on existing process id"),
770 OPT_STRING('t', "tid", &record.opts.target_tid, "tid", 777 OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
771 "record events on existing thread id"), 778 "record events on existing thread id"),
772 OPT_INTEGER('r', "realtime", &record.realtime_prio, 779 OPT_INTEGER('r', "realtime", &record.realtime_prio,
773 "collect data with this RT SCHED_FIFO priority"), 780 "collect data with this RT SCHED_FIFO priority"),
@@ -775,11 +782,11 @@ const struct option record_options[] = {
775 "collect data without buffering"), 782 "collect data without buffering"),
776 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples, 783 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
777 "collect raw sample records from all opened counters"), 784 "collect raw sample records from all opened counters"),
778 OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide, 785 OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
779 "system-wide collection from all CPUs"), 786 "system-wide collection from all CPUs"),
780 OPT_BOOLEAN('A', "append", &record.append_file, 787 OPT_BOOLEAN('A', "append", &record.append_file,
781 "append to the output file to do incremental profiling"), 788 "append to the output file to do incremental profiling"),
782 OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu", 789 OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
783 "list of cpus to monitor"), 790 "list of cpus to monitor"),
784 OPT_BOOLEAN('f', "force", &record.force, 791 OPT_BOOLEAN('f', "force", &record.force,
785 "overwrite existing data file (deprecated)"), 792 "overwrite existing data file (deprecated)"),
@@ -813,7 +820,8 @@ const struct option record_options[] = {
813 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 820 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
814 "monitor event in cgroup name only", 821 "monitor event in cgroup name only",
815 parse_cgroups), 822 parse_cgroups),
816 OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"), 823 OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
824 "user to profile"),
817 825
818 OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack, 826 OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
819 "branch any", "sample any taken branches", 827 "branch any", "sample any taken branches",
@@ -831,6 +839,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
831 struct perf_evsel *pos; 839 struct perf_evsel *pos;
832 struct perf_evlist *evsel_list; 840 struct perf_evlist *evsel_list;
833 struct perf_record *rec = &record; 841 struct perf_record *rec = &record;
842 char errbuf[BUFSIZ];
834 843
835 perf_header__set_cmdline(argc, argv); 844 perf_header__set_cmdline(argc, argv);
836 845
@@ -842,8 +851,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
842 851
843 argc = parse_options(argc, argv, record_options, record_usage, 852 argc = parse_options(argc, argv, record_options, record_usage,
844 PARSE_OPT_STOP_AT_NON_OPTION); 853 PARSE_OPT_STOP_AT_NON_OPTION);
845 if (!argc && !rec->opts.target_pid && !rec->opts.target_tid && 854 if (!argc && perf_target__none(&rec->opts.target))
846 !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
847 usage_with_options(record_usage, record_options); 855 usage_with_options(record_usage, record_options);
848 856
849 if (rec->force && rec->append_file) { 857 if (rec->force && rec->append_file) {
@@ -856,7 +864,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
856 rec->write_mode = WRITE_FORCE; 864 rec->write_mode = WRITE_FORCE;
857 } 865 }
858 866
859 if (nr_cgroups && !rec->opts.system_wide) { 867 if (nr_cgroups && !rec->opts.target.system_wide) {
860 fprintf(stderr, "cgroup monitoring only available in" 868 fprintf(stderr, "cgroup monitoring only available in"
861 " system-wide mode\n"); 869 " system-wide mode\n");
862 usage_with_options(record_usage, record_options); 870 usage_with_options(record_usage, record_options);
@@ -883,17 +891,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
883 goto out_symbol_exit; 891 goto out_symbol_exit;
884 } 892 }
885 893
886 rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid, 894 err = perf_target__validate(&rec->opts.target);
887 rec->opts.target_pid); 895 if (err) {
888 if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1) 896 perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
889 goto out_free_fd; 897 ui__warning("%s", errbuf);
898 }
899
900 err = perf_target__parse_uid(&rec->opts.target);
901 if (err) {
902 int saved_errno = errno;
890 903
891 if (rec->opts.target_pid) 904 perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
892 rec->opts.target_tid = rec->opts.target_pid; 905 ui__warning("%s", errbuf);
906
907 err = -saved_errno;
908 goto out_free_fd;
909 }
893 910
894 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 911 err = -ENOMEM;
895 rec->opts.target_tid, rec->opts.uid, 912 if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
896 rec->opts.cpu_list) < 0)
897 usage_with_options(record_usage, record_options); 913 usage_with_options(record_usage, record_options);
898 914
899 list_for_each_entry(pos, &evsel_list->entries, node) { 915 list_for_each_entry(pos, &evsel_list->entries, node) {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index cec2b8cee80c..74776558ddfb 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -304,7 +304,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
304 if (evname != NULL) 304 if (evname != NULL)
305 ret += fprintf(fp, " of event '%s'", evname); 305 ret += fprintf(fp, " of event '%s'", evname);
306 306
307 ret += fprintf(fp, "\n# Event count (approx.): %lu", nr_events); 307 ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
308 return ret + fprintf(fp, "\n#\n"); 308 return ret + fprintf(fp, "\n#\n");
309} 309}
310 310
@@ -676,14 +676,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
676 676
677 } 677 }
678 678
679 if (strcmp(report.input_name, "-") != 0) { 679 if (strcmp(report.input_name, "-") != 0)
680 if (report.use_gtk) 680 setup_browser(true);
681 perf_gtk_setup_browser(argc, argv, true); 681 else
682 else
683 setup_browser(true);
684 } else {
685 use_browser = 0; 682 use_browser = 0;
686 }
687 683
688 /* 684 /*
689 * Only in the newt browser we are doing integrated annotation, 685 * Only in the newt browser we are doing integrated annotation,
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index dde9e17c018b..d0605689bad9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -175,22 +175,21 @@ static struct perf_event_attr very_very_detailed_attrs[] = {
175 175
176static struct perf_evlist *evsel_list; 176static struct perf_evlist *evsel_list;
177 177
178static bool system_wide = false; 178static struct perf_target target = {
179static int run_idx = 0; 179 .uid = UINT_MAX,
180};
180 181
182static int run_idx = 0;
181static int run_count = 1; 183static int run_count = 1;
182static bool no_inherit = false; 184static bool no_inherit = false;
183static bool scale = true; 185static bool scale = true;
184static bool no_aggr = false; 186static bool no_aggr = false;
185static const char *target_pid;
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;
190static bool sync_run = false; 190static bool sync_run = false;
191static bool big_num = true; 191static bool big_num = true;
192static int big_num_opt = -1; 192static int big_num_opt = -1;
193static const char *cpu_list;
194static const char *csv_sep = NULL; 193static const char *csv_sep = NULL;
195static bool csv_output = false; 194static bool csv_output = false;
196static bool group = false; 195static bool group = false;
@@ -293,10 +292,10 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,
293 292
294 attr->inherit = !no_inherit; 293 attr->inherit = !no_inherit;
295 294
296 if (system_wide) 295 if (!perf_target__no_cpu(&target))
297 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, 296 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
298 group, group_fd); 297 group, group_fd);
299 if (!target_pid && !target_tid && (!group || evsel == first)) { 298 if (perf_target__no_task(&target) && (!group || evsel == first)) {
300 attr->disabled = 1; 299 attr->disabled = 1;
301 attr->enable_on_exec = 1; 300 attr->enable_on_exec = 1;
302 } 301 }
@@ -446,7 +445,7 @@ static int run_perf_stat(int argc __used, const char **argv)
446 exit(-1); 445 exit(-1);
447 } 446 }
448 447
449 if (!target_tid && !target_pid && !system_wide) 448 if (perf_target__none(&target))
450 evsel_list->threads->map[0] = child_pid; 449 evsel_list->threads->map[0] = child_pid;
451 450
452 /* 451 /*
@@ -463,8 +462,13 @@ static int run_perf_stat(int argc __used, const char **argv)
463 462
464 list_for_each_entry(counter, &evsel_list->entries, node) { 463 list_for_each_entry(counter, &evsel_list->entries, node) {
465 if (create_perf_stat_counter(counter, first) < 0) { 464 if (create_perf_stat_counter(counter, first) < 0) {
465 /*
466 * PPC returns ENXIO for HW counters until 2.6.37
467 * (behavior changed with commit b0a873e).
468 */
466 if (errno == EINVAL || errno == ENOSYS || 469 if (errno == EINVAL || errno == ENOSYS ||
467 errno == ENOENT || errno == EOPNOTSUPP) { 470 errno == ENOENT || errno == EOPNOTSUPP ||
471 errno == ENXIO) {
468 if (verbose) 472 if (verbose)
469 ui__warning("%s event is not supported by the kernel.\n", 473 ui__warning("%s event is not supported by the kernel.\n",
470 event_name(counter)); 474 event_name(counter));
@@ -476,7 +480,7 @@ static int run_perf_stat(int argc __used, const char **argv)
476 error("You may not have permission to collect %sstats.\n" 480 error("You may not have permission to collect %sstats.\n"
477 "\t Consider tweaking" 481 "\t Consider tweaking"
478 " /proc/sys/kernel/perf_event_paranoid or running as root.", 482 " /proc/sys/kernel/perf_event_paranoid or running as root.",
479 system_wide ? "system-wide " : ""); 483 target.system_wide ? "system-wide " : "");
480 } else { 484 } else {
481 error("open_counter returned with %d (%s). " 485 error("open_counter returned with %d (%s). "
482 "/bin/dmesg may provide additional information.\n", 486 "/bin/dmesg may provide additional information.\n",
@@ -968,14 +972,14 @@ static void print_stat(int argc, const char **argv)
968 if (!csv_output) { 972 if (!csv_output) {
969 fprintf(output, "\n"); 973 fprintf(output, "\n");
970 fprintf(output, " Performance counter stats for "); 974 fprintf(output, " Performance counter stats for ");
971 if (!target_pid && !target_tid) { 975 if (perf_target__no_task(&target)) {
972 fprintf(output, "\'%s", argv[0]); 976 fprintf(output, "\'%s", argv[0]);
973 for (i = 1; i < argc; i++) 977 for (i = 1; i < argc; i++)
974 fprintf(output, " %s", argv[i]); 978 fprintf(output, " %s", argv[i]);
975 } else if (target_pid) 979 } else if (target.pid)
976 fprintf(output, "process id \'%s", target_pid); 980 fprintf(output, "process id \'%s", target.pid);
977 else 981 else
978 fprintf(output, "thread id \'%s", target_tid); 982 fprintf(output, "thread id \'%s", target.tid);
979 983
980 fprintf(output, "\'"); 984 fprintf(output, "\'");
981 if (run_count > 1) 985 if (run_count > 1)
@@ -1049,11 +1053,11 @@ static const struct option options[] = {
1049 "event filter", parse_filter), 1053 "event filter", parse_filter),
1050 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 1054 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
1051 "child tasks do not inherit counters"), 1055 "child tasks do not inherit counters"),
1052 OPT_STRING('p', "pid", &target_pid, "pid", 1056 OPT_STRING('p', "pid", &target.pid, "pid",
1053 "stat events on existing process id"), 1057 "stat events on existing process id"),
1054 OPT_STRING('t', "tid", &target_tid, "tid", 1058 OPT_STRING('t', "tid", &target.tid, "tid",
1055 "stat events on existing thread id"), 1059 "stat events on existing thread id"),
1056 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1060 OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
1057 "system-wide collection from all CPUs"), 1061 "system-wide collection from all CPUs"),
1058 OPT_BOOLEAN('g', "group", &group, 1062 OPT_BOOLEAN('g', "group", &group,
1059 "put the counters into a counter group"), 1063 "put the counters into a counter group"),
@@ -1072,7 +1076,7 @@ static const struct option options[] = {
1072 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1076 OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
1073 "print large numbers with thousands\' separators", 1077 "print large numbers with thousands\' separators",
1074 stat__set_big_num), 1078 stat__set_big_num),
1075 OPT_STRING('C', "cpu", &cpu_list, "cpu", 1079 OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
1076 "list of cpus to monitor in system-wide"), 1080 "list of cpus to monitor in system-wide"),
1077 OPT_BOOLEAN('A', "no-aggr", &no_aggr, 1081 OPT_BOOLEAN('A', "no-aggr", &no_aggr,
1078 "disable CPU count aggregation"), 1082 "disable CPU count aggregation"),
@@ -1190,13 +1194,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1190 } else if (big_num_opt == 0) /* User passed --no-big-num */ 1194 } else if (big_num_opt == 0) /* User passed --no-big-num */
1191 big_num = false; 1195 big_num = false;
1192 1196
1193 if (!argc && !target_pid && !target_tid) 1197 if (!argc && perf_target__no_task(&target))
1194 usage_with_options(stat_usage, options); 1198 usage_with_options(stat_usage, options);
1195 if (run_count <= 0) 1199 if (run_count <= 0)
1196 usage_with_options(stat_usage, options); 1200 usage_with_options(stat_usage, options);
1197 1201
1198 /* no_aggr, cgroup are for system-wide only */ 1202 /* no_aggr, cgroup are for system-wide only */
1199 if ((no_aggr || nr_cgroups) && !system_wide) { 1203 if ((no_aggr || nr_cgroups) && perf_target__no_cpu(&target)) {
1200 fprintf(stderr, "both cgroup and no-aggregation " 1204 fprintf(stderr, "both cgroup and no-aggregation "
1201 "modes only available in system-wide mode\n"); 1205 "modes only available in system-wide mode\n");
1202 1206
@@ -1206,23 +1210,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1206 if (add_default_attributes()) 1210 if (add_default_attributes())
1207 goto out; 1211 goto out;
1208 1212
1209 if (target_pid) 1213 perf_target__validate(&target);
1210 target_tid = target_pid;
1211 1214
1212 evsel_list->threads = thread_map__new_str(target_pid, 1215 if (perf_evlist__create_maps(evsel_list, &target) < 0) {
1213 target_tid, UINT_MAX); 1216 if (!perf_target__no_task(&target))
1214 if (evsel_list->threads == NULL) { 1217 pr_err("Problems finding threads of monitor\n");
1215 pr_err("Problems finding threads of monitor\n"); 1218 if (!perf_target__no_cpu(&target))
1216 usage_with_options(stat_usage, options); 1219 perror("failed to parse CPUs map");
1217 }
1218
1219 if (system_wide)
1220 evsel_list->cpus = cpu_map__new(cpu_list);
1221 else
1222 evsel_list->cpus = cpu_map__dummy_new();
1223 1220
1224 if (evsel_list->cpus == NULL) {
1225 perror("failed to parse CPUs map");
1226 usage_with_options(stat_usage, options); 1221 usage_with_options(stat_usage, options);
1227 return -1; 1222 return -1;
1228 } 1223 }
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 1c5b9801ac61..9d9abbbe23be 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -1165,6 +1165,9 @@ realloc:
1165static int test__PERF_RECORD(void) 1165static int test__PERF_RECORD(void)
1166{ 1166{
1167 struct perf_record_opts opts = { 1167 struct perf_record_opts opts = {
1168 .target = {
1169 .uid = UINT_MAX,
1170 },
1168 .no_delay = true, 1171 .no_delay = true,
1169 .freq = 10, 1172 .freq = 10,
1170 .mmap_pages = 256, 1173 .mmap_pages = 256,
@@ -1207,8 +1210,7 @@ static int test__PERF_RECORD(void)
1207 * perf_evlist__prepare_workload we'll fill in the only thread 1210 * perf_evlist__prepare_workload we'll fill in the only thread
1208 * we're monitoring, the one forked there. 1211 * we're monitoring, the one forked there.
1209 */ 1212 */
1210 err = perf_evlist__create_maps(evlist, opts.target_pid, 1213 err = perf_evlist__create_maps(evlist, &opts.target);
1211 opts.target_tid, UINT_MAX, opts.cpu_list);
1212 if (err < 0) { 1214 if (err < 0) {
1213 pr_debug("Not enough memory to create thread/cpu maps\n"); 1215 pr_debug("Not enough memory to create thread/cpu maps\n");
1214 goto out_delete_evlist; 1216 goto out_delete_evlist;
@@ -1549,8 +1551,6 @@ static int __test__rdpmc(void)
1549 sa.sa_sigaction = segfault_handler; 1551 sa.sa_sigaction = segfault_handler;
1550 sigaction(SIGSEGV, &sa, NULL); 1552 sigaction(SIGSEGV, &sa, NULL);
1551 1553
1552 fprintf(stderr, "\n\n");
1553
1554 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 1554 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1555 if (fd < 0) { 1555 if (fd < 0) {
1556 die("Error: sys_perf_event_open() syscall returned " 1556 die("Error: sys_perf_event_open() syscall returned "
@@ -1575,7 +1575,7 @@ static int __test__rdpmc(void)
1575 loops *= 10; 1575 loops *= 10;
1576 1576
1577 delta = now - stamp; 1577 delta = now - stamp;
1578 fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta); 1578 pr_debug("%14d: %14Lu\n", n, (long long)delta);
1579 1579
1580 delta_sum += delta; 1580 delta_sum += delta;
1581 } 1581 }
@@ -1583,7 +1583,7 @@ static int __test__rdpmc(void)
1583 munmap(addr, page_size); 1583 munmap(addr, page_size);
1584 close(fd); 1584 close(fd);
1585 1585
1586 fprintf(stderr, " "); 1586 pr_debug(" ");
1587 1587
1588 if (!delta_sum) 1588 if (!delta_sum)
1589 return -1; 1589 return -1;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8ef59f8262bb..4eb6171e143b 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -588,7 +588,7 @@ static void *display_thread_tui(void *arg)
588 * via --uid. 588 * via --uid.
589 */ 589 */
590 list_for_each_entry(pos, &top->evlist->entries, node) 590 list_for_each_entry(pos, &top->evlist->entries, node)
591 pos->hists.uid_filter_str = top->uid_str; 591 pos->hists.uid_filter_str = top->target.uid_str;
592 592
593 perf_evlist__tui_browse_hists(top->evlist, help, 593 perf_evlist__tui_browse_hists(top->evlist, help,
594 perf_top__sort_new_samples, 594 perf_top__sort_new_samples,
@@ -948,6 +948,10 @@ try_again:
948 948
949 attr->type = PERF_TYPE_SOFTWARE; 949 attr->type = PERF_TYPE_SOFTWARE;
950 attr->config = PERF_COUNT_SW_CPU_CLOCK; 950 attr->config = PERF_COUNT_SW_CPU_CLOCK;
951 if (counter->name) {
952 free(counter->name);
953 counter->name = strdup(event_name(counter));
954 }
951 goto try_again; 955 goto try_again;
952 } 956 }
953 957
@@ -1016,7 +1020,7 @@ static int __cmd_top(struct perf_top *top)
1016 if (ret) 1020 if (ret)
1017 goto out_delete; 1021 goto out_delete;
1018 1022
1019 if (top->target_tid || top->uid != UINT_MAX) 1023 if (!perf_target__no_task(&top->target))
1020 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 1024 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
1021 perf_event__process, 1025 perf_event__process,
1022 &top->session->host_machine); 1026 &top->session->host_machine);
@@ -1150,11 +1154,11 @@ static const char * const top_usage[] = {
1150int cmd_top(int argc, const char **argv, const char *prefix __used) 1154int cmd_top(int argc, const char **argv, const char *prefix __used)
1151{ 1155{
1152 struct perf_evsel *pos; 1156 struct perf_evsel *pos;
1153 int status = -ENOMEM; 1157 int status;
1158 char errbuf[BUFSIZ];
1154 struct perf_top top = { 1159 struct perf_top top = {
1155 .count_filter = 5, 1160 .count_filter = 5,
1156 .delay_secs = 2, 1161 .delay_secs = 2,
1157 .uid = UINT_MAX,
1158 .freq = 1000, /* 1 KHz */ 1162 .freq = 1000, /* 1 KHz */
1159 .mmap_pages = 128, 1163 .mmap_pages = 128,
1160 .sym_pcnt_filter = 5, 1164 .sym_pcnt_filter = 5,
@@ -1166,13 +1170,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1166 parse_events_option), 1170 parse_events_option),
1167 OPT_INTEGER('c', "count", &top.default_interval, 1171 OPT_INTEGER('c', "count", &top.default_interval,
1168 "event period to sample"), 1172 "event period to sample"),
1169 OPT_STRING('p', "pid", &top.target_pid, "pid", 1173 OPT_STRING('p', "pid", &top.target.pid, "pid",
1170 "profile events on existing process id"), 1174 "profile events on existing process id"),
1171 OPT_STRING('t', "tid", &top.target_tid, "tid", 1175 OPT_STRING('t', "tid", &top.target.tid, "tid",
1172 "profile events on existing thread id"), 1176 "profile events on existing thread id"),
1173 OPT_BOOLEAN('a', "all-cpus", &top.system_wide, 1177 OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide,
1174 "system-wide collection from all CPUs"), 1178 "system-wide collection from all CPUs"),
1175 OPT_STRING('C', "cpu", &top.cpu_list, "cpu", 1179 OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu",
1176 "list of cpus to monitor"), 1180 "list of cpus to monitor"),
1177 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1181 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1178 "file", "vmlinux pathname"), 1182 "file", "vmlinux pathname"),
@@ -1227,7 +1231,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1227 "Display raw encoding of assembly instructions (default)"), 1231 "Display raw encoding of assembly instructions (default)"),
1228 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1232 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1229 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1233 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1230 OPT_STRING('u', "uid", &top.uid_str, "user", "user to profile"), 1234 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"),
1231 OPT_END() 1235 OPT_END()
1232 }; 1236 };
1233 1237
@@ -1253,22 +1257,27 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1253 1257
1254 setup_browser(false); 1258 setup_browser(false);
1255 1259
1256 top.uid = parse_target_uid(top.uid_str, top.target_tid, top.target_pid); 1260 status = perf_target__validate(&top.target);
1257 if (top.uid_str != NULL && top.uid == UINT_MAX - 1) 1261 if (status) {
1258 goto out_delete_evlist; 1262 perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
1263 ui__warning("%s", errbuf);
1264 }
1259 1265
1260 /* CPU and PID are mutually exclusive */ 1266 status = perf_target__parse_uid(&top.target);
1261 if (top.target_tid && top.cpu_list) { 1267 if (status) {
1262 printf("WARNING: PID switch overriding CPU\n"); 1268 int saved_errno = errno;
1263 sleep(1); 1269
1264 top.cpu_list = NULL; 1270 perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
1271 ui__warning("%s", errbuf);
1272
1273 status = -saved_errno;
1274 goto out_delete_evlist;
1265 } 1275 }
1266 1276
1267 if (top.target_pid) 1277 if (perf_target__none(&top.target))
1268 top.target_tid = top.target_pid; 1278 top.target.system_wide = true;
1269 1279
1270 if (perf_evlist__create_maps(top.evlist, top.target_pid, 1280 if (perf_evlist__create_maps(top.evlist, &top.target) < 0)
1271 top.target_tid, top.uid, top.cpu_list) < 0)
1272 usage_with_options(top_usage, options); 1281 usage_with_options(top_usage, options);
1273 1282
1274 if (!top.evlist->nr_entries && 1283 if (!top.evlist->nr_entries &&
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 89e3355ab173..14f1034f14f9 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -207,10 +207,10 @@ extern const char perf_version_string[];
207 207
208void pthread__unblock_sigwinch(void); 208void pthread__unblock_sigwinch(void);
209 209
210#include "util/target.h"
211
210struct perf_record_opts { 212struct perf_record_opts {
211 const char *target_pid; 213 struct perf_target target;
212 const char *target_tid;
213 uid_t uid;
214 bool call_graph; 214 bool call_graph;
215 bool group; 215 bool group;
216 bool inherit_stat; 216 bool inherit_stat;
@@ -223,7 +223,6 @@ struct perf_record_opts {
223 bool sample_time; 223 bool sample_time;
224 bool sample_id_all_missing; 224 bool sample_id_all_missing;
225 bool exclude_guest_missing; 225 bool exclude_guest_missing;
226 bool system_wide;
227 bool period; 226 bool period;
228 unsigned int freq; 227 unsigned int freq;
229 unsigned int mmap_pages; 228 unsigned int mmap_pages;
@@ -231,7 +230,6 @@ struct perf_record_opts {
231 int branch_stack; 230 int branch_stack;
232 u64 default_interval; 231 u64 default_interval;
233 u64 user_interval; 232 u64 user_interval;
234 const char *cpu_list;
235}; 233};
236 234
237#endif 235#endif
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index f171b4627cb1..06367c1df720 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -547,9 +547,9 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
547 struct map_symbol *ms = self->b.priv; 547 struct map_symbol *ms = self->b.priv;
548 struct symbol *sym = ms->sym; 548 struct symbol *sym = ms->sym;
549 const char *help = "<-/ESC: Exit, TAB/shift+TAB: Cycle hot lines, " 549 const char *help = "<-/ESC: Exit, TAB/shift+TAB: Cycle hot lines, "
550 "H: Go to hottest line, ->/ENTER: Line action, " 550 "H: Hottest line, ->/ENTER: Line action, "
551 "O: Toggle offset view, " 551 "O: Offset view, "
552 "S: Toggle source code view"; 552 "S: Source view";
553 int key; 553 int key;
554 554
555 if (ui_browser__show(&self->b, sym->name, help) < 0) 555 if (ui_browser__show(&self->b, sym->name, help) < 0)
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 466827e91b87..a372a4b02635 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -941,7 +941,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
941 goto zoom_dso; 941 goto zoom_dso;
942 case 't': 942 case 't':
943 goto zoom_thread; 943 goto zoom_thread;
944 case 's': 944 case '/':
945 if (ui_browser__input_window("Symbol to show", 945 if (ui_browser__input_window("Symbol to show",
946 "Please enter the name of symbol you want to see", 946 "Please enter the name of symbol you want to see",
947 buf, "ENTER: OK, ESC: Cancel", 947 buf, "ENTER: OK, ESC: Cancel",
@@ -969,7 +969,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
969 "E Expand all callchains\n" 969 "E Expand all callchains\n"
970 "d Zoom into current DSO\n" 970 "d Zoom into current DSO\n"
971 "t Zoom into current Thread\n" 971 "t Zoom into current Thread\n"
972 "s Filter symbol by name"); 972 "/ Filter symbol by name");
973 continue; 973 continue;
974 case K_ENTER: 974 case K_ENTER:
975 case K_RIGHT: 975 case K_RIGHT:
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c
index 258352a2356c..0656c381a89c 100644
--- a/tools/perf/ui/gtk/browser.c
+++ b/tools/perf/ui/gtk/browser.c
@@ -9,24 +9,13 @@
9 9
10#define MAX_COLUMNS 32 10#define MAX_COLUMNS 32
11 11
12void perf_gtk_setup_browser(int argc, const char *argv[], 12static void perf_gtk__signal(int sig)
13 bool fallback_to_pager __used)
14{
15 gtk_init(&argc, (char ***)&argv);
16}
17
18void perf_gtk_exit_browser(bool wait_for_ok __used)
19{
20 gtk_main_quit();
21}
22
23static void perf_gtk_signal(int sig)
24{ 13{
25 psignal(sig, "perf"); 14 psignal(sig, "perf");
26 gtk_main_quit(); 15 gtk_main_quit();
27} 16}
28 17
29static void perf_gtk_resize_window(GtkWidget *window) 18static void perf_gtk__resize_window(GtkWidget *window)
30{ 19{
31 GdkRectangle rect; 20 GdkRectangle rect;
32 GdkScreen *screen; 21 GdkScreen *screen;
@@ -46,7 +35,7 @@ static void perf_gtk_resize_window(GtkWidget *window)
46 gtk_window_resize(GTK_WINDOW(window), width, height); 35 gtk_window_resize(GTK_WINDOW(window), width, height);
47} 36}
48 37
49static void perf_gtk_show_hists(GtkWidget *window, struct hists *hists) 38static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
50{ 39{
51 GType col_types[MAX_COLUMNS]; 40 GType col_types[MAX_COLUMNS];
52 GtkCellRenderer *renderer; 41 GtkCellRenderer *renderer;
@@ -142,11 +131,11 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
142 GtkWidget *notebook; 131 GtkWidget *notebook;
143 GtkWidget *window; 132 GtkWidget *window;
144 133
145 signal(SIGSEGV, perf_gtk_signal); 134 signal(SIGSEGV, perf_gtk__signal);
146 signal(SIGFPE, perf_gtk_signal); 135 signal(SIGFPE, perf_gtk__signal);
147 signal(SIGINT, perf_gtk_signal); 136 signal(SIGINT, perf_gtk__signal);
148 signal(SIGQUIT, perf_gtk_signal); 137 signal(SIGQUIT, perf_gtk__signal);
149 signal(SIGTERM, perf_gtk_signal); 138 signal(SIGTERM, perf_gtk__signal);
150 139
151 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 140 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
152 141
@@ -168,7 +157,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
168 GTK_POLICY_AUTOMATIC, 157 GTK_POLICY_AUTOMATIC,
169 GTK_POLICY_AUTOMATIC); 158 GTK_POLICY_AUTOMATIC);
170 159
171 perf_gtk_show_hists(scrolled_window, hists); 160 perf_gtk__show_hists(scrolled_window, hists);
172 161
173 tab_label = gtk_label_new(evname); 162 tab_label = gtk_label_new(evname);
174 163
@@ -179,7 +168,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
179 168
180 gtk_widget_show_all(window); 169 gtk_widget_show_all(window);
181 170
182 perf_gtk_resize_window(window); 171 perf_gtk__resize_window(window);
183 172
184 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 173 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
185 174
diff --git a/tools/perf/ui/gtk/setup.c b/tools/perf/ui/gtk/setup.c
new file mode 100644
index 000000000000..829529957766
--- /dev/null
+++ b/tools/perf/ui/gtk/setup.c
@@ -0,0 +1,12 @@
1#include "gtk.h"
2#include "../../util/cache.h"
3
4int perf_gtk__init(void)
5{
6 return gtk_init_check(NULL, NULL) ? 0 : -1;
7}
8
9void perf_gtk__exit(bool wait_for_ok __used)
10{
11 gtk_main_quit();
12}
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index 85a69faa09aa..9f5f888f73e3 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -1,155 +1,45 @@
1#include <newt.h>
2#include <signal.h>
3#include <stdbool.h>
4
5#include "../cache.h" 1#include "../cache.h"
6#include "../debug.h" 2#include "../debug.h"
7#include "browser.h"
8#include "helpline.h"
9#include "ui.h"
10#include "util.h"
11#include "libslang.h"
12#include "keysyms.h"
13
14pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
15
16static volatile int ui__need_resize;
17
18void ui__refresh_dimensions(bool force)
19{
20 if (force || ui__need_resize) {
21 ui__need_resize = 0;
22 pthread_mutex_lock(&ui__lock);
23 SLtt_get_screen_size();
24 SLsmg_reinit_smg();
25 pthread_mutex_unlock(&ui__lock);
26 }
27}
28
29static void ui__sigwinch(int sig __used)
30{
31 ui__need_resize = 1;
32}
33
34static void ui__setup_sigwinch(void)
35{
36 static bool done;
37 3
38 if (done)
39 return;
40
41 done = true;
42 pthread__unblock_sigwinch();
43 signal(SIGWINCH, ui__sigwinch);
44}
45
46int ui__getch(int delay_secs)
47{
48 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
49 fd_set read_set;
50 int err, key;
51
52 ui__setup_sigwinch();
53
54 FD_ZERO(&read_set);
55 FD_SET(0, &read_set);
56
57 if (delay_secs) {
58 timeout.tv_sec = delay_secs;
59 timeout.tv_usec = 0;
60 }
61
62 err = select(1, &read_set, NULL, NULL, ptimeout);
63
64 if (err == 0)
65 return K_TIMER;
66
67 if (err == -1) {
68 if (errno == EINTR)
69 return K_RESIZE;
70 return K_ERROR;
71 }
72
73 key = SLang_getkey();
74 if (key != K_ESC)
75 return key;
76
77 FD_ZERO(&read_set);
78 FD_SET(0, &read_set);
79 timeout.tv_sec = 0;
80 timeout.tv_usec = 20;
81 err = select(1, &read_set, NULL, NULL, &timeout);
82 if (err == 0)
83 return K_ESC;
84
85 SLang_ungetkey(key);
86 return SLkp_getkey();
87}
88
89static void newt_suspend(void *d __used)
90{
91 newtSuspend();
92 raise(SIGTSTP);
93 newtResume();
94}
95
96static int ui__init(void)
97{
98 int err = SLkp_init();
99
100 if (err < 0)
101 goto out;
102
103 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
104out:
105 return err;
106}
107
108static void ui__exit(void)
109{
110 SLtt_set_cursor_visibility(1);
111 SLsmg_refresh();
112 SLsmg_reset_smg();
113 SLang_reset_tty();
114}
115
116static void ui__signal(int sig)
117{
118 ui__exit();
119 psignal(sig, "perf");
120 exit(0);
121}
122 4
123void setup_browser(bool fallback_to_pager) 5void setup_browser(bool fallback_to_pager)
124{ 6{
125 if (!isatty(1) || !use_browser || dump_trace) { 7 if (!isatty(1) || dump_trace)
126 use_browser = 0; 8 use_browser = 0;
9
10 /* default to TUI */
11 if (use_browser < 0)
12 use_browser = 1;
13
14 switch (use_browser) {
15 case 2:
16 if (perf_gtk__init() == 0)
17 break;
18 /* fall through */
19 case 1:
20 use_browser = 1;
21 if (ui__init() == 0)
22 break;
23 /* fall through */
24 default:
127 if (fallback_to_pager) 25 if (fallback_to_pager)
128 setup_pager(); 26 setup_pager();
129 return; 27 break;
130 } 28 }
131
132 use_browser = 1;
133 newtInit();
134 ui__init();
135 newtSetSuspendCallback(newt_suspend, NULL);
136 ui_helpline__init();
137 ui_browser__init();
138
139 signal(SIGSEGV, ui__signal);
140 signal(SIGFPE, ui__signal);
141 signal(SIGINT, ui__signal);
142 signal(SIGQUIT, ui__signal);
143 signal(SIGTERM, ui__signal);
144} 29}
145 30
146void exit_browser(bool wait_for_ok) 31void exit_browser(bool wait_for_ok)
147{ 32{
148 if (use_browser > 0) { 33 switch (use_browser) {
149 if (wait_for_ok) 34 case 2:
150 ui__question_window("Fatal Error", 35 perf_gtk__exit(wait_for_ok);
151 ui_helpline__last_msg, 36 break;
152 "Press any key...", 0); 37
153 ui__exit(); 38 case 1:
39 ui__exit(wait_for_ok);
40 break;
41
42 default:
43 break;
154 } 44 }
155} 45}
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
new file mode 100644
index 000000000000..d33e943ac434
--- /dev/null
+++ b/tools/perf/ui/tui/setup.c
@@ -0,0 +1,140 @@
1#include <newt.h>
2#include <signal.h>
3#include <stdbool.h>
4
5#include "../../util/cache.h"
6#include "../../util/debug.h"
7#include "../browser.h"
8#include "../helpline.h"
9#include "../ui.h"
10#include "../util.h"
11#include "../libslang.h"
12#include "../keysyms.h"
13
14pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
15
16static volatile int ui__need_resize;
17
18void ui__refresh_dimensions(bool force)
19{
20 if (force || ui__need_resize) {
21 ui__need_resize = 0;
22 pthread_mutex_lock(&ui__lock);
23 SLtt_get_screen_size();
24 SLsmg_reinit_smg();
25 pthread_mutex_unlock(&ui__lock);
26 }
27}
28
29static void ui__sigwinch(int sig __used)
30{
31 ui__need_resize = 1;
32}
33
34static void ui__setup_sigwinch(void)
35{
36 static bool done;
37
38 if (done)
39 return;
40
41 done = true;
42 pthread__unblock_sigwinch();
43 signal(SIGWINCH, ui__sigwinch);
44}
45
46int ui__getch(int delay_secs)
47{
48 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
49 fd_set read_set;
50 int err, key;
51
52 ui__setup_sigwinch();
53
54 FD_ZERO(&read_set);
55 FD_SET(0, &read_set);
56
57 if (delay_secs) {
58 timeout.tv_sec = delay_secs;
59 timeout.tv_usec = 0;
60 }
61
62 err = select(1, &read_set, NULL, NULL, ptimeout);
63
64 if (err == 0)
65 return K_TIMER;
66
67 if (err == -1) {
68 if (errno == EINTR)
69 return K_RESIZE;
70 return K_ERROR;
71 }
72
73 key = SLang_getkey();
74 if (key != K_ESC)
75 return key;
76
77 FD_ZERO(&read_set);
78 FD_SET(0, &read_set);
79 timeout.tv_sec = 0;
80 timeout.tv_usec = 20;
81 err = select(1, &read_set, NULL, NULL, &timeout);
82 if (err == 0)
83 return K_ESC;
84
85 SLang_ungetkey(key);
86 return SLkp_getkey();
87}
88
89static void newt_suspend(void *d __used)
90{
91 newtSuspend();
92 raise(SIGTSTP);
93 newtResume();
94}
95
96static void ui__signal(int sig)
97{
98 ui__exit(false);
99 psignal(sig, "perf");
100 exit(0);
101}
102
103int ui__init(void)
104{
105 int err;
106
107 newtInit();
108 err = SLkp_init();
109 if (err < 0) {
110 pr_err("TUI initialization failed.\n");
111 goto out;
112 }
113
114 SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB);
115
116 newtSetSuspendCallback(newt_suspend, NULL);
117 ui_helpline__init();
118 ui_browser__init();
119
120 signal(SIGSEGV, ui__signal);
121 signal(SIGFPE, ui__signal);
122 signal(SIGINT, ui__signal);
123 signal(SIGQUIT, ui__signal);
124 signal(SIGTERM, ui__signal);
125out:
126 return err;
127}
128
129void ui__exit(bool wait_for_ok)
130{
131 if (wait_for_ok)
132 ui__question_window("Fatal Error",
133 ui_helpline__last_msg,
134 "Press any key...", 0);
135
136 SLtt_set_cursor_visibility(1);
137 SLsmg_refresh();
138 SLsmg_reset_smg();
139 SLang_reset_tty();
140}
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 8dd224df3e54..cff18c617d13 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -33,7 +33,7 @@ extern int pager_use_color;
33 33
34extern int use_browser; 34extern int use_browser;
35 35
36#ifdef NO_NEWT_SUPPORT 36#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
37static inline void setup_browser(bool fallback_to_pager) 37static inline void setup_browser(bool fallback_to_pager)
38{ 38{
39 if (fallback_to_pager) 39 if (fallback_to_pager)
@@ -43,19 +43,29 @@ static inline void exit_browser(bool wait_for_ok __used) {}
43#else 43#else
44void setup_browser(bool fallback_to_pager); 44void setup_browser(bool fallback_to_pager);
45void exit_browser(bool wait_for_ok); 45void exit_browser(bool wait_for_ok);
46
47#ifdef NO_NEWT_SUPPORT
48static inline int ui__init(void)
49{
50 return -1;
51}
52static inline void ui__exit(bool wait_for_ok __used) {}
53#else
54int ui__init(void);
55void ui__exit(bool wait_for_ok);
46#endif 56#endif
47 57
48#ifdef NO_GTK2_SUPPORT 58#ifdef NO_GTK2_SUPPORT
49static inline void perf_gtk_setup_browser(int argc __used, const char *argv[] __used, bool fallback_to_pager) 59static inline int perf_gtk__init(void)
50{ 60{
51 if (fallback_to_pager) 61 return -1;
52 setup_pager();
53} 62}
54static inline void perf_gtk_exit_browser(bool wait_for_ok __used) {} 63static inline void perf_gtk__exit(bool wait_for_ok __used) {}
55#else 64#else
56void perf_gtk_setup_browser(int argc, const char *argv[], bool fallback_to_pager); 65int perf_gtk__init(void);
57void perf_gtk_exit_browser(bool wait_for_ok); 66void perf_gtk__exit(bool wait_for_ok);
58#endif 67#endif
68#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
59 69
60char *alias_lookup(const char *alias); 70char *alias_lookup(const char *alias);
61int split_cmdline(char *cmdline, const char ***argv); 71int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 26817daa2961..efb1fce259a4 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -11,6 +11,7 @@
11#include "event.h" 11#include "event.h"
12#include "debug.h" 12#include "debug.h"
13#include "util.h" 13#include "util.h"
14#include "target.h"
14 15
15int verbose; 16int verbose;
16bool dump_trace = false, quiet = false; 17bool dump_trace = false, quiet = false;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 1986d8051bd1..1201daf71719 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -11,6 +11,7 @@
11#include <poll.h> 11#include <poll.h>
12#include "cpumap.h" 12#include "cpumap.h"
13#include "thread_map.h" 13#include "thread_map.h"
14#include "target.h"
14#include "evlist.h" 15#include "evlist.h"
15#include "evsel.h" 16#include "evsel.h"
16#include <unistd.h> 17#include <unistd.h>
@@ -599,18 +600,19 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
599 return perf_evlist__mmap_per_cpu(evlist, prot, mask); 600 return perf_evlist__mmap_per_cpu(evlist, prot, mask);
600} 601}
601 602
602int perf_evlist__create_maps(struct perf_evlist *evlist, const char *target_pid, 603int perf_evlist__create_maps(struct perf_evlist *evlist,
603 const char *target_tid, uid_t uid, const char *cpu_list) 604 struct perf_target *target)
604{ 605{
605 evlist->threads = thread_map__new_str(target_pid, target_tid, uid); 606 evlist->threads = thread_map__new_str(target->pid, target->tid,
607 target->uid);
606 608
607 if (evlist->threads == NULL) 609 if (evlist->threads == NULL)
608 return -1; 610 return -1;
609 611
610 if (uid != UINT_MAX || (cpu_list == NULL && target_tid)) 612 if (!perf_target__no_cpu(target))
611 evlist->cpus = cpu_map__dummy_new(); 613 evlist->cpus = cpu_map__new(target->cpu_list);
612 else 614 else
613 evlist->cpus = cpu_map__new(cpu_list); 615 evlist->cpus = cpu_map__dummy_new();
614 616
615 if (evlist->cpus == NULL) 617 if (evlist->cpus == NULL)
616 goto out_delete_threads; 618 goto out_delete_threads;
@@ -827,7 +829,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
827 exit(-1); 829 exit(-1);
828 } 830 }
829 831
830 if (!opts->system_wide && !opts->target_tid && !opts->target_pid) 832 if (perf_target__none(&opts->target))
831 evlist->threads->map[0] = evlist->workload.pid; 833 evlist->threads->map[0] = evlist->workload.pid;
832 834
833 close(child_ready_pipe[1]); 835 close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 21f1c9e57f13..58abb63ac13a 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, const char *target_pid, 109int perf_evlist__create_maps(struct perf_evlist *evlist,
110 const char *tid, uid_t uid, const char *cpu_list); 110 struct perf_target *target);
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 8c13dbcb84b9..21eaab240396 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -14,6 +14,7 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "thread_map.h" 16#include "thread_map.h"
17#include "target.h"
17 18
18#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 19#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
19#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0)) 20#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -106,15 +107,15 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
106 if (opts->call_graph) 107 if (opts->call_graph)
107 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 108 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
108 109
109 if (opts->system_wide) 110 if (opts->target.system_wide)
110 attr->sample_type |= PERF_SAMPLE_CPU; 111 attr->sample_type |= PERF_SAMPLE_CPU;
111 112
112 if (opts->period) 113 if (opts->period)
113 attr->sample_type |= PERF_SAMPLE_PERIOD; 114 attr->sample_type |= PERF_SAMPLE_PERIOD;
114 115
115 if (!opts->sample_id_all_missing && 116 if (!opts->sample_id_all_missing &&
116 (opts->sample_time || opts->system_wide || 117 (opts->sample_time || !opts->no_inherit ||
117 !opts->no_inherit || opts->cpu_list)) 118 !perf_target__no_cpu(&opts->target)))
118 attr->sample_type |= PERF_SAMPLE_TIME; 119 attr->sample_type |= PERF_SAMPLE_TIME;
119 120
120 if (opts->raw_samples) { 121 if (opts->raw_samples) {
@@ -135,7 +136,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
135 attr->mmap = track; 136 attr->mmap = track;
136 attr->comm = track; 137 attr->comm = track;
137 138
138 if (!opts->target_pid && !opts->target_tid && !opts->system_wide && 139 if (perf_target__none(&opts->target) &&
139 (!opts->group || evsel == first)) { 140 (!opts->group || evsel == first)) {
140 attr->disabled = 1; 141 attr->disabled = 1;
141 attr->enable_on_exec = 1; 142 attr->enable_on_exec = 1;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4c7c2d73251f..6e618ba21382 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -31,21 +31,16 @@ static const char **header_argv;
31 31
32int perf_header__push_event(u64 id, const char *name) 32int perf_header__push_event(u64 id, const char *name)
33{ 33{
34 struct perf_trace_event_type *nevents;
35
34 if (strlen(name) > MAX_EVENT_NAME) 36 if (strlen(name) > MAX_EVENT_NAME)
35 pr_warning("Event %s will be truncated\n", name); 37 pr_warning("Event %s will be truncated\n", name);
36 38
37 if (!events) { 39 nevents = realloc(events, (event_count + 1) * sizeof(*events));
38 events = malloc(sizeof(struct perf_trace_event_type)); 40 if (nevents == NULL)
39 if (events == NULL) 41 return -ENOMEM;
40 return -ENOMEM; 42 events = nevents;
41 } else {
42 struct perf_trace_event_type *nevents;
43 43
44 nevents = realloc(events, (event_count + 1) * sizeof(*events));
45 if (nevents == NULL)
46 return -ENOMEM;
47 events = nevents;
48 }
49 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type)); 44 memset(&events[event_count], 0, sizeof(struct perf_trace_event_type));
50 events[event_count].event_id = id; 45 events[event_count].event_id = id;
51 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1); 46 strncpy(events[event_count].name, name, MAX_EVENT_NAME - 1);
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ca069f893381..5cb002894a17 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -4,7 +4,9 @@
4 * Parse symbolic events/counts passed in as options: 4 * Parse symbolic events/counts passed in as options:
5 */ 5 */
6 6
7#include <stdbool.h>
7#include "../../../include/linux/perf_event.h" 8#include "../../../include/linux/perf_event.h"
9#include "types.h"
8 10
9struct list_head; 11struct list_head;
10struct perf_evsel; 12struct perf_evsel;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 1efd3bee6336..4dcc8f3190cf 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1108,16 +1108,10 @@ more:
1108 } 1108 }
1109 1109
1110 if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) { 1110 if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) {
1111 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1111 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1112 head, event.header.size, event.header.type); 1112 head, event.header.size, event.header.type);
1113 /* 1113 err = -EINVAL;
1114 * assume we lost track of the stream, check alignment, and 1114 goto out_err;
1115 * increment a single u64 in the hope to catch on again 'soon'.
1116 */
1117 if (unlikely(head & 7))
1118 head &= ~7ULL;
1119
1120 size = 8;
1121 } 1115 }
1122 1116
1123 head += size; 1117 head += size;
@@ -1226,17 +1220,11 @@ more:
1226 1220
1227 if (size == 0 || 1221 if (size == 0 ||
1228 perf_session__process_event(session, event, tool, file_pos) < 0) { 1222 perf_session__process_event(session, event, tool, file_pos) < 0) {
1229 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1223 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1230 file_offset + head, event->header.size, 1224 file_offset + head, event->header.size,
1231 event->header.type); 1225 event->header.type);
1232 /* 1226 err = -EINVAL;
1233 * assume we lost track of the stream, check alignment, and 1227 goto out_err;
1234 * increment a single u64 in the hope to catch on again 'soon'.
1235 */
1236 if (unlikely(head & 7))
1237 head &= ~7ULL;
1238
1239 size = 8;
1240 } 1228 }
1241 1229
1242 head += size; 1230 head += size;
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
new file mode 100644
index 000000000000..1064d5b148ad
--- /dev/null
+++ b/tools/perf/util/target.c
@@ -0,0 +1,142 @@
1/*
2 * Helper functions for handling target threads/cpus
3 *
4 * Copyright (C) 2012, LG Electronics, Namhyung Kim <namhyung.kim@lge.com>
5 *
6 * Released under the GPL v2.
7 */
8
9#include "target.h"
10#include "debug.h"
11
12#include <pwd.h>
13#include <string.h>
14
15
16enum perf_target_errno perf_target__validate(struct perf_target *target)
17{
18 enum perf_target_errno ret = PERF_ERRNO_TARGET__SUCCESS;
19
20 if (target->pid)
21 target->tid = target->pid;
22
23 /* CPU and PID are mutually exclusive */
24 if (target->tid && target->cpu_list) {
25 target->cpu_list = NULL;
26 if (ret == PERF_ERRNO_TARGET__SUCCESS)
27 ret = PERF_ERRNO_TARGET__PID_OVERRIDE_CPU;
28 }
29
30 /* UID and PID are mutually exclusive */
31 if (target->tid && target->uid_str) {
32 target->uid_str = NULL;
33 if (ret == PERF_ERRNO_TARGET__SUCCESS)
34 ret = PERF_ERRNO_TARGET__PID_OVERRIDE_UID;
35 }
36
37 /* UID and CPU are mutually exclusive */
38 if (target->uid_str && target->cpu_list) {
39 target->cpu_list = NULL;
40 if (ret == PERF_ERRNO_TARGET__SUCCESS)
41 ret = PERF_ERRNO_TARGET__UID_OVERRIDE_CPU;
42 }
43
44 /* PID and SYSTEM are mutually exclusive */
45 if (target->tid && target->system_wide) {
46 target->system_wide = false;
47 if (ret == PERF_ERRNO_TARGET__SUCCESS)
48 ret = PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM;
49 }
50
51 /* UID and SYSTEM are mutually exclusive */
52 if (target->uid_str && target->system_wide) {
53 target->system_wide = false;
54 if (ret == PERF_ERRNO_TARGET__SUCCESS)
55 ret = PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM;
56 }
57
58 return ret;
59}
60
61enum perf_target_errno perf_target__parse_uid(struct perf_target *target)
62{
63 struct passwd pwd, *result;
64 char buf[1024];
65 const char *str = target->uid_str;
66
67 target->uid = UINT_MAX;
68 if (str == NULL)
69 return PERF_ERRNO_TARGET__SUCCESS;
70
71 /* Try user name first */
72 getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
73
74 if (result == NULL) {
75 /*
76 * The user name not found. Maybe it's a UID number.
77 */
78 char *endptr;
79 int uid = strtol(str, &endptr, 10);
80
81 if (*endptr != '\0')
82 return PERF_ERRNO_TARGET__INVALID_UID;
83
84 getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
85
86 if (result == NULL)
87 return PERF_ERRNO_TARGET__USER_NOT_FOUND;
88 }
89
90 target->uid = result->pw_uid;
91 return PERF_ERRNO_TARGET__SUCCESS;
92}
93
94/*
95 * This must have a same ordering as the enum perf_target_errno.
96 */
97static const char *perf_target__error_str[] = {
98 "PID/TID switch overriding CPU",
99 "PID/TID switch overriding UID",
100 "UID switch overriding CPU",
101 "PID/TID switch overriding SYSTEM",
102 "UID switch overriding SYSTEM",
103 "Invalid User: %s",
104 "Problems obtaining information for user %s",
105};
106
107int perf_target__strerror(struct perf_target *target, int errnum,
108 char *buf, size_t buflen)
109{
110 int idx;
111 const char *msg;
112
113 if (errnum >= 0) {
114 strerror_r(errnum, buf, buflen);
115 return 0;
116 }
117
118 if (errnum < __PERF_ERRNO_TARGET__START ||
119 errnum >= __PERF_ERRNO_TARGET__END)
120 return -1;
121
122 idx = errnum - __PERF_ERRNO_TARGET__START;
123 msg = perf_target__error_str[idx];
124
125 switch (errnum) {
126 case PERF_ERRNO_TARGET__PID_OVERRIDE_CPU
127 ... PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM:
128 snprintf(buf, buflen, "%s", msg);
129 break;
130
131 case PERF_ERRNO_TARGET__INVALID_UID:
132 case PERF_ERRNO_TARGET__USER_NOT_FOUND:
133 snprintf(buf, buflen, msg, target->uid_str);
134 break;
135
136 default:
137 /* cannot reach here */
138 break;
139 }
140
141 return 0;
142}
diff --git a/tools/perf/util/target.h b/tools/perf/util/target.h
new file mode 100644
index 000000000000..127cff3f8ced
--- /dev/null
+++ b/tools/perf/util/target.h
@@ -0,0 +1,64 @@
1#ifndef _PERF_TARGET_H
2#define _PERF_TARGET_H
3
4#include <stdbool.h>
5#include <sys/types.h>
6
7struct perf_target {
8 const char *pid;
9 const char *tid;
10 const char *cpu_list;
11 const char *uid_str;
12 uid_t uid;
13 bool system_wide;
14};
15
16enum perf_target_errno {
17 PERF_ERRNO_TARGET__SUCCESS = 0,
18
19 /*
20 * Choose an arbitrary negative big number not to clash with standard
21 * errno since SUS requires the errno has distinct positive values.
22 * See 'Issue 6' in the link below.
23 *
24 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
25 */
26 __PERF_ERRNO_TARGET__START = -10000,
27
28
29 /* for perf_target__validate() */
30 PERF_ERRNO_TARGET__PID_OVERRIDE_CPU = __PERF_ERRNO_TARGET__START,
31 PERF_ERRNO_TARGET__PID_OVERRIDE_UID,
32 PERF_ERRNO_TARGET__UID_OVERRIDE_CPU,
33 PERF_ERRNO_TARGET__PID_OVERRIDE_SYSTEM,
34 PERF_ERRNO_TARGET__UID_OVERRIDE_SYSTEM,
35
36 /* for perf_target__parse_uid() */
37 PERF_ERRNO_TARGET__INVALID_UID,
38 PERF_ERRNO_TARGET__USER_NOT_FOUND,
39
40 __PERF_ERRNO_TARGET__END,
41};
42
43enum perf_target_errno perf_target__validate(struct perf_target *target);
44enum perf_target_errno perf_target__parse_uid(struct perf_target *target);
45
46int perf_target__strerror(struct perf_target *target, int errnum, char *buf,
47 size_t buflen);
48
49static inline bool perf_target__no_task(struct perf_target *target)
50{
51 return !target->pid && !target->tid && !target->uid_str;
52}
53
54static inline bool perf_target__no_cpu(struct perf_target *target)
55{
56 return !target->system_wide && !target->cpu_list;
57}
58
59static inline bool perf_target__none(struct perf_target *target)
60{
61 return perf_target__no_task(target) && perf_target__no_cpu(target);
62}
63
64#endif /* _PERF_TARGET_H */
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 09fe579ccafb..abe0e8e95068 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -69,23 +69,24 @@ 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) 72 if (top->target.pid)
73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s", 73 ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %s",
74 top->target_pid); 74 top->target.pid);
75 else if (top->target_tid) 75 else if (top->target.tid)
76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %s", 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->target.uid_str != NULL)
79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s", 79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
80 top->uid_str); 80 top->target.uid_str);
81 else 81 else
82 ret += SNPRINTF(bf + ret, size - ret, " (all"); 82 ret += SNPRINTF(bf + ret, size - ret, " (all");
83 83
84 if (top->cpu_list) 84 if (top->target.cpu_list)
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" : "",
87 top->target.cpu_list);
87 else { 88 else {
88 if (top->target_tid) 89 if (top->target.tid)
89 ret += SNPRINTF(bf + ret, size - ret, ")"); 90 ret += SNPRINTF(bf + ret, size - ret, ")");
90 else 91 else
91 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)", 92 ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index ce61cb2d1acf..33347ca89ee4 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -13,6 +13,7 @@ struct perf_session;
13struct perf_top { 13struct perf_top {
14 struct perf_tool tool; 14 struct perf_tool tool;
15 struct perf_evlist *evlist; 15 struct perf_evlist *evlist;
16 struct perf_target target;
16 /* 17 /*
17 * Symbols will be added here in perf_event__process_sample and will 18 * Symbols will be added here in perf_event__process_sample and will
18 * get out after decayed. 19 * get out after decayed.
@@ -23,10 +24,7 @@ struct perf_top {
23 u64 guest_us_samples, guest_kernel_samples; 24 u64 guest_us_samples, guest_kernel_samples;
24 int print_entries, count_filter, delay_secs; 25 int print_entries, count_filter, delay_secs;
25 int freq; 26 int freq;
26 const char *target_pid, *target_tid;
27 uid_t uid;
28 bool hide_kernel_symbols, hide_user_symbols, zero; 27 bool hide_kernel_symbols, hide_user_symbols, zero;
29 bool system_wide;
30 bool use_tui, use_stdio; 28 bool use_tui, use_stdio;
31 bool sort_has_symbols; 29 bool sort_has_symbols;
32 bool dont_use_callchains; 30 bool dont_use_callchains;
@@ -37,7 +35,6 @@ struct perf_top {
37 bool sample_id_all_missing; 35 bool sample_id_all_missing;
38 bool exclude_guest_missing; 36 bool exclude_guest_missing;
39 bool dump_symtab; 37 bool dump_symtab;
40 const char *cpu_list;
41 struct hist_entry *sym_filter_entry; 38 struct hist_entry *sym_filter_entry;
42 struct perf_evsel *sym_evsel; 39 struct perf_evsel *sym_evsel;
43 struct perf_session *session; 40 struct perf_session *session;
@@ -47,7 +44,6 @@ struct perf_top {
47 int realtime_prio; 44 int realtime_prio;
48 int sym_pcnt_filter; 45 int sym_pcnt_filter;
49 const char *sym_filter; 46 const char *sym_filter;
50 const char *uid_str;
51}; 47};
52 48
53size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 49size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index 52bb07c6442a..4007aca8e0ca 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -82,41 +82,3 @@ void warning(const char *warn, ...)
82 warn_routine(warn, params); 82 warn_routine(warn, params);
83 va_end(params); 83 va_end(params);
84} 84}
85
86uid_t parse_target_uid(const char *str, const char *tid, const char *pid)
87{
88 struct passwd pwd, *result;
89 char buf[1024];
90
91 if (str == NULL)
92 return UINT_MAX;
93
94 /* UID and PID are mutually exclusive */
95 if (tid || pid) {
96 ui__warning("PID/TID switch overriding UID\n");
97 sleep(1);
98 return UINT_MAX;
99 }
100
101 getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
102
103 if (result == NULL) {
104 char *endptr;
105 int uid = strtol(str, &endptr, 10);
106
107 if (*endptr != '\0') {
108 ui__error("Invalid user %s\n", str);
109 return UINT_MAX - 1;
110 }
111
112 getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
113
114 if (result == NULL) {
115 ui__error("Problems obtaining information for user %s\n",
116 str);
117 return UINT_MAX - 1;
118 }
119 }
120
121 return result->pw_uid;
122}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 6121e24fefc0..2daaedb83d84 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -74,7 +74,6 @@
74#include <netinet/tcp.h> 74#include <netinet/tcp.h>
75#include <arpa/inet.h> 75#include <arpa/inet.h>
76#include <netdb.h> 76#include <netdb.h>
77#include <pwd.h>
78#include <inttypes.h> 77#include <inttypes.h>
79#include "../../../include/linux/magic.h" 78#include "../../../include/linux/magic.h"
80#include "types.h" 79#include "types.h"
@@ -249,8 +248,6 @@ struct perf_event_attr;
249 248
250void event_attr_init(struct perf_event_attr *attr); 249void event_attr_init(struct perf_event_attr *attr);
251 250
252uid_t parse_target_uid(const char *str, const char *tid, const char *pid);
253
254#define _STR(x) #x 251#define _STR(x) #x
255#define STR(x) _STR(x) 252#define STR(x) _STR(x)
256 253