blob: 1a79df9f739f8425ce2991dcc0cc7a2eeac982dc [file] [log] [blame]
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +02001#ifndef __PERF_CALLCHAIN_H
2#define __PERF_CALLCHAIN_H
3
4#include "../perf.h"
Arnaldo Carvalho de Melo5da50252009-07-01 14:46:08 -03005#include <linux/list.h>
Arnaldo Carvalho de Melo43cbcd82009-07-01 12:28:37 -03006#include <linux/rbtree.h>
Arnaldo Carvalho de Melo139633c2010-05-09 11:47:13 -03007#include "event.h"
Frederic Weisbecker44249612009-07-01 05:35:14 +02008#include "symbol.h"
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +02009
Frederic Weisbecker4eb3e472009-07-02 17:58:21 +020010enum chain_mode {
Frederic Weisbeckerb1a88342009-08-08 02:16:24 +020011 CHAIN_NONE,
Frederic Weisbecker805d1272009-07-05 07:39:21 +020012 CHAIN_FLAT,
13 CHAIN_GRAPH_ABS,
14 CHAIN_GRAPH_REL
Frederic Weisbecker4eb3e472009-07-02 17:58:21 +020015};
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020016
17struct callchain_node {
18 struct callchain_node *parent;
Frederic Weisbecker529363b2011-01-14 04:52:01 +010019 struct list_head siblings;
Ingo Molnarf37a2912009-07-01 12:37:06 +020020 struct list_head children;
21 struct list_head val;
Frederic Weisbecker4eb3e472009-07-02 17:58:21 +020022 struct rb_node rb_node; /* to sort nodes in an rbtree */
23 struct rb_root rb_root; /* sorted tree of children */
Ingo Molnarf37a2912009-07-01 12:37:06 +020024 unsigned int val_nr;
25 u64 hit;
Frederic Weisbecker19532872009-08-07 07:11:05 +020026 u64 children_hit;
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020027};
28
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020029struct callchain_root {
30 u64 max_depth;
31 struct callchain_node node;
32};
33
Frederic Weisbecker805d1272009-07-05 07:39:21 +020034struct callchain_param;
35
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020036typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
Frederic Weisbecker805d1272009-07-05 07:39:21 +020037 u64, struct callchain_param *);
38
39struct callchain_param {
40 enum chain_mode mode;
Arnaldo Carvalho de Melo232a5c92010-05-09 20:28:10 -030041 u32 print_limit;
Frederic Weisbecker805d1272009-07-05 07:39:21 +020042 double min_percent;
43 sort_chain_func_t sort;
44};
45
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020046struct callchain_list {
Ingo Molnarf37a2912009-07-01 12:37:06 +020047 u64 ip;
Arnaldo Carvalho de Melob3c9ac02010-03-24 16:40:18 -030048 struct map_symbol ms;
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020049 struct list_head list;
50};
51
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +010052/*
53 * A callchain cursor is a single linked list that
54 * let one feed a callchain progressively.
55 * It keeps persitent allocated entries to minimize
56 * allocations.
57 */
58struct callchain_cursor_node {
59 u64 ip;
60 struct map *map;
61 struct symbol *sym;
62 struct callchain_cursor_node *next;
63};
64
65struct callchain_cursor {
66 u64 nr;
67 struct callchain_cursor_node *first;
68 struct callchain_cursor_node **last;
69 u64 pos;
70 struct callchain_cursor_node *curr;
71};
72
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020073static inline void callchain_init(struct callchain_root *root)
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020074{
Frederic Weisbecker529363b2011-01-14 04:52:01 +010075 INIT_LIST_HEAD(&root->node.siblings);
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020076 INIT_LIST_HEAD(&root->node.children);
77 INIT_LIST_HEAD(&root->node.val);
Frederic Weisbecker97aa1052010-07-08 06:06:17 +020078
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020079 root->node.parent = NULL;
80 root->node.hit = 0;
Frederic Weisbecker98ee74a2010-08-27 02:28:40 +020081 root->node.children_hit = 0;
Frederic Weisbeckerd2009c52010-08-22 20:05:22 +020082 root->max_depth = 0;
Frederic Weisbecker8cb76d92009-06-26 16:28:00 +020083}
84
Frederic Weisbeckerf08c3152011-01-14 04:51:59 +010085static inline u64 callchain_cumul_hits(struct callchain_node *node)
Frederic Weisbecker19532872009-08-07 07:11:05 +020086{
87 return node->hit + node->children_hit;
88}
89
Frederic Weisbecker16537f12011-01-14 04:52:00 +010090int callchain_register_param(struct callchain_param *param);
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +010091int callchain_append(struct callchain_root *root,
92 struct callchain_cursor *cursor,
93 u64 period);
94
95int callchain_merge(struct callchain_cursor *cursor,
96 struct callchain_root *dst, struct callchain_root *src);
Arnaldo Carvalho de Melo139633c2010-05-09 11:47:13 -030097
Arnaldo Carvalho de Melo8115d602011-01-29 14:01:45 -020098bool ip_callchain__valid(struct ip_callchain *chain,
99 const union perf_event *event);
Frederic Weisbecker1b3a0e92011-01-14 04:51:58 +0100100/*
101 * Initialize a cursor before adding entries inside, but keep
102 * the previously allocated entries as a cache.
103 */
104static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
105{
106 cursor->nr = 0;
107 cursor->last = &cursor->first;
108}
109
110int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
111 struct map *map, struct symbol *sym);
112
113/* Close a cursor writing session. Initialize for the reader */
114static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
115{
116 cursor->curr = cursor->first;
117 cursor->pos = 0;
118}
119
120/* Cursor reading iteration helpers */
121static inline struct callchain_cursor_node *
122callchain_cursor_current(struct callchain_cursor *cursor)
123{
124 if (cursor->pos == cursor->nr)
125 return NULL;
126
127 return cursor->curr;
128}
129
130static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
131{
132 cursor->curr = cursor->curr->next;
133 cursor->pos++;
134}
John Kacur8b40f522009-09-24 18:02:18 +0200135#endif /* __PERF_CALLCHAIN_H */