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;
}
}
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;
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;
}
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;
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;
}
* 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)
{
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 *);