diff options
Diffstat (limited to 'tools/perf/util/callchain.h')
-rw-r--r-- | tools/perf/util/callchain.h | 76 |
1 files changed, 68 insertions, 8 deletions
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index c15fb8c..1a79df9 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h @@ -16,7 +16,7 @@ enum chain_mode { struct callchain_node { struct callchain_node *parent; - struct list_head brothers; + struct list_head siblings; struct list_head children; struct list_head val; struct rb_node rb_node; /* to sort nodes in an rbtree */ @@ -49,9 +49,30 @@ struct callchain_list { struct list_head list; }; +/* + * A callchain cursor is a single linked list that + * let one feed a callchain progressively. + * It keeps persitent allocated entries to minimize + * allocations. + */ +struct callchain_cursor_node { + u64 ip; + struct map *map; + struct symbol *sym; + struct callchain_cursor_node *next; +}; + +struct callchain_cursor { + u64 nr; + struct callchain_cursor_node *first; + struct callchain_cursor_node **last; + u64 pos; + struct callchain_cursor_node *curr; +}; + static inline void callchain_init(struct callchain_root *root) { - INIT_LIST_HEAD(&root->node.brothers); + INIT_LIST_HEAD(&root->node.siblings); INIT_LIST_HEAD(&root->node.children); INIT_LIST_HEAD(&root->node.val); @@ -61,15 +82,54 @@ static inline void callchain_init(struct callchain_root *root) root->max_depth = 0; } -static inline u64 cumul_hits(struct callchain_node *node) +static inline u64 callchain_cumul_hits(struct callchain_node *node) { return node->hit + node->children_hit; } -int register_callchain_param(struct callchain_param *param); -int callchain_append(struct callchain_root *root, struct ip_callchain *chain, - struct map_symbol *syms, u64 period); -int callchain_merge(struct callchain_root *dst, struct callchain_root *src); +int callchain_register_param(struct callchain_param *param); +int callchain_append(struct callchain_root *root, + struct callchain_cursor *cursor, + u64 period); + +int callchain_merge(struct callchain_cursor *cursor, + struct callchain_root *dst, struct callchain_root *src); + +bool ip_callchain__valid(struct ip_callchain *chain, + const union perf_event *event); +/* + * Initialize a cursor before adding entries inside, but keep + * the previously allocated entries as a cache. + */ +static inline void callchain_cursor_reset(struct callchain_cursor *cursor) +{ + cursor->nr = 0; + cursor->last = &cursor->first; +} + +int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, + struct map *map, struct symbol *sym); -bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event); +/* Close a cursor writing session. Initialize for the reader */ +static inline void callchain_cursor_commit(struct callchain_cursor *cursor) +{ + cursor->curr = cursor->first; + cursor->pos = 0; +} + +/* Cursor reading iteration helpers */ +static inline struct callchain_cursor_node * +callchain_cursor_current(struct callchain_cursor *cursor) +{ + if (cursor->pos == cursor->nr) + return NULL; + + return cursor->curr; +} + +static inline void callchain_cursor_advance(struct callchain_cursor *cursor) +{ + cursor->curr = cursor->curr->next; + cursor->pos++; +} #endif /* __PERF_CALLCHAIN_H */ |