diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/util/callchain.c | 56 | ||||
| -rw-r--r-- | tools/perf/util/callchain.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/hist.c | 2 |
3 files changed, 59 insertions, 0 deletions
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 59cc0e12dd4..e12d539417b 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
| @@ -28,6 +28,9 @@ bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event) | |||
| 28 | #define chain_for_each_child(child, parent) \ | 28 | #define chain_for_each_child(child, parent) \ |
| 29 | list_for_each_entry(child, &parent->children, brothers) | 29 | list_for_each_entry(child, &parent->children, brothers) |
| 30 | 30 | ||
| 31 | #define chain_for_each_child_safe(child, next, parent) \ | ||
| 32 | list_for_each_entry_safe(child, next, &parent->children, brothers) | ||
| 33 | |||
| 31 | static void | 34 | static void |
| 32 | rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, | 35 | rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, |
| 33 | enum chain_mode mode) | 36 | enum chain_mode mode) |
| @@ -406,3 +409,56 @@ end: | |||
| 406 | 409 | ||
| 407 | return 0; | 410 | return 0; |
| 408 | } | 411 | } |
| 412 | |||
| 413 | static int | ||
| 414 | merge_chain_branch(struct callchain_node *dst, struct callchain_node *src, | ||
| 415 | struct resolved_chain *chain) | ||
| 416 | { | ||
| 417 | struct callchain_node *child, *next_child; | ||
| 418 | struct callchain_list *list, *next_list; | ||
| 419 | int old_pos = chain->nr; | ||
| 420 | int err = 0; | ||
| 421 | |||
| 422 | list_for_each_entry_safe(list, next_list, &src->val, list) { | ||
| 423 | chain->ips[chain->nr].ip = list->ip; | ||
| 424 | chain->ips[chain->nr].ms = list->ms; | ||
| 425 | chain->nr++; | ||
| 426 | list_del(&list->list); | ||
| 427 | free(list); | ||
| 428 | } | ||
| 429 | |||
| 430 | if (src->hit) | ||
| 431 | append_chain_children(dst, chain, 0, src->hit); | ||
| 432 | |||
| 433 | chain_for_each_child_safe(child, next_child, src) { | ||
| 434 | err = merge_chain_branch(dst, child, chain); | ||
| 435 | if (err) | ||
| 436 | break; | ||
| 437 | |||
| 438 | list_del(&child->brothers); | ||
| 439 | free(child); | ||
| 440 | } | ||
| 441 | |||
| 442 | chain->nr = old_pos; | ||
| 443 | |||
| 444 | return err; | ||
| 445 | } | ||
| 446 | |||
| 447 | int callchain_merge(struct callchain_root *dst, struct callchain_root *src) | ||
| 448 | { | ||
| 449 | struct resolved_chain *chain; | ||
| 450 | int err; | ||
| 451 | |||
| 452 | chain = malloc(sizeof(*chain) + | ||
| 453 | src->max_depth * sizeof(struct resolved_ip)); | ||
| 454 | if (!chain) | ||
| 455 | return -ENOMEM; | ||
| 456 | |||
| 457 | chain->nr = 0; | ||
| 458 | |||
| 459 | err = merge_chain_branch(&dst->node, &src->node, chain); | ||
| 460 | |||
| 461 | free(chain); | ||
| 462 | |||
| 463 | return err; | ||
| 464 | } | ||
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 85b50fbeae5..51a8f2b600b 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
| @@ -68,6 +68,7 @@ static inline u64 cumul_hits(struct callchain_node *node) | |||
| 68 | int register_callchain_param(struct callchain_param *param); | 68 | int register_callchain_param(struct callchain_param *param); |
| 69 | int callchain_append(struct callchain_root *root, struct ip_callchain *chain, | 69 | int callchain_append(struct callchain_root *root, struct ip_callchain *chain, |
| 70 | struct map_symbol *syms, u64 period); | 70 | struct map_symbol *syms, u64 period); |
| 71 | int callchain_merge(struct callchain_root *dst, struct callchain_root *src); | ||
| 71 | 72 | ||
| 72 | bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); | 73 | bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); |
| 73 | #endif /* __PERF_CALLCHAIN_H */ | 74 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index e77ff772463..2022e874099 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
| @@ -226,6 +226,8 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he) | |||
| 226 | 226 | ||
| 227 | if (!cmp) { | 227 | if (!cmp) { |
| 228 | iter->period += he->period; | 228 | iter->period += he->period; |
| 229 | if (symbol_conf.use_callchain) | ||
| 230 | callchain_merge(iter->callchain, he->callchain); | ||
| 229 | hist_entry__free(he); | 231 | hist_entry__free(he); |
| 230 | return false; | 232 | return false; |
| 231 | } | 233 | } |
