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

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

perf tools: Move hist_entry__add common code to hist.c



Now perf report and annotate do the callgraph/hit processing in
their specialized hist_entry__add functions.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: default avatarFrédéric Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 439d473b
Loading
Loading
Loading
Loading
+9 −41
Original line number Diff line number Diff line
@@ -80,48 +80,16 @@ static void hist_hit(struct hist_entry *he, u64 ip)
			sym->hist[offset]);
}

static int
hist_entry__add(struct thread *thread, struct map *map,
		struct symbol *sym, u64 ip, char level)
static int hist_entry__add(struct thread *thread, struct map *map,
			   struct symbol *sym, u64 ip, u64 count, char level)
{
	struct rb_node **p = &hist.rb_node;
	struct rb_node *parent = NULL;
	struct hist_entry *he;
	struct hist_entry entry = {
		.thread	= thread,
		.map	= map,
		.sym	= sym,
		.ip	= ip,
		.level	= level,
		.count	= 1,
	};
	int cmp;

	while (*p != NULL) {
		parent = *p;
		he = rb_entry(parent, struct hist_entry, rb_node);

		cmp = hist_entry__cmp(&entry, he);

		if (!cmp) {
			hist_hit(he, ip);

			return 0;
		}

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

	he = malloc(sizeof(*he));
	if (!he)
	bool hit;
	struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
						  count, level, &hit);
	if (he == NULL)
		return -ENOMEM;
	*he = entry;
	rb_link_node(&he->rb_node, parent, p);
	rb_insert_color(&he->rb_node, &hist);

	if (hit)
		hist_hit(he, ip);
	return 0;
}

@@ -191,7 +159,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
	}

	if (show & show_mask) {
		if (hist_entry__add(thread, map, sym, ip, level)) {
		if (hist_entry__add(thread, map, sym, ip, 1, level)) {
			fprintf(stderr,
		"problem incrementing symbol count, skipping event\n");
			return -1;
+16 −47
Original line number Diff line number Diff line
@@ -407,9 +407,9 @@ static int call__match(struct symbol *sym)
	return 0;
}

static struct symbol **
resolve_callchain(struct thread *thread, struct map *map,
		    struct ip_callchain *chain, struct hist_entry *entry)
static struct symbol **resolve_callchain(struct thread *thread, struct map *map,
					 struct ip_callchain *chain,
					 struct symbol **parent)
{
	u64 context = PERF_CONTEXT_MAX;
	struct symbol **syms = NULL;
@@ -444,9 +444,8 @@ resolve_callchain(struct thread *thread, struct map *map,
		}

		if (sym) {
			if (sort__has_parent && call__match(sym) &&
			    !entry->parent)
				entry->parent = sym;
			if (sort__has_parent && !*parent && call__match(sym))
				*parent = sym;
			if (!callchain)
				break;
			syms[i] = sym;
@@ -465,57 +464,27 @@ hist_entry__add(struct thread *thread, struct map *map,
		struct symbol *sym, u64 ip, struct ip_callchain *chain,
		char level, u64 count)
{
	struct rb_node **p = &hist.rb_node;
	struct rb_node *parent = NULL;
	struct symbol **syms = NULL, *parent = NULL;
	bool hit;
	struct hist_entry *he;
	struct symbol **syms = NULL;
	struct hist_entry entry = {
		.thread	= thread,
		.map	= map,
		.sym	= sym,
		.ip	= ip,
		.level	= level,
		.count	= count,
		.parent = NULL,
		.sorted_chain = RB_ROOT
	};
	int cmp;

	if ((sort__has_parent || callchain) && chain)
		syms = resolve_callchain(thread, map, chain, &entry);
		syms = resolve_callchain(thread, map, chain, &parent);

	while (*p != NULL) {
		parent = *p;
		he = rb_entry(parent, struct hist_entry, rb_node);

		cmp = hist_entry__cmp(&entry, he);
	he = __hist_entry__add(thread, map, sym, parent,
			       ip, count, level, &hit);
	if (he == NULL)
		return -ENOMEM;

		if (!cmp) {
	if (hit)
		he->count += count;
			if (callchain) {
				append_chain(&he->callchain, chain, syms);
				free(syms);
			}
			return 0;
		}

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

	he = malloc(sizeof(*he));
	if (!he)
		return -ENOMEM;
	*he = entry;
	if (callchain) {
		if (!hit)
			callchain_init(&he->callchain);
		append_chain(&he->callchain, chain, syms);
		free(syms);
	}
	rb_link_node(&he->rb_node, parent, p);
	rb_insert_color(&he->rb_node, &hist);

	return 0;
}
+46 −0
Original line number Diff line number Diff line
@@ -21,6 +21,52 @@ unsigned long total_lost;
 * histogram, sorted on item, collects counts
 */

struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
				     struct symbol *sym,
				     struct symbol *sym_parent,
				     u64 ip, u64 count, char level, bool *hit)
{
	struct rb_node **p = &hist.rb_node;
	struct rb_node *parent = NULL;
	struct hist_entry *he;
	struct hist_entry entry = {
		.thread	= thread,
		.map	= map,
		.sym	= sym,
		.ip	= ip,
		.level	= level,
		.count	= count,
		.parent = sym_parent,
	};
	int cmp;

	while (*p != NULL) {
		parent = *p;
		he = rb_entry(parent, struct hist_entry, rb_node);

		cmp = hist_entry__cmp(&entry, he);

		if (!cmp) {
			*hit = true;
			return he;
		}

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

	he = malloc(sizeof(*he));
	if (!he)
		return NULL;
	*he = entry;
	rb_link_node(&he->rb_node, parent, p);
	rb_insert_color(&he->rb_node, &hist);
	*hit = false;
	return he;
}

int64_t
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
{
+3 −0
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ extern unsigned long total_fork;
extern unsigned long total_unknown;
extern unsigned long total_lost;

struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
				     struct symbol *sym, struct symbol *parent,
				     u64 ip, u64 count, char level, bool *hit);
extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
extern void hist_entry__free(struct hist_entry *);