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

Commit e66b688c authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
parents a7c55cbe 71e7cf3a
Loading
Loading
Loading
Loading
+29 −2
Original line number Diff line number Diff line
@@ -348,7 +348,18 @@ static int __cmd_report(void)
		hists__tty_browse_tree(&session->hists_tree, help);

out_delete:
	perf_session__delete(session);
	/*
	 * Speed up the exit process, for large files this can
	 * take quite a while.
	 *
	 * XXX Enable this when using valgrind or if we ever
	 * librarize this command.
	 *
	 * Also experiment with obstacks to see how much speed
	 * up we'll get here.
	 *
 	 * perf_session__delete(session);
 	 */
	return ret;
}

@@ -478,8 +489,24 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
	 * so don't allocate extra space that won't be used in the stdio
	 * implementation.
	 */
	if (use_browser > 0)
	if (use_browser > 0) {
		symbol_conf.priv_size = sizeof(struct sym_priv);
		/*
 		 * For searching by name on the "Browse map details".
 		 * providing it only in verbose mode not to bloat too
 		 * much struct symbol.
 		 */
		if (verbose) {
			/*
			 * XXX: Need to provide a less kludgy way to ask for
			 * more space per symbol, the u32 is for the index on
			 * the ui browser.
			 * See symbol__browser_index.
			 */
			symbol_conf.priv_size += sizeof(u32);
			symbol_conf.sort_by_name = true;
		}
	}

	if (symbol__init() < 0)
		return -1;
+7 −12
Original line number Diff line number Diff line
#include "builtin.h"

#include "util/util.h"
#include "perf.h"
#include "util/cache.h"
#include "util/debug.h"
#include "util/exec_cmd.h"
#include "util/header.h"
#include "util/parse-options.h"
#include "util/session.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/header.h"
#include "util/exec_cmd.h"
#include "util/trace-event.h"
#include "util/session.h"
#include "util/util.h"

static char const		*script_name;
static char const		*generate_script_lang;
@@ -59,14 +62,6 @@ static int cleanup_scripting(void)
	return scripting_ops->stop_script();
}

#include "util/parse-options.h"

#include "perf.h"
#include "util/debug.h"

#include "util/trace-event.h"
#include "util/exec_cmd.h"

static char const		*input_name = "perf.data";

static int process_sample_event(event_t *event, struct perf_session *session)
+3 −0
Original line number Diff line number Diff line
@@ -876,6 +876,9 @@ unsigned int hists__sort_list_width(struct hists *self)
		if (!se->elide)
			ret += 2 + hists__col_len(self, se->se_width_idx);

	if (verbose) /* Addr + origin */
		ret += 3 + BITS_PER_LONG / 4;

	return ret;
}

+229 −13
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <slang.h>
#include <signal.h>
#include <stdlib.h>
#include <elf.h>
#include <newt.h>
#include <sys/ttydefaults.h>

@@ -127,6 +128,39 @@ static void ui_helpline__puts(const char *msg)
	ui_helpline__push(msg);
}

static int ui_entry__read(const char *title, char *bf, size_t size, int width)
{
	struct newtExitStruct es;
	newtComponent form, entry;
	const char *result;
	int err = -1;

	newtCenteredWindow(width, 1, title);
	form = newtForm(NULL, NULL, 0);
	if (form == NULL)
		return -1;

	entry = newtEntry(0, 0, "0x", width, &result, NEWT_FLAG_SCROLL);
	if (entry == NULL)
		goto out_free_form;

	newtFormAddComponent(form, entry);
	newtFormAddHotKey(form, NEWT_KEY_ENTER);
	newtFormAddHotKey(form, NEWT_KEY_ESCAPE);
	newtFormAddHotKey(form, NEWT_KEY_LEFT);
	newtFormAddHotKey(form, CTRL('c'));
	newtFormRun(form, &es);

	if (result != NULL) {
		strncpy(bf, result, size);
		err = 0;
	}
out_free_form:
	newtPopWindow();
	newtFormDestroy(form);
	return 0;
}

static char browser__last_msg[1024];

int browser__show_help(const char *format, va_list ap)
@@ -279,7 +313,8 @@ struct ui_browser {
	void		*first_visible_entry, *entries;
	u16		top, left, width, height;
	void		*priv;
	unsigned int	(*refresh_entries)(struct ui_browser *self);
	unsigned int	(*refresh)(struct ui_browser *self);
	void		(*write)(struct ui_browser *self, void *entry, int row);
	void		(*seek)(struct ui_browser *self,
				off_t offset, int whence);
	u32		nr_entries;
@@ -316,6 +351,58 @@ static void ui_browser__list_head_seek(struct ui_browser *self,
	self->first_visible_entry = pos;
}

static void ui_browser__rb_tree_seek(struct ui_browser *self,
				     off_t offset, int whence)
{
	struct rb_root *root = self->entries;
	struct rb_node *nd;

	switch (whence) {
	case SEEK_SET:
		nd = rb_first(root);
		break;
	case SEEK_CUR:
		nd = self->first_visible_entry;
		break;
	case SEEK_END:
		nd = rb_last(root);
		break;
	default:
		return;
	}

	if (offset > 0) {
		while (offset-- != 0)
			nd = rb_next(nd);
	} else {
		while (offset++ != 0)
			nd = rb_prev(nd);
	}

	self->first_visible_entry = nd;
}

static unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self)
{
	struct rb_node *nd;
	int row = 0;

	if (self->first_visible_entry == NULL)
                self->first_visible_entry = rb_first(self->entries);

	nd = self->first_visible_entry;

	while (nd != NULL) {
		SLsmg_gotorc(self->top + row, self->left);
		self->write(self, nd, row);
		if (++row == self->height)
			break;
		nd = rb_next(nd);
	}

	return row;
}

static bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
{
	return (self->first_visible_entry_idx + row) == self->index;
@@ -418,12 +505,12 @@ static int objdump_line__show(struct objdump_line *self, struct list_head *head,
	return 0;
}

static int ui_browser__refresh_entries(struct ui_browser *self)
static int ui_browser__refresh(struct ui_browser *self)
{
	int row;

	newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
	row = self->refresh_entries(self);
	row = self->refresh(self);
	SLsmg_set_color(HE_COLORSET_NORMAL);
	SLsmg_fill_region(self->top + row, self->left,
			  self->height - row, self->width, ' ');
@@ -433,7 +520,7 @@ static int ui_browser__refresh_entries(struct ui_browser *self)

static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
{
	if (ui_browser__refresh_entries(self) < 0)
	if (ui_browser__refresh(self) < 0)
		return -1;

	while (1) {
@@ -504,7 +591,7 @@ static int ui_browser__run(struct ui_browser *self, struct newtExitStruct *es)
		default:
			return es->u.key;
		}
		if (ui_browser__refresh_entries(self) < 0)
		if (ui_browser__refresh(self) < 0)
			return -1;
	}
	return 0;
@@ -568,7 +655,7 @@ int hist_entry__tui_annotate(struct hist_entry *self)

	memset(&browser, 0, sizeof(browser));
	browser.entries	= &head;
	browser.refresh_entries = hist_entry__annotate_browser_refresh;
	browser.refresh = hist_entry__annotate_browser_refresh;
	browser.seek	= ui_browser__list_head_seek;
	browser.priv = self;
	list_for_each_entry(pos, &head, node) {
@@ -592,6 +679,128 @@ int hist_entry__tui_annotate(struct hist_entry *self)
	return ret;
}

/* -------------------------------------------------------------------- */

struct map_browser {
	struct ui_browser b;
	struct map	  *map;
	u16		  namelen;
	u8		  addrlen;
};

static void map_browser__write(struct ui_browser *self, void *nd, int row)
{
	struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
	struct map_browser *mb = container_of(self, struct map_browser, b);
	bool current_entry = ui_browser__is_current_entry(self, row);
	int color = ui_browser__percent_color(0, current_entry);

	SLsmg_set_color(color);
	slsmg_printf("%*llx %*llx %c ",
		     mb->addrlen, sym->start, mb->addrlen, sym->end,
		     sym->binding == STB_GLOBAL ? 'g' :
		     sym->binding == STB_LOCAL  ? 'l' : 'w');
	slsmg_write_nstring(sym->name, mb->namelen);
}

/* FIXME uber-kludgy, see comment on cmd_report... */
static u32 *symbol__browser_index(struct symbol *self)
{
	return ((void *)self) - sizeof(struct rb_node) - sizeof(u32);
}

static int map_browser__search(struct map_browser *self)
{
	char target[512];
	struct symbol *sym;
	int err = ui_entry__read("Search by name/addr", target, sizeof(target), 40);

	if (err)
		return err;

	if (target[0] == '0' && tolower(target[1]) == 'x') {
		u64 addr = strtoull(target, NULL, 16);
		sym = map__find_symbol(self->map, addr, NULL);
	} else
		sym = map__find_symbol_by_name(self->map, target, NULL);

	if (sym != NULL) {
		u32 *idx = symbol__browser_index(sym);
			
		self->b.first_visible_entry = &sym->rb_node;
		self->b.index = self->b.first_visible_entry_idx = *idx;
	} else
		ui_helpline__fpush("%s not found!", target);

	return 0;
}

static int map_browser__run(struct map_browser *self, struct newtExitStruct *es)
{
	if (ui_browser__show(&self->b, self->map->dso->long_name) < 0)
		return -1;

	ui_helpline__fpush("Press <- or ESC to exit, %s / to search",
			   verbose ? "" : "restart with -v to use");
	newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT);
	newtFormAddHotKey(self->b.form, NEWT_KEY_ENTER);
	if (verbose)
		newtFormAddHotKey(self->b.form, '/');

	while (1) {
		ui_browser__run(&self->b, es);

		if (es->reason != NEWT_EXIT_HOTKEY)
			break;
		if (verbose && es->u.key == '/')
			map_browser__search(self);
		else
			break;
	}

	newtFormDestroy(self->b.form);
	newtPopWindow();
	ui_helpline__pop();
	return 0;
}

static int map__browse(struct map *self)
{
	struct map_browser mb = {
		.b = {
			.entries = &self->dso->symbols[self->type],
			.refresh = ui_browser__rb_tree_refresh,
			.seek	 = ui_browser__rb_tree_seek,
			.write	 = map_browser__write,
		},
		.map = self,
	};
	struct newtExitStruct es;
	struct rb_node *nd;
	char tmp[BITS_PER_LONG / 4];
	u64 maxaddr = 0;

	for (nd = rb_first(mb.b.entries); nd; nd = rb_next(nd)) {
		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);

		if (mb.namelen < pos->namelen)
			mb.namelen = pos->namelen;
		if (maxaddr < pos->end)
			maxaddr = pos->end;
		if (verbose) {
			u32 *idx = symbol__browser_index(pos);
			*idx = mb.b.nr_entries;
		}
		++mb.b.nr_entries;
	}

	mb.addrlen = snprintf(tmp, sizeof(tmp), "%llx", maxaddr);
	mb.b.width += mb.addrlen * 2 + 4 + mb.namelen;
	return map_browser__run(&mb, &es);
}

/* -------------------------------------------------------------------- */

struct hist_browser {
	struct ui_browser   b;
	struct hists	    *hists;
@@ -602,7 +811,7 @@ struct hist_browser {
static void hist_browser__reset(struct hist_browser *self);
static int hist_browser__run(struct hist_browser *self, const char *title,
			     struct newtExitStruct *es);
static unsigned int hist_browser__refresh_entries(struct ui_browser *self);
static unsigned int hist_browser__refresh(struct ui_browser *self);
static void ui_browser__hists_seek(struct ui_browser *self,
				   off_t offset, int whence);

@@ -612,7 +821,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists)

	if (self) {
		self->hists = hists;
		self->b.refresh_entries = hist_browser__refresh_entries;
		self->b.refresh = hist_browser__refresh;
		self->b.seek = ui_browser__hists_seek;
	}

@@ -680,7 +889,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
		const struct dso *dso;
		char *options[16];
		int nr_options = 0, choice = 0, i,
		    annotate = -2, zoom_dso = -2, zoom_thread = -2;
		    annotate = -2, zoom_dso = -2, zoom_thread = -2,
		    browse_map = -2;

		if (hist_browser__run(browser, msg, &es))
			break;
@@ -771,6 +981,10 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
			     (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
			zoom_dso = nr_options++;

		if (browser->selection->map != NULL &&
		    asprintf(&options[nr_options], "Browse map details") > 0)
			browse_map = nr_options++;

		options[nr_options++] = (char *)"Exit";

		choice = popup_menu(nr_options, options);
@@ -800,7 +1014,9 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
				continue;

			hist_entry__tui_annotate(he);
		} else if (choice == zoom_dso) {
		} else if (choice == browse_map)
			map__browse(browser->selection->map);
		else if (choice == zoom_dso) {
zoom_dso:
			if (dso_filter) {
				pstack__remove(fstack, &dso_filter);
@@ -1213,7 +1429,7 @@ static int hist_browser__show_entry(struct hist_browser *self,
	return printed;
}

static unsigned int hist_browser__refresh_entries(struct ui_browser *self)
static unsigned int hist_browser__refresh(struct ui_browser *self)
{
	unsigned row = 0;
	struct rb_node *nd;
+0 −1
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@
#include <ctype.h>
#include <dwarf-regs.h>

#include "string.h"
#include "event.h"
#include "debug.h"
#include "util.h"
Loading