Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/tools/perf/util/callchain.h
10821 views
1
#ifndef __PERF_CALLCHAIN_H
2
#define __PERF_CALLCHAIN_H
3
4
#include "../perf.h"
5
#include <linux/list.h>
6
#include <linux/rbtree.h>
7
#include "event.h"
8
#include "symbol.h"
9
10
enum chain_mode {
11
CHAIN_NONE,
12
CHAIN_FLAT,
13
CHAIN_GRAPH_ABS,
14
CHAIN_GRAPH_REL
15
};
16
17
struct callchain_node {
18
struct callchain_node *parent;
19
struct list_head siblings;
20
struct list_head children;
21
struct list_head val;
22
struct rb_node rb_node; /* to sort nodes in an rbtree */
23
struct rb_root rb_root; /* sorted tree of children */
24
unsigned int val_nr;
25
u64 hit;
26
u64 children_hit;
27
};
28
29
struct callchain_root {
30
u64 max_depth;
31
struct callchain_node node;
32
};
33
34
struct callchain_param;
35
36
typedef void (*sort_chain_func_t)(struct rb_root *, struct callchain_root *,
37
u64, struct callchain_param *);
38
39
struct callchain_param {
40
enum chain_mode mode;
41
u32 print_limit;
42
double min_percent;
43
sort_chain_func_t sort;
44
};
45
46
struct callchain_list {
47
u64 ip;
48
struct map_symbol ms;
49
struct list_head list;
50
};
51
52
/*
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
*/
58
struct callchain_cursor_node {
59
u64 ip;
60
struct map *map;
61
struct symbol *sym;
62
struct callchain_cursor_node *next;
63
};
64
65
struct 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
73
static inline void callchain_init(struct callchain_root *root)
74
{
75
INIT_LIST_HEAD(&root->node.siblings);
76
INIT_LIST_HEAD(&root->node.children);
77
INIT_LIST_HEAD(&root->node.val);
78
79
root->node.parent = NULL;
80
root->node.hit = 0;
81
root->node.children_hit = 0;
82
root->max_depth = 0;
83
}
84
85
static inline u64 callchain_cumul_hits(struct callchain_node *node)
86
{
87
return node->hit + node->children_hit;
88
}
89
90
int callchain_register_param(struct callchain_param *param);
91
int callchain_append(struct callchain_root *root,
92
struct callchain_cursor *cursor,
93
u64 period);
94
95
int callchain_merge(struct callchain_cursor *cursor,
96
struct callchain_root *dst, struct callchain_root *src);
97
98
bool ip_callchain__valid(struct ip_callchain *chain,
99
const union perf_event *event);
100
/*
101
* Initialize a cursor before adding entries inside, but keep
102
* the previously allocated entries as a cache.
103
*/
104
static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
105
{
106
cursor->nr = 0;
107
cursor->last = &cursor->first;
108
}
109
110
int 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 */
114
static 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 */
121
static inline struct callchain_cursor_node *
122
callchain_cursor_current(struct callchain_cursor *cursor)
123
{
124
if (cursor->pos == cursor->nr)
125
return NULL;
126
127
return cursor->curr;
128
}
129
130
static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
131
{
132
cursor->curr = cursor->curr->next;
133
cursor->pos++;
134
}
135
#endif /* __PERF_CALLCHAIN_H */
136
137