perf tools: Move hist_entry__add common code to hist.c
authorArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 3 Oct 2009 13:42:45 +0000 (10:42 -0300)
committerIngo Molnar <mingo@elte.hu>
Sat, 3 Oct 2009 14:01:59 +0000 (16:01 +0200)
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>
tools/perf/builtin-annotate.c
tools/perf/builtin-report.c
tools/perf/util/hist.c
tools/perf/util/hist.h

index 7d5a3b1bcda9de743681dc9a58fad96ebeaf5568..855094234f2d25fa652b8e97762b731c8ba293a6 100644 (file)
@@ -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 @@ got_map:
        }
 
        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;
index 3ed3baf96ffba62dbbc8a7f06f090a2be7d9651f..0e83ffcbe55a4dca36067024080d85b54068d952 100644 (file)
@@ -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);
-
-       while (*p != NULL) {
-               parent = *p;
-               he = rb_entry(parent, struct hist_entry, rb_node);
-
-               cmp = hist_entry__cmp(&entry, he);
+               syms = resolve_callchain(thread, map, chain, &parent);
 
-               if (!cmp) {
-                       he->count += count;
-                       if (callchain) {
-                               append_chain(&he->callchain, chain, syms);
-                               free(syms);
-                       }
-                       return 0;
-               }
+       he = __hist_entry__add(thread, map, sym, parent,
+                              ip, count, level, &hit);
+       if (he == NULL)
+               return -ENOMEM;
 
-               if (cmp < 0)
-                       p = &(*p)->rb_left;
-               else
-                       p = &(*p)->rb_right;
-       }
+       if (hit)
+               he->count += count;
 
-       he = malloc(sizeof(*he));
-       if (!he)
-               return -ENOMEM;
-       *he = entry;
        if (callchain) {
-               callchain_init(&he->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;
 }
index 82808dc4f8e334f74cc7fbe5ed60729babc72c56..7393a02fd8d470fe9ac50340b41e61fe7564b804 100644 (file)
@@ -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)
 {
index 9a8daa12b43ab1572b229d40805557eaf48d72e5..ac2149c559b0c0cb10cc02a3ab95b9f93c2b9a39 100644 (file)
@@ -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 *);