Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 25903407 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar
Browse files

perf report: Add --dsos parameter



So that we can filter by dso. Symbols in other dsos won't be
accounted for.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1246399282-20934-2-git-send-email-acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent f5812a7a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ OPTIONS
-i::
--input=::
        Input file name. (default: perf.data)
-d::
--dsos=::
	Only consider symbols in these dsos. CSV that understands
	file://filename entries.

SEE ALSO
--------
+2 −0
Original line number Diff line number Diff line
@@ -301,6 +301,7 @@ LIB_H += util/util.h
LIB_H += util/help.h
LIB_H += util/strbuf.h
LIB_H += util/string.h
LIB_H += util/strlist.h
LIB_H += util/run-command.h
LIB_H += util/sigchain.h
LIB_H += util/symbol.h
@@ -322,6 +323,7 @@ LIB_OBJS += util/run-command.o
LIB_OBJS += util/quote.o
LIB_OBJS += util/strbuf.o
LIB_OBJS += util/string.o
LIB_OBJS += util/strlist.o
LIB_OBJS += util/usage.o
LIB_OBJS += util/wrapper.o
LIB_OBJS += util/sigchain.o
+16 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include "util/symbol.h"
#include "util/string.h"
#include "util/callchain.h"
#include "util/strlist.h"

#include "perf.h"
#include "util/header.h"
@@ -32,6 +33,8 @@ static char *vmlinux = NULL;

static char		default_sort_order[] = "comm,dso";
static char		*sort_order = default_sort_order;
static char		*dso_list_str;
static struct strlist	*dso_list;

static int		input;
static int		show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
@@ -1272,6 +1275,9 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
	if (show & show_mask) {
		struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip);

		if (dso_list && dso && dso->name && !strlist__has_entry(dso_list, dso->name))
			return 0;

		if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) {
			eprintf("problem incrementing symbol count, skipping event\n");
			return -1;
@@ -1659,6 +1665,8 @@ static const struct option options[] = {
	OPT_BOOLEAN('x', "exclude-other", &exclude_other,
		    "Only display entries with parent-match"),
	OPT_BOOLEAN('c', "callchain", &callchain, "Display callchains"),
	OPT_STRING('d', "dsos", &dso_list_str, "dso[,dso...]",
		   "only consider symbols in these dsos"),
	OPT_END()
};

@@ -1698,6 +1706,14 @@ int cmd_report(int argc, const char **argv, const char *prefix)
	if (argc)
		usage_with_options(report_usage, options);

	if (dso_list_str) {
		dso_list = strlist__new(true, dso_list_str);
		if (!dso_list) {
			fprintf(stderr, "problems parsing dso list\n");
			exit(129);
		}
	}

	setup_pager();

	return __cmd_report();
+184 −0
Original line number Diff line number Diff line
/*
 * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
 *
 * Licensed under the GPLv2.
 */

#include "strlist.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static struct str_node *str_node__new(const char *s, bool dupstr)
{
	struct str_node *self = malloc(sizeof(*self));

	if (self != NULL) {
		if (dupstr) {
			s = strdup(s);
			if (s == NULL)
				goto out_delete;
		}
		self->s = s;
	}

	return self;

out_delete:
	free(self);
	return NULL;
}

static void str_node__delete(struct str_node *self, bool dupstr)
{
	if (dupstr)
		free((void *)self->s);
	free(self);
}

int strlist__add(struct strlist *self, const char *new_entry)
{
	struct rb_node **p = &self->entries.rb_node;
	struct rb_node *parent = NULL;
	struct str_node *sn;

	while (*p != NULL) {
		int rc;

		parent = *p;
		sn = rb_entry(parent, struct str_node, rb_node);
		rc = strcmp(sn->s, new_entry);

		if (rc > 0)
			p = &(*p)->rb_left;
		else if (rc < 0)
			p = &(*p)->rb_right;
		else
			return -EEXIST;
	}

	sn = str_node__new(new_entry, self->dupstr);
	if (sn == NULL)
		return -ENOMEM;

	rb_link_node(&sn->rb_node, parent, p);
	rb_insert_color(&sn->rb_node, &self->entries);

	return 0;
}

int strlist__load(struct strlist *self, const char *filename)
{
	char entry[1024];
	int err;
	FILE *fp = fopen(filename, "r");

	if (fp == NULL)
		return errno;

	while (fgets(entry, sizeof(entry), fp) != NULL) {
		const size_t len = strlen(entry);

		if (len == 0)
			continue;
		entry[len - 1] = '\0';

		err = strlist__add(self, entry);
		if (err != 0)
			goto out;
	}

	err = 0;
out:
	fclose(fp);
	return err;
}

void strlist__remove(struct strlist *self, struct str_node *sn)
{
	rb_erase(&sn->rb_node, &self->entries);
	str_node__delete(sn, self->dupstr);
}

bool strlist__has_entry(struct strlist *self, const char *entry)
{
	struct rb_node **p = &self->entries.rb_node;
	struct rb_node *parent = NULL;

	while (*p != NULL) {
		struct str_node *sn;
		int rc;

		parent = *p;
		sn = rb_entry(parent, struct str_node, rb_node);
		rc = strcmp(sn->s, entry);

		if (rc > 0)
			p = &(*p)->rb_left;
		else if (rc < 0)
			p = &(*p)->rb_right;
		else
			return true;
	}

	return false;
}

static int strlist__parse_list_entry(struct strlist *self, const char *s)
{
	if (strncmp(s, "file://", 7) == 0)
		return strlist__load(self, s + 7);

	return strlist__add(self, s);
}

int strlist__parse_list(struct strlist *self, const char *s)
{
	char *sep;
	int err;

	while ((sep = strchr(s, ',')) != NULL) {
		*sep = '\0';
		err = strlist__parse_list_entry(self, s);
		*sep = ',';
		if (err != 0)
			return err;
		s = sep + 1;
	}

	return *s ? strlist__parse_list_entry(self, s) : 0;
}

struct strlist *strlist__new(bool dupstr, const char *slist)
{
	struct strlist *self = malloc(sizeof(*self));

	if (self != NULL) {
		self->entries = RB_ROOT;
		self->dupstr = dupstr;
		if (slist && strlist__parse_list(self, slist) != 0)
			goto out_error;
	}

	return self;
out_error:
	free(self);
	return NULL;
}

void strlist__delete(struct strlist *self)
{
	if (self != NULL) {
		struct str_node *pos;
		struct rb_node *next = rb_first(&self->entries);

		while (next) {
			pos = rb_entry(next, struct str_node, rb_node);
			next = rb_next(&pos->rb_node);
			strlist__remove(self, pos);
		}
		self->entries = RB_ROOT;
		free(self);
	}
}
+32 −0
Original line number Diff line number Diff line
#ifndef STRLIST_H_
#define STRLIST_H_

#include "rbtree.h"
#include <stdbool.h>

struct str_node {
	struct rb_node rb_node;
	const char     *s;
};

struct strlist {
	struct rb_root entries;
	bool dupstr;
};

struct strlist *strlist__new(bool dupstr, const char *slist);
void strlist__delete(struct strlist *self);

void strlist__remove(struct strlist *self, struct str_node *sn);
int strlist__load(struct strlist *self, const char *filename);
int strlist__add(struct strlist *self, const char *str);

bool strlist__has_entry(struct strlist *self, const char *entry);

static inline bool strlist__empty(const struct strlist *self)
{
	return rb_first(&self->entries) == NULL;
}

int strlist__parse_list(struct strlist *self, const char *s);
#endif /* STRLIST_H_ */