aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-annotate.c50
-rw-r--r--tools/perf/builtin-report.c63
-rw-r--r--tools/perf/util/hist.c46
-rw-r--r--tools/perf/util/hist.h3
4 files changed, 74 insertions, 88 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7d5a3b1bcda9..855094234f2d 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -80,48 +80,16 @@ static void hist_hit(struct hist_entry *he, u64 ip)
80 sym->hist[offset]); 80 sym->hist[offset]);
81} 81}
82 82
83static int 83static int hist_entry__add(struct thread *thread, struct map *map,
84hist_entry__add(struct thread *thread, struct map *map, 84 struct symbol *sym, u64 ip, u64 count, char level)
85 struct symbol *sym, u64 ip, char level)
86{ 85{
87 struct rb_node **p = &hist.rb_node; 86 bool hit;
88 struct rb_node *parent = NULL; 87 struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip,
89 struct hist_entry *he; 88 count, level, &hit);
90 struct hist_entry entry = { 89 if (he == NULL)
91 .thread = thread,
92 .map = map,
93 .sym = sym,
94 .ip = ip,
95 .level = level,
96 .count = 1,
97 };
98 int cmp;
99
100 while (*p != NULL) {
101 parent = *p;
102 he = rb_entry(parent, struct hist_entry, rb_node);
103
104 cmp = hist_entry__cmp(&entry, he);
105
106 if (!cmp) {
107 hist_hit(he, ip);
108
109 return 0;
110 }
111
112 if (cmp < 0)
113 p = &(*p)->rb_left;
114 else
115 p = &(*p)->rb_right;
116 }
117
118 he = malloc(sizeof(*he));
119 if (!he)
120 return -ENOMEM; 90 return -ENOMEM;
121 *he = entry; 91 if (hit)
122 rb_link_node(&he->rb_node, parent, p); 92 hist_hit(he, ip);
123 rb_insert_color(&he->rb_node, &hist);
124
125 return 0; 93 return 0;
126} 94}
127 95
@@ -191,7 +159,7 @@ got_map:
191 } 159 }
192 160
193 if (show & show_mask) { 161 if (show & show_mask) {
194 if (hist_entry__add(thread, map, sym, ip, level)) { 162 if (hist_entry__add(thread, map, sym, ip, 1, level)) {
195 fprintf(stderr, 163 fprintf(stderr,
196 "problem incrementing symbol count, skipping event\n"); 164 "problem incrementing symbol count, skipping event\n");
197 return -1; 165 return -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 3ed3baf96ffb..0e83ffcbe55a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -407,9 +407,9 @@ static int call__match(struct symbol *sym)
407 return 0; 407 return 0;
408} 408}
409 409
410static struct symbol ** 410static struct symbol **resolve_callchain(struct thread *thread, struct map *map,
411resolve_callchain(struct thread *thread, struct map *map, 411 struct ip_callchain *chain,
412 struct ip_callchain *chain, struct hist_entry *entry) 412 struct symbol **parent)
413{ 413{
414 u64 context = PERF_CONTEXT_MAX; 414 u64 context = PERF_CONTEXT_MAX;
415 struct symbol **syms = NULL; 415 struct symbol **syms = NULL;
@@ -444,9 +444,8 @@ resolve_callchain(struct thread *thread, struct map *map,
444 } 444 }
445 445
446 if (sym) { 446 if (sym) {
447 if (sort__has_parent && call__match(sym) && 447 if (sort__has_parent && !*parent && call__match(sym))
448 !entry->parent) 448 *parent = sym;
449 entry->parent = sym;
450 if (!callchain) 449 if (!callchain)
451 break; 450 break;
452 syms[i] = sym; 451 syms[i] = sym;
@@ -465,57 +464,27 @@ hist_entry__add(struct thread *thread, struct map *map,
465 struct symbol *sym, u64 ip, struct ip_callchain *chain, 464 struct symbol *sym, u64 ip, struct ip_callchain *chain,
466 char level, u64 count) 465 char level, u64 count)
467{ 466{
468 struct rb_node **p = &hist.rb_node; 467 struct symbol **syms = NULL, *parent = NULL;
469 struct rb_node *parent = NULL; 468 bool hit;
470 struct hist_entry *he; 469 struct hist_entry *he;
471 struct symbol **syms = NULL;
472 struct hist_entry entry = {
473 .thread = thread,
474 .map = map,
475 .sym = sym,
476 .ip = ip,
477 .level = level,
478 .count = count,
479 .parent = NULL,
480 .sorted_chain = RB_ROOT
481 };
482 int cmp;
483 470
484 if ((sort__has_parent || callchain) && chain) 471 if ((sort__has_parent || callchain) && chain)
485 syms = resolve_callchain(thread, map, chain, &entry); 472 syms = resolve_callchain(thread, map, chain, &parent);
486
487 while (*p != NULL) {
488 parent = *p;
489 he = rb_entry(parent, struct hist_entry, rb_node);
490
491 cmp = hist_entry__cmp(&entry, he);
492 473
493 if (!cmp) { 474 he = __hist_entry__add(thread, map, sym, parent,
494 he->count += count; 475 ip, count, level, &hit);
495 if (callchain) { 476 if (he == NULL)
496 append_chain(&he->callchain, chain, syms); 477 return -ENOMEM;
497 free(syms);
498 }
499 return 0;
500 }
501 478
502 if (cmp < 0) 479 if (hit)
503 p = &(*p)->rb_left; 480 he->count += count;
504 else
505 p = &(*p)->rb_right;
506 }
507 481
508 he = malloc(sizeof(*he));
509 if (!he)
510 return -ENOMEM;
511 *he = entry;
512 if (callchain) { 482 if (callchain) {
513 callchain_init(&he->callchain); 483 if (!hit)
484 callchain_init(&he->callchain);
514 append_chain(&he->callchain, chain, syms); 485 append_chain(&he->callchain, chain, syms);
515 free(syms); 486 free(syms);
516 } 487 }
517 rb_link_node(&he->rb_node, parent, p);
518 rb_insert_color(&he->rb_node, &hist);
519 488
520 return 0; 489 return 0;
521} 490}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 82808dc4f8e3..7393a02fd8d4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -21,6 +21,52 @@ unsigned long total_lost;
21 * histogram, sorted on item, collects counts 21 * histogram, sorted on item, collects counts
22 */ 22 */
23 23
24struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
25 struct symbol *sym,
26 struct symbol *sym_parent,
27 u64 ip, u64 count, char level, bool *hit)
28{
29 struct rb_node **p = &hist.rb_node;
30 struct rb_node *parent = NULL;
31 struct hist_entry *he;
32 struct hist_entry entry = {
33 .thread = thread,
34 .map = map,
35 .sym = sym,
36 .ip = ip,
37 .level = level,
38 .count = count,
39 .parent = sym_parent,
40 };
41 int cmp;
42
43 while (*p != NULL) {
44 parent = *p;
45 he = rb_entry(parent, struct hist_entry, rb_node);
46
47 cmp = hist_entry__cmp(&entry, he);
48
49 if (!cmp) {
50 *hit = true;
51 return he;
52 }
53
54 if (cmp < 0)
55 p = &(*p)->rb_left;
56 else
57 p = &(*p)->rb_right;
58 }
59
60 he = malloc(sizeof(*he));
61 if (!he)
62 return NULL;
63 *he = entry;
64 rb_link_node(&he->rb_node, parent, p);
65 rb_insert_color(&he->rb_node, &hist);
66 *hit = false;
67 return he;
68}
69
24int64_t 70int64_t
25hist_entry__cmp(struct hist_entry *left, struct hist_entry *right) 71hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
26{ 72{
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 9a8daa12b43a..ac2149c559b0 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -36,6 +36,9 @@ extern unsigned long total_fork;
36extern unsigned long total_unknown; 36extern unsigned long total_unknown;
37extern unsigned long total_lost; 37extern unsigned long total_lost;
38 38
39struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
40 struct symbol *sym, struct symbol *parent,
41 u64 ip, u64 count, char level, bool *hit);
39extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 42extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
40extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 43extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
41extern void hist_entry__free(struct hist_entry *); 44extern void hist_entry__free(struct hist_entry *);