Skip to content

Commit

Permalink
perf evsel: Do missing feature fallbacks in just one place
Browse files Browse the repository at this point in the history
Instead of doing it in stat, top, record or any other tool that opens
event descriptors.

Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-vr8hzph83d5t2mdlkf565h84@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Arnaldo Carvalho de Melo committed Jan 24, 2013
1 parent ce90e38 commit 594ac61
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 90 deletions.
36 changes: 0 additions & 36 deletions tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,25 +234,6 @@ static int perf_record__open(struct perf_record *rec)

list_for_each_entry(pos, &evlist->entries, node) {
struct perf_event_attr *attr = &pos->attr;
/*
* Check if parse_single_tracepoint_event has already asked for
* PERF_SAMPLE_TIME.
*
* XXX this is kludgy but short term fix for problems introduced by
* eac23d1c that broke 'perf script' by having different sample_types
* when using multiple tracepoint events when we use a perf binary
* that tries to use sample_id_all on an older kernel.
*
* We need to move counter creation to perf_session, support
* different sample_types, etc.
*/
bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;

fallback_missing_features:
if (opts->exclude_guest_missing)
attr->exclude_guest = attr->exclude_host = 0;
retry_sample_id:
attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
try_again:
if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) {
int err = errno;
Expand All @@ -266,23 +247,6 @@ static int perf_record__open(struct perf_record *rec)
" an out-of-range profile CPU?\n");
rc = -err;
goto out;
} else if (err == EINVAL) {
if (!opts->exclude_guest_missing &&
(attr->exclude_guest || attr->exclude_host)) {
pr_debug("Old kernel, cannot exclude "
"guest or host samples.\n");
opts->exclude_guest_missing = true;
goto fallback_missing_features;
} else if (!opts->sample_id_all_missing) {
/*
* Old kernel, no attr->sample_id_type_all field
*/
opts->sample_id_all_missing = true;
if (!opts->sample_time && !opts->raw_samples && !time_needed)
perf_evsel__reset_sample_bit(pos, TIME);

goto retry_sample_id;
}
}

/*
Expand Down
30 changes: 3 additions & 27 deletions tools/perf/builtin-stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,47 +132,23 @@ static struct stats walltime_nsecs_stats;
static int create_perf_stat_counter(struct perf_evsel *evsel)
{
struct perf_event_attr *attr = &evsel->attr;
bool exclude_guest_missing = false;
int ret;

if (scale)
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;

attr->inherit = !no_inherit;

retry:
if (exclude_guest_missing)
evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;

if (perf_target__has_cpu(&target)) {
ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
if (ret)
goto check_ret;
return 0;
}
if (perf_target__has_cpu(&target))
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));

if (!perf_target__has_task(&target) &&
perf_evsel__is_group_leader(evsel)) {
attr->disabled = 1;
attr->enable_on_exec = 1;
}

ret = perf_evsel__open_per_thread(evsel, evsel_list->threads);
if (!ret)
return 0;
/* fall through */
check_ret:
if (ret && errno == EINVAL) {
if (!exclude_guest_missing &&
(evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
pr_debug("Old kernel, cannot exclude "
"guest or host samples.\n");
exclude_guest_missing = true;
goto retry;
}
}
return ret;
return perf_evsel__open_per_thread(evsel, evsel_list->threads);
}

/*
Expand Down
20 changes: 0 additions & 20 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -900,12 +900,6 @@ static void perf_top__start_counters(struct perf_top *top)

list_for_each_entry(counter, &evlist->entries, node) {
struct perf_event_attr *attr = &counter->attr;

fallback_missing_features:
if (top->exclude_guest_missing)
attr->exclude_guest = attr->exclude_host = 0;
retry_sample_id:
attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
try_again:
if (perf_evsel__open(counter, top->evlist->cpus,
top->evlist->threads) < 0) {
Expand All @@ -914,20 +908,6 @@ static void perf_top__start_counters(struct perf_top *top)
if (err == EPERM || err == EACCES) {
ui__error_paranoid();
goto out_err;
} else if (err == EINVAL) {
if (!top->exclude_guest_missing &&
(attr->exclude_guest || attr->exclude_host)) {
pr_debug("Old kernel, cannot exclude "
"guest or host samples.\n");
top->exclude_guest_missing = true;
goto fallback_missing_features;
} else if (!top->sample_id_all_missing) {
/*
* Old kernel, no attr->sample_id_type_all field
*/
top->sample_id_all_missing = true;
goto retry_sample_id;
}
}
/*
* If it's cycles then fall back to hrtimer
Expand Down
2 changes: 0 additions & 2 deletions tools/perf/perf.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,6 @@ struct perf_record_opts {
bool raw_samples;
bool sample_address;
bool sample_time;
bool sample_id_all_missing;
bool exclude_guest_missing;
bool period;
unsigned int freq;
unsigned int mmap_pages;
Expand Down
31 changes: 28 additions & 3 deletions tools/perf/util/evsel.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
#include <linux/perf_event.h>
#include "perf_regs.h"

static struct {
bool sample_id_all;
bool exclude_guest;
} perf_missing_features;

#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))

static int __perf_evsel__sample_size(u64 sample_type)
Expand Down Expand Up @@ -463,7 +468,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
struct perf_event_attr *attr = &evsel->attr;
int track = !evsel->idx; /* only the first counter needs these */

attr->sample_id_all = opts->sample_id_all_missing ? 0 : 1;
attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
attr->inherit = !opts->no_inherit;

perf_evsel__set_sample_bit(evsel, IP);
Expand Down Expand Up @@ -513,7 +518,7 @@ void perf_evsel__config(struct perf_evsel *evsel,
if (opts->period)
perf_evsel__set_sample_bit(evsel, PERIOD);

if (!opts->sample_id_all_missing &&
if (!perf_missing_features.sample_id_all &&
(opts->sample_time || !opts->no_inherit ||
perf_target__has_cpu(&opts->target)))
perf_evsel__set_sample_bit(evsel, TIME);
Expand Down Expand Up @@ -761,6 +766,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
pid = evsel->cgrp->fd;
}

fallback_missing_features:
if (perf_missing_features.exclude_guest)
evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
retry_sample_id:
if (perf_missing_features.sample_id_all)
evsel->attr.sample_id_all = 0;

for (cpu = 0; cpu < cpus->nr; cpu++) {

for (thread = 0; thread < threads->nr; thread++) {
Expand All @@ -777,13 +789,26 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
group_fd, flags);
if (FD(evsel, cpu, thread) < 0) {
err = -errno;
goto out_close;
goto try_fallback;
}
}
}

return 0;

try_fallback:
if (err != -EINVAL || cpu > 0 || thread > 0)
goto out_close;

if (!perf_missing_features.exclude_guest &&
(evsel->attr.exclude_guest || evsel->attr.exclude_host)) {
perf_missing_features.exclude_guest = true;
goto fallback_missing_features;
} else if (!perf_missing_features.sample_id_all) {
perf_missing_features.sample_id_all = true;
goto retry_sample_id;
}

out_close:
do {
while (--thread >= 0) {
Expand Down
2 changes: 0 additions & 2 deletions tools/perf/util/top.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ struct perf_top {
bool sort_has_symbols;
bool kptr_restrict_warned;
bool vmlinux_warned;
bool sample_id_all_missing;
bool exclude_guest_missing;
bool dump_symtab;
struct hist_entry *sym_filter_entry;
struct perf_evsel *sym_evsel;
Expand Down

0 comments on commit 594ac61

Please sign in to comment.