Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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>
  • Loading branch information
Ingo Molnar committed May 11, 2012
2 parents c4f400e + 5a5626b commit 5dcefda
Show file tree
Hide file tree
Showing 27 changed files with 583 additions and 369 deletions.
8 changes: 8 additions & 0 deletions tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ LIB_H += util/cpumap.h
LIB_H += util/top.h
LIB_H += $(ARCH_INCLUDE)
LIB_H += util/cgroup.h
LIB_H += util/target.h

LIB_OBJS += $(OUTPUT)util/abspath.o
LIB_OBJS += $(OUTPUT)util/alias.o
Expand Down Expand Up @@ -361,6 +362,7 @@ LIB_OBJS += $(OUTPUT)util/util.o
LIB_OBJS += $(OUTPUT)util/xyarray.o
LIB_OBJS += $(OUTPUT)util/cpumap.o
LIB_OBJS += $(OUTPUT)util/cgroup.o
LIB_OBJS += $(OUTPUT)util/target.o

BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o

Expand Down Expand Up @@ -481,6 +483,7 @@ else
LIB_OBJS += $(OUTPUT)ui/helpline.o
LIB_OBJS += $(OUTPUT)ui/progress.o
LIB_OBJS += $(OUTPUT)ui/util.o
LIB_OBJS += $(OUTPUT)ui/tui/setup.o
LIB_H += ui/browser.h
LIB_H += ui/browsers/map.h
LIB_H += ui/helpline.h
Expand All @@ -503,6 +506,11 @@ else
BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
# Make sure that it'd be included only once.
ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
LIB_OBJS += $(OUTPUT)ui/setup.o
endif
endif
endif

Expand Down
60 changes: 38 additions & 22 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ struct perf_record {
struct perf_evlist *evlist;
struct perf_session *session;
const char *progname;
const char *uid_str;
int output;
unsigned int page_size;
int realtime_prio;
Expand Down Expand Up @@ -218,7 +217,7 @@ static void perf_record__open(struct perf_record *rec)
if (err == EPERM || err == EACCES) {
ui__error_paranoid();
exit(EXIT_FAILURE);
} else if (err == ENODEV && opts->cpu_list) {
} else if (err == ENODEV && opts->target.cpu_list) {
die("No such device - did you specify"
" an out-of-range profile CPU?\n");
} else if (err == EINVAL) {
Expand All @@ -243,16 +242,24 @@ static void perf_record__open(struct perf_record *rec)
/*
* If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which
* is always available even if no PMU support:
* is always available even if no PMU support.
*
* PPC returns ENXIO until 2.6.37 (behavior changed
* with commit b0a873e).
*/
if (err == ENOENT && attr->type == PERF_TYPE_HARDWARE
if ((err == ENOENT || err == ENXIO)
&& attr->type == PERF_TYPE_HARDWARE
&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {

if (verbose)
ui__warning("The cycles event is not supported, "
"trying to fall back to cpu-clock-ticks\n");
attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_SW_CPU_CLOCK;
if (pos->name) {
free(pos->name);
pos->name = NULL;
}
goto try_again;
}

Expand Down Expand Up @@ -578,7 +585,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
perf_session__process_machines(session, tool,
perf_event__synthesize_guest_os);

if (!opts->system_wide)
if (!opts->target.system_wide)
perf_event__synthesize_thread_map(tool, evsel_list->threads,
process_synthesized_event,
machine);
Expand Down Expand Up @@ -765,21 +772,21 @@ const struct option record_options[] = {
parse_events_option),
OPT_CALLBACK(0, "filter", &record.evlist, "filter",
"event filter", parse_filter),
OPT_STRING('p', "pid", &record.opts.target_pid, "pid",
OPT_STRING('p', "pid", &record.opts.target.pid, "pid",
"record events on existing process id"),
OPT_STRING('t', "tid", &record.opts.target_tid, "tid",
OPT_STRING('t', "tid", &record.opts.target.tid, "tid",
"record events on existing thread id"),
OPT_INTEGER('r', "realtime", &record.realtime_prio,
"collect data with this RT SCHED_FIFO priority"),
OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
"collect data without buffering"),
OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
"collect raw sample records from all opened counters"),
OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
OPT_BOOLEAN('a', "all-cpus", &record.opts.target.system_wide,
"system-wide collection from all CPUs"),
OPT_BOOLEAN('A', "append", &record.append_file,
"append to the output file to do incremental profiling"),
OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
"list of cpus to monitor"),
OPT_BOOLEAN('f', "force", &record.force,
"overwrite existing data file (deprecated)"),
Expand Down Expand Up @@ -813,7 +820,8 @@ const struct option record_options[] = {
OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
"monitor event in cgroup name only",
parse_cgroups),
OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
OPT_STRING('u', "uid", &record.opts.target.uid_str, "user",
"user to profile"),

OPT_CALLBACK_NOOPT('b', "branch-any", &record.opts.branch_stack,
"branch any", "sample any taken branches",
Expand All @@ -831,6 +839,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
struct perf_evsel *pos;
struct perf_evlist *evsel_list;
struct perf_record *rec = &record;
char errbuf[BUFSIZ];

perf_header__set_cmdline(argc, argv);

Expand All @@ -842,8 +851,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)

argc = parse_options(argc, argv, record_options, record_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc && !rec->opts.target_pid && !rec->opts.target_tid &&
!rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
if (!argc && perf_target__none(&rec->opts.target))
usage_with_options(record_usage, record_options);

if (rec->force && rec->append_file) {
Expand All @@ -856,7 +864,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
rec->write_mode = WRITE_FORCE;
}

if (nr_cgroups && !rec->opts.system_wide) {
if (nr_cgroups && !rec->opts.target.system_wide) {
fprintf(stderr, "cgroup monitoring only available in"
" system-wide mode\n");
usage_with_options(record_usage, record_options);
Expand All @@ -883,17 +891,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
goto out_symbol_exit;
}

rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid,
rec->opts.target_pid);
if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1)
goto out_free_fd;
err = perf_target__validate(&rec->opts.target);
if (err) {
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
ui__warning("%s", errbuf);
}

err = perf_target__parse_uid(&rec->opts.target);
if (err) {
int saved_errno = errno;

if (rec->opts.target_pid)
rec->opts.target_tid = rec->opts.target_pid;
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
ui__warning("%s", errbuf);

err = -saved_errno;
goto out_free_fd;
}

if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
rec->opts.target_tid, rec->opts.uid,
rec->opts.cpu_list) < 0)
err = -ENOMEM;
if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
usage_with_options(record_usage, record_options);

list_for_each_entry(pos, &evsel_list->entries, node) {
Expand Down
12 changes: 4 additions & 8 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
if (evname != NULL)
ret += fprintf(fp, " of event '%s'", evname);

ret += fprintf(fp, "\n# Event count (approx.): %lu", nr_events);
ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
return ret + fprintf(fp, "\n#\n");
}

Expand Down Expand Up @@ -676,14 +676,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)

}

if (strcmp(report.input_name, "-") != 0) {
if (report.use_gtk)
perf_gtk_setup_browser(argc, argv, true);
else
setup_browser(true);
} else {
if (strcmp(report.input_name, "-") != 0)
setup_browser(true);
else
use_browser = 0;
}

/*
* Only in the newt browser we are doing integrated annotation,
Expand Down
65 changes: 30 additions & 35 deletions tools/perf/builtin-stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,22 +175,21 @@ static struct perf_event_attr very_very_detailed_attrs[] = {

static struct perf_evlist *evsel_list;

static bool system_wide = false;
static int run_idx = 0;
static struct perf_target target = {
.uid = UINT_MAX,
};

static int run_idx = 0;
static int run_count = 1;
static bool no_inherit = false;
static bool scale = true;
static bool no_aggr = false;
static const char *target_pid;
static const char *target_tid;
static pid_t child_pid = -1;
static bool null_run = false;
static int detailed_run = 0;
static bool sync_run = false;
static bool big_num = true;
static int big_num_opt = -1;
static const char *cpu_list;
static const char *csv_sep = NULL;
static bool csv_output = false;
static bool group = false;
Expand Down Expand Up @@ -293,10 +292,10 @@ static int create_perf_stat_counter(struct perf_evsel *evsel,

attr->inherit = !no_inherit;

if (system_wide)
if (!perf_target__no_cpu(&target))
return perf_evsel__open_per_cpu(evsel, evsel_list->cpus,
group, group_fd);
if (!target_pid && !target_tid && (!group || evsel == first)) {
if (perf_target__no_task(&target) && (!group || evsel == first)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}
Expand Down Expand Up @@ -446,7 +445,7 @@ static int run_perf_stat(int argc __used, const char **argv)
exit(-1);
}

if (!target_tid && !target_pid && !system_wide)
if (perf_target__none(&target))
evsel_list->threads->map[0] = child_pid;

/*
Expand All @@ -463,8 +462,13 @@ static int run_perf_stat(int argc __used, const char **argv)

list_for_each_entry(counter, &evsel_list->entries, node) {
if (create_perf_stat_counter(counter, first) < 0) {
/*
* PPC returns ENXIO for HW counters until 2.6.37
* (behavior changed with commit b0a873e).
*/
if (errno == EINVAL || errno == ENOSYS ||
errno == ENOENT || errno == EOPNOTSUPP) {
errno == ENOENT || errno == EOPNOTSUPP ||
errno == ENXIO) {
if (verbose)
ui__warning("%s event is not supported by the kernel.\n",
event_name(counter));
Expand All @@ -476,7 +480,7 @@ static int run_perf_stat(int argc __used, const char **argv)
error("You may not have permission to collect %sstats.\n"
"\t Consider tweaking"
" /proc/sys/kernel/perf_event_paranoid or running as root.",
system_wide ? "system-wide " : "");
target.system_wide ? "system-wide " : "");
} else {
error("open_counter returned with %d (%s). "
"/bin/dmesg may provide additional information.\n",
Expand Down Expand Up @@ -968,14 +972,14 @@ static void print_stat(int argc, const char **argv)
if (!csv_output) {
fprintf(output, "\n");
fprintf(output, " Performance counter stats for ");
if (!target_pid && !target_tid) {
if (perf_target__no_task(&target)) {
fprintf(output, "\'%s", argv[0]);
for (i = 1; i < argc; i++)
fprintf(output, " %s", argv[i]);
} else if (target_pid)
fprintf(output, "process id \'%s", target_pid);
} else if (target.pid)
fprintf(output, "process id \'%s", target.pid);
else
fprintf(output, "thread id \'%s", target_tid);
fprintf(output, "thread id \'%s", target.tid);

fprintf(output, "\'");
if (run_count > 1)
Expand Down Expand Up @@ -1049,11 +1053,11 @@ static const struct option options[] = {
"event filter", parse_filter),
OPT_BOOLEAN('i', "no-inherit", &no_inherit,
"child tasks do not inherit counters"),
OPT_STRING('p', "pid", &target_pid, "pid",
OPT_STRING('p', "pid", &target.pid, "pid",
"stat events on existing process id"),
OPT_STRING('t', "tid", &target_tid, "tid",
OPT_STRING('t', "tid", &target.tid, "tid",
"stat events on existing thread id"),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
"system-wide collection from all CPUs"),
OPT_BOOLEAN('g', "group", &group,
"put the counters into a counter group"),
Expand All @@ -1072,7 +1076,7 @@ static const struct option options[] = {
OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL,
"print large numbers with thousands\' separators",
stat__set_big_num),
OPT_STRING('C', "cpu", &cpu_list, "cpu",
OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
"list of cpus to monitor in system-wide"),
OPT_BOOLEAN('A', "no-aggr", &no_aggr,
"disable CPU count aggregation"),
Expand Down Expand Up @@ -1190,13 +1194,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
} else if (big_num_opt == 0) /* User passed --no-big-num */
big_num = false;

if (!argc && !target_pid && !target_tid)
if (!argc && perf_target__no_task(&target))
usage_with_options(stat_usage, options);
if (run_count <= 0)
usage_with_options(stat_usage, options);

/* no_aggr, cgroup are for system-wide only */
if ((no_aggr || nr_cgroups) && !system_wide) {
if ((no_aggr || nr_cgroups) && perf_target__no_cpu(&target)) {
fprintf(stderr, "both cgroup and no-aggregation "
"modes only available in system-wide mode\n");

Expand All @@ -1206,23 +1210,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
if (add_default_attributes())
goto out;

if (target_pid)
target_tid = target_pid;
perf_target__validate(&target);

evsel_list->threads = thread_map__new_str(target_pid,
target_tid, UINT_MAX);
if (evsel_list->threads == NULL) {
pr_err("Problems finding threads of monitor\n");
usage_with_options(stat_usage, options);
}

if (system_wide)
evsel_list->cpus = cpu_map__new(cpu_list);
else
evsel_list->cpus = cpu_map__dummy_new();
if (perf_evlist__create_maps(evsel_list, &target) < 0) {
if (!perf_target__no_task(&target))
pr_err("Problems finding threads of monitor\n");
if (!perf_target__no_cpu(&target))
perror("failed to parse CPUs map");

if (evsel_list->cpus == NULL) {
perror("failed to parse CPUs map");
usage_with_options(stat_usage, options);
return -1;
}
Expand Down
Loading

0 comments on commit 5dcefda

Please sign in to comment.