Merge branch 'perf/core' of git://github.com/acmel/linux into perf/core
This commit is contained in:
commit
d9e24427f3
12 changed files with 160 additions and 24 deletions
|
@ -80,9 +80,10 @@ OPTIONS
|
||||||
--dump-raw-trace::
|
--dump-raw-trace::
|
||||||
Dump raw trace in ASCII.
|
Dump raw trace in ASCII.
|
||||||
|
|
||||||
-g [type,min,order]::
|
-g [type,min[,limit],order]::
|
||||||
--call-graph::
|
--call-graph::
|
||||||
Display call chains using type, min percent threshold and order.
|
Display call chains using type, min percent threshold, optional print
|
||||||
|
limit and order.
|
||||||
type can be either:
|
type can be either:
|
||||||
- flat: single column, linear exposure of call chains.
|
- flat: single column, linear exposure of call chains.
|
||||||
- graph: use a graph tree, displaying absolute overhead rates.
|
- graph: use a graph tree, displaying absolute overhead rates.
|
||||||
|
|
|
@ -700,6 +700,7 @@ const struct option record_options[] = {
|
||||||
OPT_BOOLEAN('d', "data", &record.opts.sample_address,
|
OPT_BOOLEAN('d', "data", &record.opts.sample_address,
|
||||||
"Sample addresses"),
|
"Sample addresses"),
|
||||||
OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
|
OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
|
||||||
|
OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
|
||||||
OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
|
OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
|
||||||
"don't sample"),
|
"don't sample"),
|
||||||
OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
|
OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
|
||||||
|
|
|
@ -407,7 +407,7 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
|
||||||
goto setup;
|
goto setup;
|
||||||
|
|
||||||
if (tok2[0] != 'c') {
|
if (tok2[0] != 'c') {
|
||||||
callchain_param.print_limit = strtod(tok2, &endptr);
|
callchain_param.print_limit = strtoul(tok2, &endptr, 0);
|
||||||
tok2 = strtok(NULL, ",");
|
tok2 = strtok(NULL, ",");
|
||||||
if (!tok2)
|
if (!tok2)
|
||||||
goto setup;
|
goto setup;
|
||||||
|
@ -485,8 +485,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
|
||||||
"regex filter to identify parent, see: '--sort parent'"),
|
"regex filter to identify parent, see: '--sort parent'"),
|
||||||
OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
|
OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
|
||||||
"Only display entries with parent-match"),
|
"Only display entries with parent-match"),
|
||||||
OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent, call_order",
|
OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
|
||||||
"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
|
"Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit and callchain order. "
|
||||||
"Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
|
"Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
|
||||||
OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
|
OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
|
||||||
"alias for inverted call graph"),
|
"alias for inverted call graph"),
|
||||||
|
|
|
@ -603,7 +603,7 @@ out_free_threads:
|
||||||
|
|
||||||
#define TEST_ASSERT_VAL(text, cond) \
|
#define TEST_ASSERT_VAL(text, cond) \
|
||||||
do { \
|
do { \
|
||||||
if (!cond) { \
|
if (!(cond)) { \
|
||||||
pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
|
pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
|
@ -759,6 +759,103 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
|
struct perf_evsel, node);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
|
||||||
|
|
||||||
|
return test__checkevent_tracepoint(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel;
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
|
||||||
|
|
||||||
|
list_for_each_entry(evsel, &evlist->entries, node) {
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user",
|
||||||
|
!evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel",
|
||||||
|
evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
return test__checkevent_tracepoint_multi(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_raw_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
|
struct perf_evsel, node);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
|
||||||
|
|
||||||
|
return test__checkevent_raw(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_numeric_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
|
struct perf_evsel, node);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
|
||||||
|
|
||||||
|
return test__checkevent_numeric(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_symbolic_name_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
|
struct perf_evsel, node);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
|
||||||
|
|
||||||
|
return test__checkevent_symbolic_name(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
|
struct perf_evsel, node);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
|
||||||
|
|
||||||
|
return test__checkevent_symbolic_alias(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test__checkevent_genhw_modifier(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
|
struct perf_evsel, node);
|
||||||
|
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
||||||
|
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||||
|
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
|
||||||
|
|
||||||
|
return test__checkevent_genhw(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
static struct test__event_st {
|
static struct test__event_st {
|
||||||
const char *name;
|
const char *name;
|
||||||
__u32 type;
|
__u32 type;
|
||||||
|
@ -808,6 +905,34 @@ static struct test__event_st {
|
||||||
.name = "mem:0:w",
|
.name = "mem:0:w",
|
||||||
.check = test__checkevent_breakpoint_w,
|
.check = test__checkevent_breakpoint_w,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "syscalls:sys_enter_open:k",
|
||||||
|
.check = test__checkevent_tracepoint_modifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "syscalls:*:u",
|
||||||
|
.check = test__checkevent_tracepoint_multi_modifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "r1:kp",
|
||||||
|
.check = test__checkevent_raw_modifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "1:1:hp",
|
||||||
|
.check = test__checkevent_numeric_modifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "instructions:h",
|
||||||
|
.check = test__checkevent_symbolic_name_modifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "faults:u",
|
||||||
|
.check = test__checkevent_symbolic_alias_modifier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "L1-dcache-load-miss:kp",
|
||||||
|
.check = test__checkevent_genhw_modifier,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
|
#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
|
||||||
|
|
|
@ -200,6 +200,7 @@ struct perf_record_opts {
|
||||||
bool sample_time;
|
bool sample_time;
|
||||||
bool sample_id_all_avail;
|
bool sample_id_all_avail;
|
||||||
bool system_wide;
|
bool system_wide;
|
||||||
|
bool period;
|
||||||
unsigned int freq;
|
unsigned int freq;
|
||||||
unsigned int mmap_pages;
|
unsigned int mmap_pages;
|
||||||
unsigned int user_freq;
|
unsigned int user_freq;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* GIT - The information manager from hell
|
* config.c
|
||||||
|
*
|
||||||
|
* Helper functions for parsing config items.
|
||||||
|
* Originally copied from GIT source.
|
||||||
*
|
*
|
||||||
* Copyright (C) Linus Torvalds, 2005
|
* Copyright (C) Linus Torvalds, 2005
|
||||||
* Copyright (C) Johannes Schindelin, 2005
|
* Copyright (C) Johannes Schindelin, 2005
|
||||||
|
|
|
@ -814,13 +814,14 @@ int perf_event__preprocess_sample(const union perf_event *event,
|
||||||
al->cpu = sample->cpu;
|
al->cpu = sample->cpu;
|
||||||
|
|
||||||
if (al->map) {
|
if (al->map) {
|
||||||
|
struct dso *dso = al->map->dso;
|
||||||
|
|
||||||
if (symbol_conf.dso_list &&
|
if (symbol_conf.dso_list &&
|
||||||
(!al->map || !al->map->dso ||
|
(!dso || !(strlist__has_entry(symbol_conf.dso_list,
|
||||||
!(strlist__has_entry(symbol_conf.dso_list,
|
dso->short_name) ||
|
||||||
al->map->dso->short_name) ||
|
(dso->short_name != dso->long_name &&
|
||||||
(al->map->dso->short_name != al->map->dso->long_name &&
|
strlist__has_entry(symbol_conf.dso_list,
|
||||||
strlist__has_entry(symbol_conf.dso_list,
|
dso->long_name)))))
|
||||||
al->map->dso->long_name)))))
|
|
||||||
goto out_filtered;
|
goto out_filtered;
|
||||||
|
|
||||||
al->sym = map__find_symbol(al->map, al->addr, filter);
|
al->sym = map__find_symbol(al->map, al->addr, filter);
|
||||||
|
|
|
@ -447,8 +447,10 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist,
|
||||||
evlist->mmap[idx].mask = mask;
|
evlist->mmap[idx].mask = mask;
|
||||||
evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
|
evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
|
||||||
MAP_SHARED, fd, 0);
|
MAP_SHARED, fd, 0);
|
||||||
if (evlist->mmap[idx].base == MAP_FAILED)
|
if (evlist->mmap[idx].base == MAP_FAILED) {
|
||||||
|
evlist->mmap[idx].base = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
perf_evlist__add_pollfd(evlist, fd);
|
perf_evlist__add_pollfd(evlist, fd);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -108,6 +108,9 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
|
||||||
if (opts->system_wide)
|
if (opts->system_wide)
|
||||||
attr->sample_type |= PERF_SAMPLE_CPU;
|
attr->sample_type |= PERF_SAMPLE_CPU;
|
||||||
|
|
||||||
|
if (opts->period)
|
||||||
|
attr->sample_type |= PERF_SAMPLE_PERIOD;
|
||||||
|
|
||||||
if (opts->sample_id_all_avail &&
|
if (opts->sample_id_all_avail &&
|
||||||
(opts->sample_time || opts->system_wide ||
|
(opts->sample_time || opts->system_wide ||
|
||||||
!opts->no_inherit || opts->cpu_list))
|
!opts->no_inherit || opts->cpu_list))
|
||||||
|
@ -457,7 +460,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
|
||||||
u32 val32[2];
|
u32 val32[2];
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
|
memset(data, 0, sizeof(*data));
|
||||||
data->cpu = data->pid = data->tid = -1;
|
data->cpu = data->pid = data->tid = -1;
|
||||||
data->stream_id = data->id = data->time = -1ULL;
|
data->stream_id = data->id = data->time = -1ULL;
|
||||||
|
|
||||||
|
|
|
@ -1757,7 +1757,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
/*sshfs might return bad dent->d_type, so we have to stat*/
|
/*sshfs might return bad dent->d_type, so we have to stat*/
|
||||||
sprintf(path, "%s/%s", dir_name, dent->d_name);
|
snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
|
||||||
if (stat(path, &st))
|
if (stat(path, &st))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1766,8 +1766,6 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
|
||||||
!strcmp(dent->d_name, ".."))
|
!strcmp(dent->d_name, ".."))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s",
|
|
||||||
dir_name, dent->d_name);
|
|
||||||
ret = map_groups__set_modules_path_dir(mg, path);
|
ret = map_groups__set_modules_path_dir(mg, path);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1788,9 +1786,6 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
|
||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%s",
|
|
||||||
dir_name, dent->d_name);
|
|
||||||
|
|
||||||
long_name = strdup(path);
|
long_name = strdup(path);
|
||||||
if (long_name == NULL) {
|
if (long_name == NULL) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -2609,10 +2604,10 @@ int symbol__init(void)
|
||||||
symbol_conf.initialized = true;
|
symbol_conf.initialized = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_free_dso_list:
|
|
||||||
strlist__delete(symbol_conf.dso_list);
|
|
||||||
out_free_comm_list:
|
out_free_comm_list:
|
||||||
strlist__delete(symbol_conf.comm_list);
|
strlist__delete(symbol_conf.comm_list);
|
||||||
|
out_free_dso_list:
|
||||||
|
strlist__delete(symbol_conf.dso_list);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* GIT - The information manager from hell
|
* usage.c
|
||||||
|
*
|
||||||
|
* Various reporting routines.
|
||||||
|
* Originally copied from GIT source.
|
||||||
*
|
*
|
||||||
* Copyright (C) Linus Torvalds, 2005
|
* Copyright (C) Linus Torvalds, 2005
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -32,6 +32,7 @@ void perf_read_values_destroy(struct perf_read_values *values)
|
||||||
|
|
||||||
for (i = 0; i < values->threads; i++)
|
for (i = 0; i < values->threads; i++)
|
||||||
free(values->value[i]);
|
free(values->value[i]);
|
||||||
|
free(values->value);
|
||||||
free(values->pid);
|
free(values->pid);
|
||||||
free(values->tid);
|
free(values->tid);
|
||||||
free(values->counterrawid);
|
free(values->counterrawid);
|
||||||
|
|
Loading…
Add table
Reference in a new issue