Skip to content

Commit

Permalink
perf session: Move kmaps to perf_session
Browse files Browse the repository at this point in the history
There is still some more work to do to disentangle map creation
from DSO loading, but this happens only for the kernel, and for
the early adopters of perf diff, where this disentanglement
matters most, we'll be testing different kernels, so no problem
here.

Further clarification: right now we create the kernel maps for
the various modules and discontiguous kernel text maps when
loading the DSO, we should do it as a two step process, first
creating the maps, for multiple mappings with the same DSO
store, then doing the dso load just once, for the first hit on
one of the maps sharing this DSO backing store.

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frédéric Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
acmel authored and Ingo Molnar committed Dec 14, 2009
1 parent b3165f4 commit 4aa6563
Show file tree
Hide file tree
Showing 18 changed files with 134 additions and 118 deletions.
2 changes: 1 addition & 1 deletion tools/perf/builtin-annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ static struct perf_event_ops event_ops = {
static int __cmd_annotate(void)
{
struct perf_session *session = perf_session__new(input_name, O_RDONLY,
force);
force, &symbol_conf);
int ret;

if (session == NULL)
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-buildid-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ static int perf_file_section__process_buildids(struct perf_file_section *self,
static int __cmd_buildid_list(void)
{
int err = -1;
struct perf_session *session = perf_session__new(input_name, O_RDONLY, force);

struct perf_session *session = perf_session__new(input_name, O_RDONLY,
force, NULL);
if (session == NULL)
return -1;

Expand Down
41 changes: 19 additions & 22 deletions tools/perf/builtin-kmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,19 +364,6 @@ static struct perf_event_ops event_ops = {
.sample_type_check = sample_type_check,
};

static int read_events(void)
{
int err;
struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);

if (session == NULL)
return -ENOMEM;

err = perf_session__process_events(session, &event_ops);
perf_session__delete(session);
return err;
}

static double fragmentation(unsigned long n_req, unsigned long n_alloc)
{
if (n_alloc == 0)
Expand All @@ -385,7 +372,8 @@ static double fragmentation(unsigned long n_req, unsigned long n_alloc)
return 100.0 - (100.0 * n_req / n_alloc);
}

static void __print_result(struct rb_root *root, int n_lines, int is_caller)
static void __print_result(struct rb_root *root, struct perf_session *session,
int n_lines, int is_caller)
{
struct rb_node *next;

Expand All @@ -406,7 +394,7 @@ static void __print_result(struct rb_root *root, int n_lines, int is_caller)
if (is_caller) {
addr = data->call_site;
if (!raw_ip)
sym = map_groups__find_function(kmaps, addr, NULL);
sym = map_groups__find_function(&session->kmaps, session, addr, NULL);
} else
addr = data->ptr;

Expand Down Expand Up @@ -447,12 +435,12 @@ static void print_summary(void)
printf("Cross CPU allocations: %lu/%lu\n", nr_cross_allocs, nr_allocs);
}

static void print_result(void)
static void print_result(struct perf_session *session)
{
if (caller_flag)
__print_result(&root_caller_sorted, caller_lines, 1);
__print_result(&root_caller_sorted, session, caller_lines, 1);
if (alloc_flag)
__print_result(&root_alloc_sorted, alloc_lines, 0);
__print_result(&root_alloc_sorted, session, alloc_lines, 0);
print_summary();
}

Expand Down Expand Up @@ -520,12 +508,21 @@ static void sort_result(void)

static int __cmd_kmem(void)
{
int err;
struct perf_session *session = perf_session__new(input_name, O_RDONLY,
0, NULL);
if (session == NULL)
return -ENOMEM;

setup_pager();
read_events();
err = perf_session__process_events(session, &event_ops);
if (err != 0)
goto out_delete;
sort_result();
print_result();

return 0;
print_result(session);
out_delete:
perf_session__delete(session);
return err;
}

static const char * const kmem_usage[] = {
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ static int __cmd_record(int argc, const char **argv)
exit(-1);
}

session = perf_session__new(output_name, O_WRONLY, force);
session = perf_session__new(output_name, O_WRONLY, force, NULL);
if (session == NULL) {
pr_err("Not enough memory for reading perf file header\n");
return -1;
Expand Down
14 changes: 8 additions & 6 deletions tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,7 @@ static int call__match(struct symbol *sym)
}

static struct symbol **resolve_callchain(struct thread *thread,
struct perf_session *session,
struct ip_callchain *chain,
struct symbol **parent)
{
Expand Down Expand Up @@ -447,8 +448,8 @@ static struct symbol **resolve_callchain(struct thread *thread,
continue;
}

thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
ip, &al, NULL);
thread__find_addr_location(thread, session, cpumode,
MAP__FUNCTION, ip, &al, NULL);
if (al.sym != NULL) {
if (sort__has_parent && !*parent &&
call__match(al.sym))
Expand All @@ -467,14 +468,15 @@ static struct symbol **resolve_callchain(struct thread *thread,
*/

static int hist_entry__add(struct addr_location *al,
struct perf_session *session,
struct ip_callchain *chain, u64 count)
{
struct symbol **syms = NULL, *parent = NULL;
bool hit;
struct hist_entry *he;

if ((sort__has_parent || callchain) && chain)
syms = resolve_callchain(al->thread, chain, &parent);
syms = resolve_callchain(al->thread, session, chain, &parent);

he = __hist_entry__add(al, parent, count, &hit);
if (he == NULL)
Expand Down Expand Up @@ -650,7 +652,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)

cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

thread__find_addr_location(thread, cpumode,
thread__find_addr_location(thread, session, cpumode,
MAP__FUNCTION, data.ip, &al, NULL);
/*
* We have to do this here as we may have a dso with no symbol hit that
Expand All @@ -669,7 +671,7 @@ static int process_sample_event(event_t *event, struct perf_session *session)
if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name))
return 0;

if (hist_entry__add(&al, data.callchain, data.period)) {
if (hist_entry__add(&al, session, data.callchain, data.period)) {
pr_debug("problem incrementing symbol count, skipping event\n");
return -1;
}
Expand Down Expand Up @@ -763,7 +765,7 @@ static int __cmd_report(void)
int ret;
struct perf_session *session;

session = perf_session__new(input_name, O_RDONLY, force);
session = perf_session__new(input_name, O_RDONLY, force, &symbol_conf);
if (session == NULL)
return -ENOMEM;

Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -1679,8 +1679,8 @@ static struct perf_event_ops event_ops = {
static int read_events(void)
{
int err;
struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);

struct perf_session *session = perf_session__new(input_name, O_RDONLY,
0, NULL);
if (session == NULL)
return -ENOMEM;

Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-timechart.c
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,8 @@ static struct perf_event_ops event_ops = {

static int __cmd_timechart(void)
{
struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0);
struct perf_session *session = perf_session__new(input_name, O_RDONLY,
0, NULL);
int ret;

if (session == NULL)
Expand Down
4 changes: 2 additions & 2 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,8 +1162,8 @@ static int __cmd_top(void)
* FIXME: perf_session__new should allow passing a O_MMAP, so that all this
* mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
*/
struct perf_session *session = perf_session__new(NULL, O_WRONLY, false);

struct perf_session *session = perf_session__new(NULL, O_WRONLY, false,
&symbol_conf);
if (session == NULL)
return -ENOMEM;

Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)

setup_pager();

session = perf_session__new(input_name, O_RDONLY, 0);
session = perf_session__new(input_name, O_RDONLY, 0, NULL);
if (session == NULL)
return -ENOMEM;

Expand Down
13 changes: 7 additions & 6 deletions tools/perf/util/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ int event__process_task(event_t *self, struct perf_session *session)
return 0;
}

void thread__find_addr_location(struct thread *self, u8 cpumode,
void thread__find_addr_location(struct thread *self,
struct perf_session *session, u8 cpumode,
enum map_type type, u64 addr,
struct addr_location *al,
symbol_filter_t filter)
Expand All @@ -268,7 +269,7 @@ void thread__find_addr_location(struct thread *self, u8 cpumode,

if (cpumode & PERF_RECORD_MISC_KERNEL) {
al->level = 'k';
mg = kmaps;
mg = &session->kmaps;
} else if (cpumode & PERF_RECORD_MISC_USER)
al->level = '.';
else {
Expand All @@ -289,14 +290,14 @@ void thread__find_addr_location(struct thread *self, u8 cpumode,
* "[vdso]" dso, but for now lets use the old trick of looking
* in the whole kernel symbol list.
*/
if ((long long)al->addr < 0 && mg != kmaps) {
mg = kmaps;
if ((long long)al->addr < 0 && mg != &session->kmaps) {
mg = &session->kmaps;
goto try_again;
}
al->sym = NULL;
} else {
al->addr = al->map->map_ip(al->map, al->addr);
al->sym = map__find_symbol(al->map, al->addr, filter);
al->sym = map__find_symbol(al->map, session, al->addr, filter);
}
}

Expand All @@ -311,7 +312,7 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,

dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);

thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
thread__find_addr_location(thread, session, cpumode, MAP__FUNCTION,
self->ip.ip, al, filter);
dump_printf(" ...... dso: %s\n",
al->map ? al->map->dso->long_name :
Expand Down
10 changes: 6 additions & 4 deletions tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,17 @@ void map__delete(struct map *self);
struct map *map__clone(struct map *self);
int map__overlap(struct map *l, struct map *r);
size_t map__fprintf(struct map *self, FILE *fp);
struct symbol *map__find_symbol(struct map *self, u64 addr,
symbol_filter_t filter);

struct perf_session;

struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
u64 addr, symbol_filter_t filter);
struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
struct perf_session *session,
symbol_filter_t filter);
void map__fixup_start(struct map *self);
void map__fixup_end(struct map *self);

struct perf_session;

int event__synthesize_thread(pid_t pid,
int (*process)(event_t *event,
struct perf_session *session),
Expand Down
14 changes: 8 additions & 6 deletions tools/perf/util/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ void map__fixup_end(struct map *self)

#define DSO__DELETED "(deleted)"

static int map__load(struct map *self, symbol_filter_t filter)
static int map__load(struct map *self, struct perf_session *session,
symbol_filter_t filter)
{
const char *name = self->dso->long_name;
int nr = dso__load(self->dso, self, filter);
int nr = dso__load(self->dso, self, session, filter);

if (nr < 0) {
if (self->dso->has_build_id) {
Expand Down Expand Up @@ -143,19 +144,20 @@ static int map__load(struct map *self, symbol_filter_t filter)
return 0;
}

struct symbol *map__find_symbol(struct map *self, u64 addr,
symbol_filter_t filter)
struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
u64 addr, symbol_filter_t filter)
{
if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
if (!dso__loaded(self->dso, self->type) && map__load(self, session, filter) < 0)
return NULL;

return dso__find_symbol(self->dso, self->type, addr);
}

struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
struct perf_session *session,
symbol_filter_t filter)
{
if (!dso__loaded(self->dso, self->type) && map__load(self, filter) < 0)
if (!dso__loaded(self->dso, self->type) && map__load(self, session, filter) < 0)
return NULL;

if (!dso__sorted_by_name(self->dso, self->type))
Expand Down
19 changes: 12 additions & 7 deletions tools/perf/util/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static int perf_session__open(struct perf_session *self, bool force)
}

struct perf_session *perf_session__new(const char *filename, int mode,
bool force)
bool force, struct symbol_conf *conf)
{
size_t len = filename ? strlen(filename) + 1 : 0;
struct perf_session *self = zalloc(sizeof(*self) + len);
Expand All @@ -58,24 +58,29 @@ struct perf_session *perf_session__new(const char *filename, int mode,
goto out;

if (perf_header__init(&self->header) < 0)
goto out_delete;
goto out_free;

memcpy(self->filename, filename, len);
self->threads = RB_ROOT;
self->last_match = NULL;
self->mmap_window = 32;
self->cwd = NULL;
self->cwdlen = 0;
map_groups__init(&self->kmaps);

if (mode == O_RDONLY && perf_session__open(self, force) < 0) {
perf_session__delete(self);
self = NULL;
}
if (perf_session__create_kernel_maps(self, conf) < 0)
goto out_delete;

if (mode == O_RDONLY && perf_session__open(self, force) < 0)
goto out_delete;
out:
return self;
out_delete:
out_free:
free(self);
return NULL;
out_delete:
perf_session__delete(self);
return NULL;
}

void perf_session__delete(struct perf_session *self)
Expand Down
6 changes: 5 additions & 1 deletion tools/perf/util/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,23 @@

#include "event.h"
#include "header.h"
#include "thread.h"
#include <linux/rbtree.h>

struct thread;
struct symbol_conf;

struct perf_session {
struct perf_header header;
unsigned long size;
unsigned long mmap_window;
struct map_groups kmaps;
struct rb_root threads;
struct thread *last_match;
int fd;
int cwdlen;
char *cwd;
bool use_modules;
char filename[0];
};

Expand All @@ -37,7 +41,7 @@ struct perf_event_ops {
};

struct perf_session *perf_session__new(const char *filename, int mode,
bool force);
bool force, struct symbol_conf *conf);
void perf_session__delete(struct perf_session *self);

int perf_session__process_events(struct perf_session *self,
Expand Down
Loading

0 comments on commit 4aa6563

Please sign in to comment.