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: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
439d473b47
commit
9735abf11b
|
@ -80,48 +80,16 @@ static void hist_hit(struct hist_entry *he, u64 ip)
|
||||||
sym->hist[offset]);
|
sym->hist[offset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int hist_entry__add(struct thread *thread, struct map *map,
|
||||||
hist_entry__add(struct thread *thread, struct map *map,
|
struct symbol *sym, u64 ip, u64 count, char level)
|
||||||
struct symbol *sym, u64 ip, char level)
|
|
||||||
{
|
{
|
||||||
struct rb_node **p = &hist.rb_node;
|
bool hit;
|
||||||
struct rb_node *parent = NULL;
|
struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
|
||||||
struct hist_entry *he;
|
count, level, &hit);
|
||||||
struct hist_entry entry = {
|
if (he == NULL)
|
||||||
.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)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
*he = entry;
|
if (hit)
|
||||||
rb_link_node(&he->rb_node, parent, p);
|
hist_hit(he, ip);
|
||||||
rb_insert_color(&he->rb_node, &hist);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,7 +159,7 @@ got_map:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show & show_mask) {
|
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,
|
fprintf(stderr,
|
||||||
"problem incrementing symbol count, skipping event\n");
|
"problem incrementing symbol count, skipping event\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -407,9 +407,9 @@ static int call__match(struct symbol *sym)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct symbol **
|
static struct symbol **resolve_callchain(struct thread *thread, struct map *map,
|
||||||
resolve_callchain(struct thread *thread, struct map *map,
|
struct ip_callchain *chain,
|
||||||
struct ip_callchain *chain, struct hist_entry *entry)
|
struct symbol **parent)
|
||||||
{
|
{
|
||||||
u64 context = PERF_CONTEXT_MAX;
|
u64 context = PERF_CONTEXT_MAX;
|
||||||
struct symbol **syms = NULL;
|
struct symbol **syms = NULL;
|
||||||
|
@ -444,9 +444,8 @@ resolve_callchain(struct thread *thread, struct map *map,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sym) {
|
if (sym) {
|
||||||
if (sort__has_parent && call__match(sym) &&
|
if (sort__has_parent && !*parent && call__match(sym))
|
||||||
!entry->parent)
|
*parent = sym;
|
||||||
entry->parent = sym;
|
|
||||||
if (!callchain)
|
if (!callchain)
|
||||||
break;
|
break;
|
||||||
syms[i] = sym;
|
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,
|
struct symbol *sym, u64 ip, struct ip_callchain *chain,
|
||||||
char level, u64 count)
|
char level, u64 count)
|
||||||
{
|
{
|
||||||
struct rb_node **p = &hist.rb_node;
|
struct symbol **syms = NULL, *parent = NULL;
|
||||||
struct rb_node *parent = NULL;
|
bool hit;
|
||||||
struct hist_entry *he;
|
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)
|
if ((sort__has_parent || callchain) && chain)
|
||||||
syms = resolve_callchain(thread, map, chain, &entry);
|
syms = resolve_callchain(thread, map, chain, &parent);
|
||||||
|
|
||||||
while (*p != NULL) {
|
he = __hist_entry__add(thread, map, sym, parent,
|
||||||
parent = *p;
|
ip, count, level, &hit);
|
||||||
he = rb_entry(parent, struct hist_entry, rb_node);
|
if (he == NULL)
|
||||||
|
|
||||||
cmp = hist_entry__cmp(&entry, he);
|
|
||||||
|
|
||||||
if (!cmp) {
|
|
||||||
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;
|
return -ENOMEM;
|
||||||
*he = entry;
|
|
||||||
|
if (hit)
|
||||||
|
he->count += count;
|
||||||
|
|
||||||
if (callchain) {
|
if (callchain) {
|
||||||
|
if (!hit)
|
||||||
callchain_init(&he->callchain);
|
callchain_init(&he->callchain);
|
||||||
append_chain(&he->callchain, chain, syms);
|
append_chain(&he->callchain, chain, syms);
|
||||||
free(syms);
|
free(syms);
|
||||||
}
|
}
|
||||||
rb_link_node(&he->rb_node, parent, p);
|
|
||||||
rb_insert_color(&he->rb_node, &hist);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,52 @@ unsigned long total_lost;
|
||||||
* histogram, sorted on item, collects counts
|
* 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
|
int64_t
|
||||||
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
|
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,9 @@ extern unsigned long total_fork;
|
||||||
extern unsigned long total_unknown;
|
extern unsigned long total_unknown;
|
||||||
extern unsigned long total_lost;
|
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__cmp(struct hist_entry *, struct hist_entry *);
|
||||||
extern int64_t hist_entry__collapse(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 *);
|
extern void hist_entry__free(struct hist_entry *);
|
||||||
|
|
Loading…
Reference in New Issue