From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759108AbeAIPgt (ORCPT + 1 other); Tue, 9 Jan 2018 10:36:49 -0500 Received: from mx1.redhat.com ([209.132.183.28]:62387 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1759090AbeAIPgs (ORCPT ); Tue, 9 Jan 2018 10:36:48 -0500 From: Jiri Olsa To: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker , lkml , Ingo Molnar , Namhyung Kim , David Ahern , Andi Kleen , Alexander Shishkin , Peter Zijlstra Subject: [PATCH 22/49] perf tools: Introduce thread__find_addr_location_by_time() and friends Date: Tue, 9 Jan 2018 16:34:55 +0100 Message-Id: <20180109153522.14116-23-jolsa@kernel.org> In-Reply-To: <20180109153522.14116-1-jolsa@kernel.org> References: <20180109153522.14116-1-jolsa@kernel.org> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 09 Jan 2018 15:36:48 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: From: Namhyung Kim These new functions are for find appropriate map (and symbol) at the given time when used with an indexed data file. This is based on the fact that map_groups list is sorted by time in the previous patch. Cc: Frederic Weisbecker Link: http://lkml.kernel.org/n/tip-dg807z4umbjfq0yk2e3vixaj@git.kernel.org Signed-off-by: Namhyung Kim Signed-off-by: Jiri Olsa --- tools/perf/util/event.c | 58 +++++++++++++++++++++++++++++++++++++++-------- tools/perf/util/machine.c | 24 ++++++++++++-------- tools/perf/util/thread.c | 26 +++++++++++++++++++++ tools/perf/util/thread.h | 11 +++++++++ 4 files changed, 101 insertions(+), 18 deletions(-) diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 79cc3c34cde2..00e46ab1e432 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -1491,16 +1491,14 @@ int perf_event__process(struct perf_tool *tool __maybe_unused, return machine__process_event(machine, event, sample); } -void thread__find_addr_map(struct thread *thread, u8 cpumode, - enum map_type type, u64 addr, - struct addr_location *al) +static void map_groups__find_addr_map(struct map_groups *mg, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al) { - struct map_groups *mg = thread->mg; struct machine *machine = mg->machine; bool load_map = false; al->machine = machine; - al->thread = thread; al->addr = addr; al->cpumode = cpumode; al->filtered = 0; @@ -1569,6 +1567,29 @@ void thread__find_addr_map(struct thread *thread, u8 cpumode, } } +void thread__find_addr_map(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al) +{ + al->thread = thread; + map_groups__find_addr_map(thread->mg, cpumode, type, addr, al); +} + +void thread__find_addr_map_by_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp) +{ + struct map_groups *mg; + + if (perf_has_index) + mg = thread__get_map_groups(thread, timestamp); + else + mg = thread->mg; + + al->thread = thread; + map_groups__find_addr_map(mg, cpumode, type, addr, al); +} + void thread__find_addr_location(struct thread *thread, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al) @@ -1580,6 +1601,22 @@ void thread__find_addr_location(struct thread *thread, al->sym = NULL; } +void thread__find_addr_location_by_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp) +{ + if (perf_has_index) + thread__find_addr_map_by_time(thread, cpumode, type, addr, al, + timestamp); + else + thread__find_addr_map(thread, cpumode, type, addr, al); + + if (al->map != NULL) + al->sym = map__find_symbol(al->map, al->addr); + else + al->sym = NULL; +} + /* * Callers need to drop the reference to al->thread, obtained in * machine__findnew_thread() @@ -1606,7 +1643,9 @@ int machine__resolve(struct machine *machine, struct addr_location *al, machine__kernel_map(machine) == NULL) machine__create_kernel_maps(machine); - thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al); + thread__find_addr_map_by_time(thread, sample->cpumode, MAP__FUNCTION, + sample->ip, al, sample->time); + dump_printf(" ...... dso: %s\n", al->map ? al->map->dso->long_name : al->level == 'H' ? "[hypervisor]" : ""); @@ -1685,10 +1724,11 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr) void thread__resolve(struct thread *thread, struct addr_location *al, struct perf_sample *sample) { - thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->addr, al); + thread__find_addr_map_by_time(thread, sample->cpumode, MAP__FUNCTION, + sample->addr, al, sample->time); if (!al->map) - thread__find_addr_map(thread, sample->cpumode, MAP__VARIABLE, - sample->addr, al); + thread__find_addr_map_by_time(thread, sample->cpumode, MAP__VARIABLE, + sample->addr, al, sample->time); al->cpu = sample->cpu; al->sym = NULL; diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 6349ea11753b..b6fbb302b4e0 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1850,7 +1850,7 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex) static void ip__resolve_ams(struct thread *thread, struct addr_map_symbol *ams, - u64 ip) + u64 ip, u64 timestamp) { struct addr_location al; @@ -1862,7 +1862,8 @@ static void ip__resolve_ams(struct thread *thread, * Thus, we have to try consecutively until we find a match * or else, the symbol is unknown */ - thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al); + thread__find_cpumode_addr_location_by_time(thread, MAP__FUNCTION, + ip, &al, timestamp); ams->addr = ip; ams->al_addr = al.addr; @@ -1873,20 +1874,23 @@ static void ip__resolve_ams(struct thread *thread, static void ip__resolve_data(struct thread *thread, u8 m, struct addr_map_symbol *ams, - u64 addr, u64 phys_addr) + u64 addr, u64 phys_addr, u64 timestamp) { struct addr_location al; memset(&al, 0, sizeof(al)); - thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al); + thread__find_addr_location_by_time(thread, m, MAP__VARIABLE, + addr, &al, timestamp); + if (al.map == NULL) { /* * some shared data regions have execute bit set which puts * their mapping in the MAP__FUNCTION type array. * Check there as a fallback option before dropping the sample. */ - thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al); + thread__find_addr_location_by_time(thread, m, MAP__FUNCTION, + addr, &al, timestamp); } ams->addr = addr; @@ -1904,9 +1908,9 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, if (!mi) return NULL; - ip__resolve_ams(al->thread, &mi->iaddr, sample->ip); + ip__resolve_ams(al->thread, &mi->iaddr, sample->ip, sample->time); ip__resolve_data(al->thread, al->cpumode, &mi->daddr, - sample->addr, sample->phys_addr); + sample->addr, sample->phys_addr, sample->time); mi->data_src.val = sample->data_src; return mi; @@ -2024,8 +2028,10 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, return NULL; for (i = 0; i < bs->nr; i++) { - ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to); - ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from); + ip__resolve_ams(al->thread, &bi[i].to, + bs->entries[i].to, sample->time); + ip__resolve_ams(al->thread, &bi[i].from, + bs->entries[i].from, sample->time); bi[i].flags = bs->entries[i].flags; } return bi; diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 6ad32879440d..a05bee5b58b9 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -557,3 +557,29 @@ struct thread *thread__main_thread(struct machine *machine, struct thread *threa return machine__find_thread(machine, thread->pid_, thread->pid_); } + +void thread__find_cpumode_addr_location_by_time(struct thread *thread, + enum map_type type, u64 addr, + struct addr_location *al, + u64 timestamp) +{ + size_t i; + const u8 cpumodes[] = { + PERF_RECORD_MISC_USER, + PERF_RECORD_MISC_KERNEL, + PERF_RECORD_MISC_GUEST_USER, + PERF_RECORD_MISC_GUEST_KERNEL + }; + + if (!perf_has_index) { + thread__find_cpumode_addr_location(thread, type, addr, al); + return; + } + + for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { + thread__find_addr_location_by_time(thread, cpumodes[i], type, + addr, al, timestamp); + if (al->map) + break; + } +} diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 81995cb7102d..614e622d884f 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -101,14 +101,25 @@ struct thread *thread__main_thread(struct machine *machine, struct thread *threa void thread__find_addr_map(struct thread *thread, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al); +void thread__find_addr_map_by_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, u64 timestamp); void thread__find_addr_location(struct thread *thread, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al); +void thread__find_addr_location_by_time(struct thread *thread, u8 cpumode, + enum map_type type, u64 addr, + struct addr_location *al, + u64 timestamp); void thread__find_cpumode_addr_location(struct thread *thread, enum map_type type, u64 addr, struct addr_location *al); +void thread__find_cpumode_addr_location_by_time(struct thread *thread, + enum map_type type, u64 addr, + struct addr_location *al, + u64 timestamp); static inline void *thread__priv(struct thread *thread) { -- 2.13.6