perf/core improvements and fixes:

User visible:
 
 - Fixes and improvements for supporting annotating ARM binaries, support ARM
   call and jump instructions, more work needed to have arch specific stuff
   separated into tools/perf/arch/*/annotate/ (Russell King)
 
 - Fix several 'perf test' entries broken by recent perf/core changes (Jiri Olsa)
 
 Infrastructure:
 
 - Consolidate perf_ev{list,sel}__{enable,disable}() calls (Jiri Olsa)
 
 - Pass correct string to dso__adjust_kmod_long_name (Wang Nan)
 
 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJWZgMhAAoJENZQFvNTUqpAunUP/2x5II8HDGVTpjsV5jriyDNU
 vj1XnYaVrEoBQG2EXGRFnQYbrCogB8b5TjMWk01XibOoNPzNUJbTIfCpi0aPFNGl
 YrAUN3paz5lQliUlRV56913dnixammfjsy+c837Kk3HzaKpIdTpo1Unkz94Bjv5i
 4PVMk0YMM4fvBQF3Urg2x4BKhk7sZkDTJvuRtrCDr6WE8X2Eon7TXvYo2QEIUQ5e
 9totlruQFAvpbu08F1gd6RhqtIC3uDcJNX1eEebUJtf4EhJmTAyJ7QhtaRzcmaOk
 IusfXtCvhkLjprjOXLGt4nnhUw3Lnaxno6/Izm9eyJ2JAj8ERIfl9T7Yoc5Ab/Hc
 helKeCgaD2jJgPvldOjm4/ckKkxsxbK1oPZ5FvhKLMIz0mjKZcB5CpYxj0Zzos2g
 BjLIH9sXp9x1j8coeCRyfqOx7tMhY1vCVd4JVbl5/cIWt58+dAXJPcqxRAXUPlpt
 PN+uIaQ2IQa+K++dgQOsNDyUCRIJOvuCEYjhDkqagfccSF85K5v43HFIVS4c5Q1w
 znF9884UhiRhR5SuZqZCQUTwFOk5rsOcX8wliIJCWP2bEaMde1vaMhTAGMXe8Qk+
 6do62hAgSeUTlH2f7eMExRY8/CXQvJmu5O1ukb2mWcSJkNeL8npoCFER1W1gy9Yh
 NDU9dOoKMwOtzyI3STkg
 =CSRu
 -----END PGP SIGNATURE-----

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

User visible changes:

  - Fixes and improvements for supporting annotating ARM binaries, support ARM
    call and jump instructions, more work needed to have arch specific stuff
    separated into tools/perf/arch/*/annotate/ (Russell King)

  - Fix several 'perf test' entries broken by recent perf/core changes (Jiri Olsa)

Infrastructure changes:

  - Consolidate perf_ev{list,sel}__{enable,disable}() calls (Jiri Olsa)

  - Pass correct string to dso__adjust_kmod_long_name() (Wang Nan)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2015-12-08 05:23:09 +01:00
commit 803ca41856
11 changed files with 95 additions and 60 deletions

View File

@ -168,15 +168,25 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
attr->sample_period = 0;
attr->sample_type = 0;
if (target__has_cpu(&target))
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
if (!target__has_task(&target) && perf_evsel__is_group_leader(evsel)) {
/*
* Disabling all counters initially, they will be enabled
* either manually by us or by kernel via enable_on_exec
* set later.
*/
if (perf_evsel__is_group_leader(evsel)) {
attr->disabled = 1;
if (!initial_delay)
/*
* In case of initial_delay we enable tracee
* events manually.
*/
if (target__none(&target) && !initial_delay)
attr->enable_on_exec = 1;
}
if (target__has_cpu(&target))
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
return perf_evsel__open_per_thread(evsel, evsel_list->threads);
}
@ -251,18 +261,18 @@ static void process_interval(void)
print_counters(&rs, 0, NULL);
}
static void handle_initial_delay(void)
static void enable_counters(void)
{
struct perf_evsel *counter;
if (initial_delay) {
const int ncpus = cpu_map__nr(evsel_list->cpus),
nthreads = thread_map__nr(evsel_list->threads);
if (initial_delay)
usleep(initial_delay * 1000);
evlist__for_each(evsel_list, counter)
perf_evsel__enable(counter, ncpus, nthreads);
}
/*
* We need to enable counters only if:
* - we don't have tracee (attaching to task or cpu)
* - we have initial delay configured
*/
if (!target__none(&target) || initial_delay)
perf_evlist__enable(evsel_list);
}
static volatile int workload_exec_errno;
@ -359,7 +369,7 @@ static int __run_perf_stat(int argc, const char **argv)
if (forks) {
perf_evlist__start_workload(evsel_list);
handle_initial_delay();
enable_counters();
if (interval) {
while (!waitpid(child_pid, &status, WNOHANG)) {
@ -378,7 +388,7 @@ static int __run_perf_stat(int argc, const char **argv)
if (WIFSIGNALED(status))
psignal(WTERMSIG(status), argv[0]);
} else {
handle_initial_delay();
enable_counters();
while (!done) {
nanosleep(&ts, NULL);
if (interval)

View File

@ -433,7 +433,6 @@ enum {
static int do_test_code_reading(bool try_kcore)
{
struct machines machines;
struct machine *machine;
struct thread *thread;
struct record_opts opts = {
@ -459,8 +458,7 @@ static int do_test_code_reading(bool try_kcore)
pid = getpid();
machines__init(&machines);
machine = &machines.host;
machine = machine__new_host();
ret = machine__create_kernel_maps(machine);
if (ret < 0) {
@ -549,6 +547,13 @@ static int do_test_code_reading(bool try_kcore)
if (ret < 0) {
if (!excl_kernel) {
excl_kernel = true;
/*
* Both cpus and threads are now owned by evlist
* and will be freed by following perf_evlist__set_maps
* call. Getting refference to keep them alive.
*/
cpu_map__get(cpus);
thread_map__get(threads);
perf_evlist__set_maps(evlist, NULL, NULL);
perf_evlist__delete(evlist);
evlist = NULL;
@ -594,9 +599,8 @@ out_err:
cpu_map__put(cpus);
thread_map__put(threads);
}
machines__destroy_kernel_maps(&machines);
machine__delete_threads(machine);
machines__exit(&machines);
machine__delete(machine);
return err;
}

View File

@ -160,14 +160,11 @@ static int krava_1(struct thread *thread)
int test__dwarf_unwind(int subtest __maybe_unused)
{
struct machines machines;
struct machine *machine;
struct thread *thread;
int err = -1;
machines__init(&machines);
machine = machines__find(&machines, HOST_KERNEL_ID);
machine = machine__new_host();
if (!machine) {
pr_err("Could not get machine\n");
return -1;
@ -199,7 +196,6 @@ int test__dwarf_unwind(int subtest __maybe_unused)
out:
machine__delete_threads(machine);
machine__exit(machine);
machines__exit(&machines);
machine__delete(machine);
return err;
}

View File

@ -103,7 +103,8 @@ int test__perf_evsel__roundtrip_name_test(int subtest __maybe_unused)
if (err)
ret = err;
err = perf_evsel__name_array_test(perf_evsel__sw_names);
err = __perf_evsel__name_array_test(perf_evsel__sw_names,
PERF_COUNT_SW_DUMMY + 1);
if (err)
ret = err;

View File

@ -87,6 +87,11 @@ struct machine *setup_fake_machine(struct machines *machines)
return NULL;
}
if (machine__create_kernel_maps(machine)) {
pr_debug("Not enough memory for machine setup\n");
goto out;
}
for (i = 0; i < ARRAY_SIZE(fake_threads); i++) {
struct thread *thread;

View File

@ -149,7 +149,6 @@ static int synth_process(struct machine *machine)
static int mmap_events(synth_cb synth)
{
struct machines machines;
struct machine *machine;
int err, i;
@ -162,8 +161,7 @@ static int mmap_events(synth_cb synth)
*/
TEST_ASSERT_VAL("failed to create threads", !threads_create());
machines__init(&machines);
machine = &machines.host;
machine = machine__new_host();
dump_trace = verbose > 1 ? 1 : 0;
@ -203,7 +201,7 @@ static int mmap_events(synth_cb synth)
}
machine__delete_threads(machine);
machines__exit(&machines);
machine__delete(machine);
return err;
}

View File

@ -65,6 +65,11 @@ static int call__parse(struct ins_operands *ops)
name++;
#ifdef __arm__
if (strchr(name, '+'))
return -1;
#endif
tok = strchr(name, '>');
if (tok == NULL)
return -1;
@ -246,7 +251,11 @@ static int mov__parse(struct ins_operands *ops)
return -1;
target = ++s;
#ifdef __arm__
comment = strchr(s, ';');
#else
comment = strchr(s, '#');
#endif
if (comment != NULL)
s = comment - 1;
@ -354,6 +363,20 @@ static struct ins instructions[] = {
{ .name = "addq", .ops = &mov_ops, },
{ .name = "addw", .ops = &mov_ops, },
{ .name = "and", .ops = &mov_ops, },
#ifdef __arm__
{ .name = "b", .ops = &jump_ops, }, // might also be a call
{ .name = "bcc", .ops = &jump_ops, },
{ .name = "bcs", .ops = &jump_ops, },
{ .name = "beq", .ops = &jump_ops, },
{ .name = "bge", .ops = &jump_ops, },
{ .name = "bgt", .ops = &jump_ops, },
{ .name = "bhi", .ops = &jump_ops, },
{ .name = "bl", .ops = &call_ops, },
{ .name = "blt", .ops = &jump_ops, },
{ .name = "bls", .ops = &jump_ops, },
{ .name = "blx", .ops = &call_ops, },
{ .name = "bne", .ops = &jump_ops, },
#endif
{ .name = "bts", .ops = &mov_ops, },
{ .name = "call", .ops = &call_ops, },
{ .name = "callq", .ops = &call_ops, },

View File

@ -336,20 +336,12 @@ static int perf_evlist__nr_threads(struct perf_evlist *evlist,
void perf_evlist__disable(struct perf_evlist *evlist)
{
int cpu, thread;
struct perf_evsel *pos;
int nr_cpus = cpu_map__nr(evlist->cpus);
int nr_threads;
for (cpu = 0; cpu < nr_cpus; cpu++) {
evlist__for_each(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
nr_threads = perf_evlist__nr_threads(evlist, pos);
for (thread = 0; thread < nr_threads; thread++)
ioctl(FD(pos, cpu, thread),
PERF_EVENT_IOC_DISABLE, 0);
}
evlist__for_each(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
perf_evsel__disable(pos);
}
evlist->enabled = false;
@ -357,20 +349,12 @@ void perf_evlist__disable(struct perf_evlist *evlist)
void perf_evlist__enable(struct perf_evlist *evlist)
{
int cpu, thread;
struct perf_evsel *pos;
int nr_cpus = cpu_map__nr(evlist->cpus);
int nr_threads;
for (cpu = 0; cpu < nr_cpus; cpu++) {
evlist__for_each(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
nr_threads = perf_evlist__nr_threads(evlist, pos);
for (thread = 0; thread < nr_threads; thread++)
ioctl(FD(pos, cpu, thread),
PERF_EVENT_IOC_ENABLE, 0);
}
evlist__for_each(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
perf_evsel__enable(pos);
}
evlist->enabled = true;

View File

@ -981,13 +981,26 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
return -1;
}
int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
int perf_evsel__enable(struct perf_evsel *evsel)
{
int nthreads = thread_map__nr(evsel->threads);
int ncpus = cpu_map__nr(evsel->cpus);
return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
PERF_EVENT_IOC_ENABLE,
0);
}
int perf_evsel__disable(struct perf_evsel *evsel)
{
int nthreads = thread_map__nr(evsel->threads);
int ncpus = cpu_map__nr(evsel->cpus);
return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
PERF_EVENT_IOC_DISABLE,
0);
}
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
{
if (ncpus == 0 || nthreads == 0)

View File

@ -227,7 +227,8 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
const char *op, const char *filter);
int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);
int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads);
int perf_evsel__enable(struct perf_evsel *evsel);
int perf_evsel__disable(struct perf_evsel *evsel);
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
struct cpu_map *cpus);

View File

@ -576,7 +576,7 @@ static void dso__adjust_kmod_long_name(struct dso *dso, const char *filename)
if (!dup_filename)
return;
dso__set_long_name(dso, filename, true);
dso__set_long_name(dso, dup_filename, true);
}
struct map *machine__findnew_module_map(struct machine *machine, u64 start,