lkml.org 
[lkml]   [2015]   [Mar]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 21/38] perf tools: Introduce session__find_addr_location() and friends
Date
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 <fweisbec@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/event.c | 57 ++++++++++++++++++++++++++++++++++++++---------
tools/perf/util/hist.c | 4 ++--
tools/perf/util/machine.c | 37 ++++++++++++++++++++----------
tools/perf/util/machine.h | 2 ++
tools/perf/util/session.h | 38 +++++++++++++++++++++++++++++++
tools/perf/util/thread.c | 21 +++++++++++++++++
tools/perf/util/thread.h | 10 +++++++++
7 files changed, 145 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 8d4a5cb829d0..5abf7086c97c 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -746,16 +746,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;
@@ -824,6 +822,26 @@ 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_time(struct thread *thread, u8 cpumode,
+ enum map_type type, u64 addr,
+ struct addr_location *al, u64 timestamp)
+{
+ struct map_groups *mg;
+
+ mg = thread__get_map_groups(thread, timestamp);
+
+ 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)
@@ -836,6 +854,21 @@ void thread__find_addr_location(struct thread *thread,
al->sym = NULL;
}

+void thread__find_addr_location_time(struct thread *thread, u8 cpumode,
+ enum map_type type, u64 addr,
+ struct addr_location *al, u64 timestamp)
+{
+ struct map_groups *mg;
+
+ mg = thread__get_map_groups(thread, timestamp);
+ map_groups__find_addr_map(mg, cpumode, type, addr, al);
+ if (al->map != NULL)
+ al->sym = map__find_symbol(al->map, al->addr,
+ mg->machine->symbol_filter);
+ else
+ al->sym = NULL;
+}
+
int perf_event__preprocess_sample(const union perf_event *event,
struct machine *machine,
struct addr_location *al,
@@ -868,7 +901,9 @@ int perf_event__preprocess_sample(const union perf_event *event,
machine->vmlinux_maps[MAP__FUNCTION] == NULL)
machine__create_kernel_maps(machine);

- thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
+ session__find_addr_map(session, thread, cpumode, MAP__FUNCTION,
+ sample->ip, al, sample->time);
+
dump_printf(" ...... dso: %s\n",
al->map ? al->map->dso->long_name :
al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -929,14 +964,16 @@ void perf_event__preprocess_sample_addr(union perf_event *event,
struct perf_sample *sample,
struct thread *thread,
struct addr_location *al,
- struct perf_session *session __maybe_unused)
+ struct perf_session *session)
{
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

- thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
+ session__find_addr_map(session, thread, cpumode, MAP__FUNCTION,
+ sample->addr, al, sample->time);
+
if (!al->map)
- thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
- sample->addr, al);
+ session__find_addr_map(session, thread, cpumode, MAP__VARIABLE,
+ sample->addr, al, sample->time);

al->cpu = sample->cpu;
al->sym = NULL;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 0553a14a80a4..0d189ae76922 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -496,7 +496,7 @@ iter_prepare_mem_entry(struct hist_entry_iter *iter, struct addr_location *al)
struct perf_sample *sample = iter->sample;
struct mem_info *mi;

- mi = sample__resolve_mem(sample, al);
+ mi = sample__resolve_mem(sample, iter->session, al);
if (mi == NULL)
return -ENOMEM;

@@ -570,7 +570,7 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al
struct branch_info *bi;
struct perf_sample *sample = iter->sample;

- bi = sample__resolve_bstack(sample, al);
+ bi = sample__resolve_bstack(sample, iter->session, al);
if (!bi)
return -ENOMEM;

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b14e4dc5261d..4743718d4bf1 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -8,6 +8,7 @@
#include "sort.h"
#include "strlist.h"
#include "thread.h"
+#include "session.h"
#include "vdso.h"
#include <stdbool.h>
#include <symbol/kallsyms.h>
@@ -1469,9 +1470,10 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
return 0;
}

-static void ip__resolve_ams(struct thread *thread,
+static void ip__resolve_ams(struct perf_session *session,
+ struct thread *thread,
struct addr_map_symbol *ams,
- u64 ip)
+ u64 ip, u64 timestamp)
{
struct addr_location al;

@@ -1483,7 +1485,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);
+ session__find_cpumode_addr_location(session, thread, MAP__FUNCTION,
+ ip, &al, timestamp);

ams->addr = ip;
ams->al_addr = al.addr;
@@ -1491,21 +1494,25 @@ static void ip__resolve_ams(struct thread *thread,
ams->map = al.map;
}

-static void ip__resolve_data(struct thread *thread,
- u8 m, struct addr_map_symbol *ams, u64 addr)
+static void ip__resolve_data(struct perf_session *session,
+ struct thread *thread, u8 m,
+ struct addr_map_symbol *ams,
+ u64 addr, u64 timestamp)
{
struct addr_location al;

memset(&al, 0, sizeof(al));

- thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al);
+ session__find_addr_location(session, 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);
+ session__find_addr_location(session, thread, m, MAP__FUNCTION,
+ addr, &al, timestamp);
}

ams->addr = addr;
@@ -1515,6 +1522,7 @@ static void ip__resolve_data(struct thread *thread,
}

struct mem_info *sample__resolve_mem(struct perf_sample *sample,
+ struct perf_session *session,
struct addr_location *al)
{
struct mem_info *mi = zalloc(sizeof(*mi));
@@ -1522,8 +1530,10 @@ 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_data(al->thread, al->cpumode, &mi->daddr, sample->addr);
+ ip__resolve_ams(session, al->thread, &mi->iaddr, sample->ip,
+ sample->time);
+ ip__resolve_data(session, al->thread, al->cpumode, &mi->daddr,
+ sample->addr, sample->time);
mi->data_src.val = sample->data_src;

return mi;
@@ -1539,6 +1549,7 @@ static int add_callchain_ip(struct thread *thread,

al.filtered = 0;
al.sym = NULL;
+
if (branch_history)
thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
ip, &al);
@@ -1589,6 +1600,7 @@ static int add_callchain_ip(struct thread *thread,
}

struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
+ struct perf_session *session,
struct addr_location *al)
{
unsigned int i;
@@ -1599,8 +1611,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(session, al->thread, &bi[i].to,
+ bs->entries[i].to, sample->time);
+ ip__resolve_ams(session, al->thread, &bi[i].from,
+ bs->entries[i].from, sample->time);
bi[i].flags = bs->entries[i].flags;
}
return bi;
@@ -1826,7 +1840,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
ip = chain->ips[j];

err = add_callchain_ip(thread, parent, root_al, false, ip);
-
if (err)
return (err < 0) ? err : 0;
}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 9571b6b1c5b5..45aee0c329ef 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -121,8 +121,10 @@ void machine__delete_threads(struct machine *machine);
void machine__delete(struct machine *machine);

struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
+ struct perf_session *session,
struct addr_location *al);
struct mem_info *sample__resolve_mem(struct perf_sample *sample,
+ struct perf_session *session,
struct addr_location *al);
int thread__resolve_callchain(struct thread *thread,
struct perf_evsel *evsel,
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index aff0d2b4cc0b..dbd21f8e7cf1 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -142,4 +142,42 @@ static inline bool perf_session__has_index(struct perf_session *session)
return perf_header__has_feat(&session->header, HEADER_DATA_INDEX);
}

+static inline void
+session__find_addr_map(struct perf_session *session, struct thread *thread,
+ u8 cpumode, enum map_type type, u64 addr,
+ struct addr_location *al, u64 timestamp)
+{
+ if (session && perf_session__has_index(session))
+ thread__find_addr_map_time(thread, cpumode, type, addr, al,
+ timestamp);
+ else
+ thread__find_addr_map(thread, cpumode, type, addr, al);
+}
+
+static inline void
+session__find_addr_location(struct perf_session *session, struct thread *thread,
+ u8 cpumode, enum map_type type, u64 addr,
+ struct addr_location *al, u64 timestamp)
+{
+ if (session && perf_session__has_index(session))
+ thread__find_addr_location_time(thread, cpumode, type, addr, al,
+ timestamp);
+ else
+ thread__find_addr_location(thread, cpumode, type, addr, al);
+}
+
+static inline void
+session__find_cpumode_addr_location(struct perf_session *session,
+ struct thread *thread, enum map_type type,
+ u64 addr, struct addr_location *al,
+ u64 timestamp)
+{
+ if (session && perf_session__has_index(session))
+ thread__find_cpumode_addr_location_time(thread, type, addr, al,
+ timestamp);
+ else
+ thread__find_cpumode_addr_location(thread, type, addr, al);
+}
+
+
#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 7b01c171dcfa..9ae1ce8606af 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -359,3 +359,24 @@ void thread__find_cpumode_addr_location(struct thread *thread,
break;
}
}
+
+void thread__find_cpumode_addr_location_time(struct thread *thread,
+ enum map_type type, u64 addr,
+ struct addr_location *al,
+ u64 timestamp)
+{
+ size_t i;
+ const u8 const cpumodes[] = {
+ PERF_RECORD_MISC_USER,
+ PERF_RECORD_MISC_KERNEL,
+ PERF_RECORD_MISC_GUEST_USER,
+ PERF_RECORD_MISC_GUEST_KERNEL
+ };
+
+ for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
+ thread__find_addr_location_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 08cafa2d97f9..5209ad5adadf 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -66,14 +66,24 @@ size_t thread__fprintf(struct thread *thread, FILE *fp);
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_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_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_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.2.2


\
 
 \ /
  Last update: 2015-03-03 04:41    [W:0.214 / U:0.148 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site