perf tools: Introduce bitmask'ed additional headers
[linux-2.6/x86.git] / tools / perf / util / hist.c
blob7393a02fd8d470fe9ac50340b41e61fe7564b804
1 #include "hist.h"
3 struct rb_root hist;
4 struct rb_root collapse_hists;
5 struct rb_root output_hists;
6 int callchain;
8 struct callchain_param callchain_param = {
9 .mode = CHAIN_GRAPH_REL,
10 .min_percent = 0.5
13 unsigned long total;
14 unsigned long total_mmap;
15 unsigned long total_comm;
16 unsigned long total_fork;
17 unsigned long total_unknown;
18 unsigned long total_lost;
21 * histogram, sorted on item, collects counts
24 struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
25 struct symbol *sym,
26 struct symbol *sym_parent,
27 u64 ip, u64 count, char level, bool *hit)
29 struct rb_node **p = &hist.rb_node;
30 struct rb_node *parent = NULL;
31 struct hist_entry *he;
32 struct hist_entry entry = {
33 .thread = thread,
34 .map = map,
35 .sym = sym,
36 .ip = ip,
37 .level = level,
38 .count = count,
39 .parent = sym_parent,
41 int cmp;
43 while (*p != NULL) {
44 parent = *p;
45 he = rb_entry(parent, struct hist_entry, rb_node);
47 cmp = hist_entry__cmp(&entry, he);
49 if (!cmp) {
50 *hit = true;
51 return he;
54 if (cmp < 0)
55 p = &(*p)->rb_left;
56 else
57 p = &(*p)->rb_right;
60 he = malloc(sizeof(*he));
61 if (!he)
62 return NULL;
63 *he = entry;
64 rb_link_node(&he->rb_node, parent, p);
65 rb_insert_color(&he->rb_node, &hist);
66 *hit = false;
67 return he;
70 int64_t
71 hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
73 struct sort_entry *se;
74 int64_t cmp = 0;
76 list_for_each_entry(se, &hist_entry__sort_list, list) {
77 cmp = se->cmp(left, right);
78 if (cmp)
79 break;
82 return cmp;
85 int64_t
86 hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
88 struct sort_entry *se;
89 int64_t cmp = 0;
91 list_for_each_entry(se, &hist_entry__sort_list, list) {
92 int64_t (*f)(struct hist_entry *, struct hist_entry *);
94 f = se->collapse ?: se->cmp;
96 cmp = f(left, right);
97 if (cmp)
98 break;
101 return cmp;
104 void hist_entry__free(struct hist_entry *he)
106 free(he);
110 * collapse the histogram
113 void collapse__insert_entry(struct hist_entry *he)
115 struct rb_node **p = &collapse_hists.rb_node;
116 struct rb_node *parent = NULL;
117 struct hist_entry *iter;
118 int64_t cmp;
120 while (*p != NULL) {
121 parent = *p;
122 iter = rb_entry(parent, struct hist_entry, rb_node);
124 cmp = hist_entry__collapse(iter, he);
126 if (!cmp) {
127 iter->count += he->count;
128 hist_entry__free(he);
129 return;
132 if (cmp < 0)
133 p = &(*p)->rb_left;
134 else
135 p = &(*p)->rb_right;
138 rb_link_node(&he->rb_node, parent, p);
139 rb_insert_color(&he->rb_node, &collapse_hists);
142 void collapse__resort(void)
144 struct rb_node *next;
145 struct hist_entry *n;
147 if (!sort__need_collapse)
148 return;
150 next = rb_first(&hist);
151 while (next) {
152 n = rb_entry(next, struct hist_entry, rb_node);
153 next = rb_next(&n->rb_node);
155 rb_erase(&n->rb_node, &hist);
156 collapse__insert_entry(n);
161 * reverse the map, sort on count.
164 void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
166 struct rb_node **p = &output_hists.rb_node;
167 struct rb_node *parent = NULL;
168 struct hist_entry *iter;
170 if (callchain)
171 callchain_param.sort(&he->sorted_chain, &he->callchain,
172 min_callchain_hits, &callchain_param);
174 while (*p != NULL) {
175 parent = *p;
176 iter = rb_entry(parent, struct hist_entry, rb_node);
178 if (he->count > iter->count)
179 p = &(*p)->rb_left;
180 else
181 p = &(*p)->rb_right;
184 rb_link_node(&he->rb_node, parent, p);
185 rb_insert_color(&he->rb_node, &output_hists);
188 void output__resort(u64 total_samples)
190 struct rb_node *next;
191 struct hist_entry *n;
192 struct rb_root *tree = &hist;
193 u64 min_callchain_hits;
195 min_callchain_hits =
196 total_samples * (callchain_param.min_percent / 100);
198 if (sort__need_collapse)
199 tree = &collapse_hists;
201 next = rb_first(tree);
203 while (next) {
204 n = rb_entry(next, struct hist_entry, rb_node);
205 next = rb_next(&n->rb_node);
207 rb_erase(&n->rb_node, tree);
208 output__insert_entry(n, min_callchain_hits);