xref: /OK3568_Linux_fs/kernel/tools/perf/util/callchain.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Handle the callchains from the stream in an ad-hoc radix tree and then
6*4882a593Smuzhiyun  * sort them in an rbtree.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Using a radix for code path provides a fast retrieval and factorizes
9*4882a593Smuzhiyun  * memory use. Also that lets us use the paths in a hierarchical graph view.
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <inttypes.h>
14*4882a593Smuzhiyun #include <stdlib.h>
15*4882a593Smuzhiyun #include <stdio.h>
16*4882a593Smuzhiyun #include <stdbool.h>
17*4882a593Smuzhiyun #include <errno.h>
18*4882a593Smuzhiyun #include <math.h>
19*4882a593Smuzhiyun #include <linux/string.h>
20*4882a593Smuzhiyun #include <linux/zalloc.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "asm/bug.h"
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include "debug.h"
25*4882a593Smuzhiyun #include "dso.h"
26*4882a593Smuzhiyun #include "event.h"
27*4882a593Smuzhiyun #include "hist.h"
28*4882a593Smuzhiyun #include "sort.h"
29*4882a593Smuzhiyun #include "machine.h"
30*4882a593Smuzhiyun #include "map.h"
31*4882a593Smuzhiyun #include "callchain.h"
32*4882a593Smuzhiyun #include "branch.h"
33*4882a593Smuzhiyun #include "symbol.h"
34*4882a593Smuzhiyun #include "../perf.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define CALLCHAIN_PARAM_DEFAULT			\
37*4882a593Smuzhiyun 	.mode		= CHAIN_GRAPH_ABS,	\
38*4882a593Smuzhiyun 	.min_percent	= 0.5,			\
39*4882a593Smuzhiyun 	.order		= ORDER_CALLEE,		\
40*4882a593Smuzhiyun 	.key		= CCKEY_FUNCTION,	\
41*4882a593Smuzhiyun 	.value		= CCVAL_PERCENT,	\
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun struct callchain_param callchain_param = {
44*4882a593Smuzhiyun 	CALLCHAIN_PARAM_DEFAULT
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun  * Are there any events usind DWARF callchains?
49*4882a593Smuzhiyun  *
50*4882a593Smuzhiyun  * I.e.
51*4882a593Smuzhiyun  *
52*4882a593Smuzhiyun  * -e cycles/call-graph=dwarf/
53*4882a593Smuzhiyun  */
54*4882a593Smuzhiyun bool dwarf_callchain_users;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun struct callchain_param callchain_param_default = {
57*4882a593Smuzhiyun 	CALLCHAIN_PARAM_DEFAULT
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun __thread struct callchain_cursor callchain_cursor;
61*4882a593Smuzhiyun 
parse_callchain_record_opt(const char * arg,struct callchain_param * param)62*4882a593Smuzhiyun int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	return parse_callchain_record(arg, param);
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
parse_callchain_mode(const char * value)67*4882a593Smuzhiyun static int parse_callchain_mode(const char *value)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	if (!strncmp(value, "graph", strlen(value))) {
70*4882a593Smuzhiyun 		callchain_param.mode = CHAIN_GRAPH_ABS;
71*4882a593Smuzhiyun 		return 0;
72*4882a593Smuzhiyun 	}
73*4882a593Smuzhiyun 	if (!strncmp(value, "flat", strlen(value))) {
74*4882a593Smuzhiyun 		callchain_param.mode = CHAIN_FLAT;
75*4882a593Smuzhiyun 		return 0;
76*4882a593Smuzhiyun 	}
77*4882a593Smuzhiyun 	if (!strncmp(value, "fractal", strlen(value))) {
78*4882a593Smuzhiyun 		callchain_param.mode = CHAIN_GRAPH_REL;
79*4882a593Smuzhiyun 		return 0;
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 	if (!strncmp(value, "folded", strlen(value))) {
82*4882a593Smuzhiyun 		callchain_param.mode = CHAIN_FOLDED;
83*4882a593Smuzhiyun 		return 0;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 	return -1;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
parse_callchain_order(const char * value)88*4882a593Smuzhiyun static int parse_callchain_order(const char *value)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun 	if (!strncmp(value, "caller", strlen(value))) {
91*4882a593Smuzhiyun 		callchain_param.order = ORDER_CALLER;
92*4882a593Smuzhiyun 		callchain_param.order_set = true;
93*4882a593Smuzhiyun 		return 0;
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun 	if (!strncmp(value, "callee", strlen(value))) {
96*4882a593Smuzhiyun 		callchain_param.order = ORDER_CALLEE;
97*4882a593Smuzhiyun 		callchain_param.order_set = true;
98*4882a593Smuzhiyun 		return 0;
99*4882a593Smuzhiyun 	}
100*4882a593Smuzhiyun 	return -1;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun 
parse_callchain_sort_key(const char * value)103*4882a593Smuzhiyun static int parse_callchain_sort_key(const char *value)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun 	if (!strncmp(value, "function", strlen(value))) {
106*4882a593Smuzhiyun 		callchain_param.key = CCKEY_FUNCTION;
107*4882a593Smuzhiyun 		return 0;
108*4882a593Smuzhiyun 	}
109*4882a593Smuzhiyun 	if (!strncmp(value, "address", strlen(value))) {
110*4882a593Smuzhiyun 		callchain_param.key = CCKEY_ADDRESS;
111*4882a593Smuzhiyun 		return 0;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 	if (!strncmp(value, "srcline", strlen(value))) {
114*4882a593Smuzhiyun 		callchain_param.key = CCKEY_SRCLINE;
115*4882a593Smuzhiyun 		return 0;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 	if (!strncmp(value, "branch", strlen(value))) {
118*4882a593Smuzhiyun 		callchain_param.branch_callstack = 1;
119*4882a593Smuzhiyun 		return 0;
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 	return -1;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
parse_callchain_value(const char * value)124*4882a593Smuzhiyun static int parse_callchain_value(const char *value)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	if (!strncmp(value, "percent", strlen(value))) {
127*4882a593Smuzhiyun 		callchain_param.value = CCVAL_PERCENT;
128*4882a593Smuzhiyun 		return 0;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 	if (!strncmp(value, "period", strlen(value))) {
131*4882a593Smuzhiyun 		callchain_param.value = CCVAL_PERIOD;
132*4882a593Smuzhiyun 		return 0;
133*4882a593Smuzhiyun 	}
134*4882a593Smuzhiyun 	if (!strncmp(value, "count", strlen(value))) {
135*4882a593Smuzhiyun 		callchain_param.value = CCVAL_COUNT;
136*4882a593Smuzhiyun 		return 0;
137*4882a593Smuzhiyun 	}
138*4882a593Smuzhiyun 	return -1;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
get_stack_size(const char * str,unsigned long * _size)141*4882a593Smuzhiyun static int get_stack_size(const char *str, unsigned long *_size)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	char *endptr;
144*4882a593Smuzhiyun 	unsigned long size;
145*4882a593Smuzhiyun 	unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	size = strtoul(str, &endptr, 0);
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	do {
150*4882a593Smuzhiyun 		if (*endptr)
151*4882a593Smuzhiyun 			break;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		size = round_up(size, sizeof(u64));
154*4882a593Smuzhiyun 		if (!size || size > max_size)
155*4882a593Smuzhiyun 			break;
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 		*_size = size;
158*4882a593Smuzhiyun 		return 0;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	} while (0);
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 	pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
163*4882a593Smuzhiyun 	       max_size, str);
164*4882a593Smuzhiyun 	return -1;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun static int
__parse_callchain_report_opt(const char * arg,bool allow_record_opt)168*4882a593Smuzhiyun __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	char *tok;
171*4882a593Smuzhiyun 	char *endptr, *saveptr = NULL;
172*4882a593Smuzhiyun 	bool minpcnt_set = false;
173*4882a593Smuzhiyun 	bool record_opt_set = false;
174*4882a593Smuzhiyun 	bool try_stack_size = false;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	callchain_param.enabled = true;
177*4882a593Smuzhiyun 	symbol_conf.use_callchain = true;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (!arg)
180*4882a593Smuzhiyun 		return 0;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	while ((tok = strtok_r((char *)arg, ",", &saveptr)) != NULL) {
183*4882a593Smuzhiyun 		if (!strncmp(tok, "none", strlen(tok))) {
184*4882a593Smuzhiyun 			callchain_param.mode = CHAIN_NONE;
185*4882a593Smuzhiyun 			callchain_param.enabled = false;
186*4882a593Smuzhiyun 			symbol_conf.use_callchain = false;
187*4882a593Smuzhiyun 			return 0;
188*4882a593Smuzhiyun 		}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 		if (!parse_callchain_mode(tok) ||
191*4882a593Smuzhiyun 		    !parse_callchain_order(tok) ||
192*4882a593Smuzhiyun 		    !parse_callchain_sort_key(tok) ||
193*4882a593Smuzhiyun 		    !parse_callchain_value(tok)) {
194*4882a593Smuzhiyun 			/* parsing ok - move on to the next */
195*4882a593Smuzhiyun 			try_stack_size = false;
196*4882a593Smuzhiyun 			goto next;
197*4882a593Smuzhiyun 		} else if (allow_record_opt && !record_opt_set) {
198*4882a593Smuzhiyun 			if (parse_callchain_record(tok, &callchain_param))
199*4882a593Smuzhiyun 				goto try_numbers;
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 			/* assume that number followed by 'dwarf' is stack size */
202*4882a593Smuzhiyun 			if (callchain_param.record_mode == CALLCHAIN_DWARF)
203*4882a593Smuzhiyun 				try_stack_size = true;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 			record_opt_set = true;
206*4882a593Smuzhiyun 			goto next;
207*4882a593Smuzhiyun 		}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun try_numbers:
210*4882a593Smuzhiyun 		if (try_stack_size) {
211*4882a593Smuzhiyun 			unsigned long size = 0;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 			if (get_stack_size(tok, &size) < 0)
214*4882a593Smuzhiyun 				return -1;
215*4882a593Smuzhiyun 			callchain_param.dump_size = size;
216*4882a593Smuzhiyun 			try_stack_size = false;
217*4882a593Smuzhiyun 		} else if (!minpcnt_set) {
218*4882a593Smuzhiyun 			/* try to get the min percent */
219*4882a593Smuzhiyun 			callchain_param.min_percent = strtod(tok, &endptr);
220*4882a593Smuzhiyun 			if (tok == endptr)
221*4882a593Smuzhiyun 				return -1;
222*4882a593Smuzhiyun 			minpcnt_set = true;
223*4882a593Smuzhiyun 		} else {
224*4882a593Smuzhiyun 			/* try print limit at last */
225*4882a593Smuzhiyun 			callchain_param.print_limit = strtoul(tok, &endptr, 0);
226*4882a593Smuzhiyun 			if (tok == endptr)
227*4882a593Smuzhiyun 				return -1;
228*4882a593Smuzhiyun 		}
229*4882a593Smuzhiyun next:
230*4882a593Smuzhiyun 		arg = NULL;
231*4882a593Smuzhiyun 	}
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun 	if (callchain_register_param(&callchain_param) < 0) {
234*4882a593Smuzhiyun 		pr_err("Can't register callchain params\n");
235*4882a593Smuzhiyun 		return -1;
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 	return 0;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun 
parse_callchain_report_opt(const char * arg)240*4882a593Smuzhiyun int parse_callchain_report_opt(const char *arg)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	return __parse_callchain_report_opt(arg, false);
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
parse_callchain_top_opt(const char * arg)245*4882a593Smuzhiyun int parse_callchain_top_opt(const char *arg)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	return __parse_callchain_report_opt(arg, true);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
parse_callchain_record(const char * arg,struct callchain_param * param)250*4882a593Smuzhiyun int parse_callchain_record(const char *arg, struct callchain_param *param)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	char *tok, *name, *saveptr = NULL;
253*4882a593Smuzhiyun 	char *buf;
254*4882a593Smuzhiyun 	int ret = -1;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	/* We need buffer that we know we can write to. */
257*4882a593Smuzhiyun 	buf = malloc(strlen(arg) + 1);
258*4882a593Smuzhiyun 	if (!buf)
259*4882a593Smuzhiyun 		return -ENOMEM;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	strcpy(buf, arg);
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	tok = strtok_r((char *)buf, ",", &saveptr);
264*4882a593Smuzhiyun 	name = tok ? : (char *)buf;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	do {
267*4882a593Smuzhiyun 		/* Framepointer style */
268*4882a593Smuzhiyun 		if (!strncmp(name, "fp", sizeof("fp"))) {
269*4882a593Smuzhiyun 			if (!strtok_r(NULL, ",", &saveptr)) {
270*4882a593Smuzhiyun 				param->record_mode = CALLCHAIN_FP;
271*4882a593Smuzhiyun 				ret = 0;
272*4882a593Smuzhiyun 			} else
273*4882a593Smuzhiyun 				pr_err("callchain: No more arguments "
274*4882a593Smuzhiyun 				       "needed for --call-graph fp\n");
275*4882a593Smuzhiyun 			break;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 		/* Dwarf style */
278*4882a593Smuzhiyun 		} else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
279*4882a593Smuzhiyun 			const unsigned long default_stack_dump_size = 8192;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 			ret = 0;
282*4882a593Smuzhiyun 			param->record_mode = CALLCHAIN_DWARF;
283*4882a593Smuzhiyun 			param->dump_size = default_stack_dump_size;
284*4882a593Smuzhiyun 			dwarf_callchain_users = true;
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 			tok = strtok_r(NULL, ",", &saveptr);
287*4882a593Smuzhiyun 			if (tok) {
288*4882a593Smuzhiyun 				unsigned long size = 0;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 				ret = get_stack_size(tok, &size);
291*4882a593Smuzhiyun 				param->dump_size = size;
292*4882a593Smuzhiyun 			}
293*4882a593Smuzhiyun 		} else if (!strncmp(name, "lbr", sizeof("lbr"))) {
294*4882a593Smuzhiyun 			if (!strtok_r(NULL, ",", &saveptr)) {
295*4882a593Smuzhiyun 				param->record_mode = CALLCHAIN_LBR;
296*4882a593Smuzhiyun 				ret = 0;
297*4882a593Smuzhiyun 			} else
298*4882a593Smuzhiyun 				pr_err("callchain: No more arguments "
299*4882a593Smuzhiyun 					"needed for --call-graph lbr\n");
300*4882a593Smuzhiyun 			break;
301*4882a593Smuzhiyun 		} else {
302*4882a593Smuzhiyun 			pr_err("callchain: Unknown --call-graph option "
303*4882a593Smuzhiyun 			       "value: %s\n", arg);
304*4882a593Smuzhiyun 			break;
305*4882a593Smuzhiyun 		}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	} while (0);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	free(buf);
310*4882a593Smuzhiyun 	return ret;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
perf_callchain_config(const char * var,const char * value)313*4882a593Smuzhiyun int perf_callchain_config(const char *var, const char *value)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	char *endptr;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	if (!strstarts(var, "call-graph."))
318*4882a593Smuzhiyun 		return 0;
319*4882a593Smuzhiyun 	var += sizeof("call-graph.") - 1;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	if (!strcmp(var, "record-mode"))
322*4882a593Smuzhiyun 		return parse_callchain_record_opt(value, &callchain_param);
323*4882a593Smuzhiyun 	if (!strcmp(var, "dump-size")) {
324*4882a593Smuzhiyun 		unsigned long size = 0;
325*4882a593Smuzhiyun 		int ret;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 		ret = get_stack_size(value, &size);
328*4882a593Smuzhiyun 		callchain_param.dump_size = size;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 		return ret;
331*4882a593Smuzhiyun 	}
332*4882a593Smuzhiyun 	if (!strcmp(var, "print-type")){
333*4882a593Smuzhiyun 		int ret;
334*4882a593Smuzhiyun 		ret = parse_callchain_mode(value);
335*4882a593Smuzhiyun 		if (ret == -1)
336*4882a593Smuzhiyun 			pr_err("Invalid callchain mode: %s\n", value);
337*4882a593Smuzhiyun 		return ret;
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 	if (!strcmp(var, "order")){
340*4882a593Smuzhiyun 		int ret;
341*4882a593Smuzhiyun 		ret = parse_callchain_order(value);
342*4882a593Smuzhiyun 		if (ret == -1)
343*4882a593Smuzhiyun 			pr_err("Invalid callchain order: %s\n", value);
344*4882a593Smuzhiyun 		return ret;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 	if (!strcmp(var, "sort-key")){
347*4882a593Smuzhiyun 		int ret;
348*4882a593Smuzhiyun 		ret = parse_callchain_sort_key(value);
349*4882a593Smuzhiyun 		if (ret == -1)
350*4882a593Smuzhiyun 			pr_err("Invalid callchain sort key: %s\n", value);
351*4882a593Smuzhiyun 		return ret;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun 	if (!strcmp(var, "threshold")) {
354*4882a593Smuzhiyun 		callchain_param.min_percent = strtod(value, &endptr);
355*4882a593Smuzhiyun 		if (value == endptr) {
356*4882a593Smuzhiyun 			pr_err("Invalid callchain threshold: %s\n", value);
357*4882a593Smuzhiyun 			return -1;
358*4882a593Smuzhiyun 		}
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 	if (!strcmp(var, "print-limit")) {
361*4882a593Smuzhiyun 		callchain_param.print_limit = strtod(value, &endptr);
362*4882a593Smuzhiyun 		if (value == endptr) {
363*4882a593Smuzhiyun 			pr_err("Invalid callchain print limit: %s\n", value);
364*4882a593Smuzhiyun 			return -1;
365*4882a593Smuzhiyun 		}
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	return 0;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun static void
rb_insert_callchain(struct rb_root * root,struct callchain_node * chain,enum chain_mode mode)372*4882a593Smuzhiyun rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
373*4882a593Smuzhiyun 		    enum chain_mode mode)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	struct rb_node **p = &root->rb_node;
376*4882a593Smuzhiyun 	struct rb_node *parent = NULL;
377*4882a593Smuzhiyun 	struct callchain_node *rnode;
378*4882a593Smuzhiyun 	u64 chain_cumul = callchain_cumul_hits(chain);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	while (*p) {
381*4882a593Smuzhiyun 		u64 rnode_cumul;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 		parent = *p;
384*4882a593Smuzhiyun 		rnode = rb_entry(parent, struct callchain_node, rb_node);
385*4882a593Smuzhiyun 		rnode_cumul = callchain_cumul_hits(rnode);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 		switch (mode) {
388*4882a593Smuzhiyun 		case CHAIN_FLAT:
389*4882a593Smuzhiyun 		case CHAIN_FOLDED:
390*4882a593Smuzhiyun 			if (rnode->hit < chain->hit)
391*4882a593Smuzhiyun 				p = &(*p)->rb_left;
392*4882a593Smuzhiyun 			else
393*4882a593Smuzhiyun 				p = &(*p)->rb_right;
394*4882a593Smuzhiyun 			break;
395*4882a593Smuzhiyun 		case CHAIN_GRAPH_ABS: /* Falldown */
396*4882a593Smuzhiyun 		case CHAIN_GRAPH_REL:
397*4882a593Smuzhiyun 			if (rnode_cumul < chain_cumul)
398*4882a593Smuzhiyun 				p = &(*p)->rb_left;
399*4882a593Smuzhiyun 			else
400*4882a593Smuzhiyun 				p = &(*p)->rb_right;
401*4882a593Smuzhiyun 			break;
402*4882a593Smuzhiyun 		case CHAIN_NONE:
403*4882a593Smuzhiyun 		default:
404*4882a593Smuzhiyun 			break;
405*4882a593Smuzhiyun 		}
406*4882a593Smuzhiyun 	}
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	rb_link_node(&chain->rb_node, parent, p);
409*4882a593Smuzhiyun 	rb_insert_color(&chain->rb_node, root);
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun static void
__sort_chain_flat(struct rb_root * rb_root,struct callchain_node * node,u64 min_hit)413*4882a593Smuzhiyun __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
414*4882a593Smuzhiyun 		  u64 min_hit)
415*4882a593Smuzhiyun {
416*4882a593Smuzhiyun 	struct rb_node *n;
417*4882a593Smuzhiyun 	struct callchain_node *child;
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	n = rb_first(&node->rb_root_in);
420*4882a593Smuzhiyun 	while (n) {
421*4882a593Smuzhiyun 		child = rb_entry(n, struct callchain_node, rb_node_in);
422*4882a593Smuzhiyun 		n = rb_next(n);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 		__sort_chain_flat(rb_root, child, min_hit);
425*4882a593Smuzhiyun 	}
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	if (node->hit && node->hit >= min_hit)
428*4882a593Smuzhiyun 		rb_insert_callchain(rb_root, node, CHAIN_FLAT);
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun /*
432*4882a593Smuzhiyun  * Once we get every callchains from the stream, we can now
433*4882a593Smuzhiyun  * sort them by hit
434*4882a593Smuzhiyun  */
435*4882a593Smuzhiyun static void
sort_chain_flat(struct rb_root * rb_root,struct callchain_root * root,u64 min_hit,struct callchain_param * param __maybe_unused)436*4882a593Smuzhiyun sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
437*4882a593Smuzhiyun 		u64 min_hit, struct callchain_param *param __maybe_unused)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	*rb_root = RB_ROOT;
440*4882a593Smuzhiyun 	__sort_chain_flat(rb_root, &root->node, min_hit);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun 
__sort_chain_graph_abs(struct callchain_node * node,u64 min_hit)443*4882a593Smuzhiyun static void __sort_chain_graph_abs(struct callchain_node *node,
444*4882a593Smuzhiyun 				   u64 min_hit)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun 	struct rb_node *n;
447*4882a593Smuzhiyun 	struct callchain_node *child;
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 	node->rb_root = RB_ROOT;
450*4882a593Smuzhiyun 	n = rb_first(&node->rb_root_in);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	while (n) {
453*4882a593Smuzhiyun 		child = rb_entry(n, struct callchain_node, rb_node_in);
454*4882a593Smuzhiyun 		n = rb_next(n);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 		__sort_chain_graph_abs(child, min_hit);
457*4882a593Smuzhiyun 		if (callchain_cumul_hits(child) >= min_hit)
458*4882a593Smuzhiyun 			rb_insert_callchain(&node->rb_root, child,
459*4882a593Smuzhiyun 					    CHAIN_GRAPH_ABS);
460*4882a593Smuzhiyun 	}
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun static void
sort_chain_graph_abs(struct rb_root * rb_root,struct callchain_root * chain_root,u64 min_hit,struct callchain_param * param __maybe_unused)464*4882a593Smuzhiyun sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
465*4882a593Smuzhiyun 		     u64 min_hit, struct callchain_param *param __maybe_unused)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun 	__sort_chain_graph_abs(&chain_root->node, min_hit);
468*4882a593Smuzhiyun 	rb_root->rb_node = chain_root->node.rb_root.rb_node;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
__sort_chain_graph_rel(struct callchain_node * node,double min_percent)471*4882a593Smuzhiyun static void __sort_chain_graph_rel(struct callchain_node *node,
472*4882a593Smuzhiyun 				   double min_percent)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun 	struct rb_node *n;
475*4882a593Smuzhiyun 	struct callchain_node *child;
476*4882a593Smuzhiyun 	u64 min_hit;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	node->rb_root = RB_ROOT;
479*4882a593Smuzhiyun 	min_hit = ceil(node->children_hit * min_percent);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	n = rb_first(&node->rb_root_in);
482*4882a593Smuzhiyun 	while (n) {
483*4882a593Smuzhiyun 		child = rb_entry(n, struct callchain_node, rb_node_in);
484*4882a593Smuzhiyun 		n = rb_next(n);
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 		__sort_chain_graph_rel(child, min_percent);
487*4882a593Smuzhiyun 		if (callchain_cumul_hits(child) >= min_hit)
488*4882a593Smuzhiyun 			rb_insert_callchain(&node->rb_root, child,
489*4882a593Smuzhiyun 					    CHAIN_GRAPH_REL);
490*4882a593Smuzhiyun 	}
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun static void
sort_chain_graph_rel(struct rb_root * rb_root,struct callchain_root * chain_root,u64 min_hit __maybe_unused,struct callchain_param * param)494*4882a593Smuzhiyun sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
495*4882a593Smuzhiyun 		     u64 min_hit __maybe_unused, struct callchain_param *param)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun 	__sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
498*4882a593Smuzhiyun 	rb_root->rb_node = chain_root->node.rb_root.rb_node;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
callchain_register_param(struct callchain_param * param)501*4882a593Smuzhiyun int callchain_register_param(struct callchain_param *param)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	switch (param->mode) {
504*4882a593Smuzhiyun 	case CHAIN_GRAPH_ABS:
505*4882a593Smuzhiyun 		param->sort = sort_chain_graph_abs;
506*4882a593Smuzhiyun 		break;
507*4882a593Smuzhiyun 	case CHAIN_GRAPH_REL:
508*4882a593Smuzhiyun 		param->sort = sort_chain_graph_rel;
509*4882a593Smuzhiyun 		break;
510*4882a593Smuzhiyun 	case CHAIN_FLAT:
511*4882a593Smuzhiyun 	case CHAIN_FOLDED:
512*4882a593Smuzhiyun 		param->sort = sort_chain_flat;
513*4882a593Smuzhiyun 		break;
514*4882a593Smuzhiyun 	case CHAIN_NONE:
515*4882a593Smuzhiyun 	default:
516*4882a593Smuzhiyun 		return -1;
517*4882a593Smuzhiyun 	}
518*4882a593Smuzhiyun 	return 0;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun /*
522*4882a593Smuzhiyun  * Create a child for a parent. If inherit_children, then the new child
523*4882a593Smuzhiyun  * will become the new parent of it's parent children
524*4882a593Smuzhiyun  */
525*4882a593Smuzhiyun static struct callchain_node *
create_child(struct callchain_node * parent,bool inherit_children)526*4882a593Smuzhiyun create_child(struct callchain_node *parent, bool inherit_children)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun 	struct callchain_node *new;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	new = zalloc(sizeof(*new));
531*4882a593Smuzhiyun 	if (!new) {
532*4882a593Smuzhiyun 		perror("not enough memory to create child for code path tree");
533*4882a593Smuzhiyun 		return NULL;
534*4882a593Smuzhiyun 	}
535*4882a593Smuzhiyun 	new->parent = parent;
536*4882a593Smuzhiyun 	INIT_LIST_HEAD(&new->val);
537*4882a593Smuzhiyun 	INIT_LIST_HEAD(&new->parent_val);
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	if (inherit_children) {
540*4882a593Smuzhiyun 		struct rb_node *n;
541*4882a593Smuzhiyun 		struct callchain_node *child;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 		new->rb_root_in = parent->rb_root_in;
544*4882a593Smuzhiyun 		parent->rb_root_in = RB_ROOT;
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 		n = rb_first(&new->rb_root_in);
547*4882a593Smuzhiyun 		while (n) {
548*4882a593Smuzhiyun 			child = rb_entry(n, struct callchain_node, rb_node_in);
549*4882a593Smuzhiyun 			child->parent = new;
550*4882a593Smuzhiyun 			n = rb_next(n);
551*4882a593Smuzhiyun 		}
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 		/* make it the first child */
554*4882a593Smuzhiyun 		rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
555*4882a593Smuzhiyun 		rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
556*4882a593Smuzhiyun 	}
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	return new;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun /*
563*4882a593Smuzhiyun  * Fill the node with callchain values
564*4882a593Smuzhiyun  */
565*4882a593Smuzhiyun static int
fill_node(struct callchain_node * node,struct callchain_cursor * cursor)566*4882a593Smuzhiyun fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun 	struct callchain_cursor_node *cursor_node;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	node->val_nr = cursor->nr - cursor->pos;
571*4882a593Smuzhiyun 	if (!node->val_nr)
572*4882a593Smuzhiyun 		pr_warning("Warning: empty node in callchain tree\n");
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	cursor_node = callchain_cursor_current(cursor);
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	while (cursor_node) {
577*4882a593Smuzhiyun 		struct callchain_list *call;
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 		call = zalloc(sizeof(*call));
580*4882a593Smuzhiyun 		if (!call) {
581*4882a593Smuzhiyun 			perror("not enough memory for the code path tree");
582*4882a593Smuzhiyun 			return -1;
583*4882a593Smuzhiyun 		}
584*4882a593Smuzhiyun 		call->ip = cursor_node->ip;
585*4882a593Smuzhiyun 		call->ms = cursor_node->ms;
586*4882a593Smuzhiyun 		map__get(call->ms.map);
587*4882a593Smuzhiyun 		call->srcline = cursor_node->srcline;
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun 		if (cursor_node->branch) {
590*4882a593Smuzhiyun 			call->branch_count = 1;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 			if (cursor_node->branch_from) {
593*4882a593Smuzhiyun 				/*
594*4882a593Smuzhiyun 				 * branch_from is set with value somewhere else
595*4882a593Smuzhiyun 				 * to imply it's "to" of a branch.
596*4882a593Smuzhiyun 				 */
597*4882a593Smuzhiyun 				call->brtype_stat.branch_to = true;
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun 				if (cursor_node->branch_flags.predicted)
600*4882a593Smuzhiyun 					call->predicted_count = 1;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 				if (cursor_node->branch_flags.abort)
603*4882a593Smuzhiyun 					call->abort_count = 1;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 				branch_type_count(&call->brtype_stat,
606*4882a593Smuzhiyun 						  &cursor_node->branch_flags,
607*4882a593Smuzhiyun 						  cursor_node->branch_from,
608*4882a593Smuzhiyun 						  cursor_node->ip);
609*4882a593Smuzhiyun 			} else {
610*4882a593Smuzhiyun 				/*
611*4882a593Smuzhiyun 				 * It's "from" of a branch
612*4882a593Smuzhiyun 				 */
613*4882a593Smuzhiyun 				call->brtype_stat.branch_to = false;
614*4882a593Smuzhiyun 				call->cycles_count =
615*4882a593Smuzhiyun 					cursor_node->branch_flags.cycles;
616*4882a593Smuzhiyun 				call->iter_count = cursor_node->nr_loop_iter;
617*4882a593Smuzhiyun 				call->iter_cycles = cursor_node->iter_cycles;
618*4882a593Smuzhiyun 			}
619*4882a593Smuzhiyun 		}
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 		list_add_tail(&call->list, &node->val);
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 		callchain_cursor_advance(cursor);
624*4882a593Smuzhiyun 		cursor_node = callchain_cursor_current(cursor);
625*4882a593Smuzhiyun 	}
626*4882a593Smuzhiyun 	return 0;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun static struct callchain_node *
add_child(struct callchain_node * parent,struct callchain_cursor * cursor,u64 period)630*4882a593Smuzhiyun add_child(struct callchain_node *parent,
631*4882a593Smuzhiyun 	  struct callchain_cursor *cursor,
632*4882a593Smuzhiyun 	  u64 period)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun 	struct callchain_node *new;
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	new = create_child(parent, false);
637*4882a593Smuzhiyun 	if (new == NULL)
638*4882a593Smuzhiyun 		return NULL;
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	if (fill_node(new, cursor) < 0) {
641*4882a593Smuzhiyun 		struct callchain_list *call, *tmp;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 		list_for_each_entry_safe(call, tmp, &new->val, list) {
644*4882a593Smuzhiyun 			list_del_init(&call->list);
645*4882a593Smuzhiyun 			map__zput(call->ms.map);
646*4882a593Smuzhiyun 			free(call);
647*4882a593Smuzhiyun 		}
648*4882a593Smuzhiyun 		free(new);
649*4882a593Smuzhiyun 		return NULL;
650*4882a593Smuzhiyun 	}
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	new->children_hit = 0;
653*4882a593Smuzhiyun 	new->hit = period;
654*4882a593Smuzhiyun 	new->children_count = 0;
655*4882a593Smuzhiyun 	new->count = 1;
656*4882a593Smuzhiyun 	return new;
657*4882a593Smuzhiyun }
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun enum match_result {
660*4882a593Smuzhiyun 	MATCH_ERROR  = -1,
661*4882a593Smuzhiyun 	MATCH_EQ,
662*4882a593Smuzhiyun 	MATCH_LT,
663*4882a593Smuzhiyun 	MATCH_GT,
664*4882a593Smuzhiyun };
665*4882a593Smuzhiyun 
match_chain_strings(const char * left,const char * right)666*4882a593Smuzhiyun static enum match_result match_chain_strings(const char *left,
667*4882a593Smuzhiyun 					     const char *right)
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun 	enum match_result ret = MATCH_EQ;
670*4882a593Smuzhiyun 	int cmp;
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	if (left && right)
673*4882a593Smuzhiyun 		cmp = strcmp(left, right);
674*4882a593Smuzhiyun 	else if (!left && right)
675*4882a593Smuzhiyun 		cmp = 1;
676*4882a593Smuzhiyun 	else if (left && !right)
677*4882a593Smuzhiyun 		cmp = -1;
678*4882a593Smuzhiyun 	else
679*4882a593Smuzhiyun 		return MATCH_ERROR;
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun 	if (cmp != 0)
682*4882a593Smuzhiyun 		ret = cmp < 0 ? MATCH_LT : MATCH_GT;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	return ret;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun /*
688*4882a593Smuzhiyun  * We need to always use relative addresses because we're aggregating
689*4882a593Smuzhiyun  * callchains from multiple threads, i.e. different address spaces, so
690*4882a593Smuzhiyun  * comparing absolute addresses make no sense as a symbol in a DSO may end up
691*4882a593Smuzhiyun  * in a different address when used in a different binary or even the same
692*4882a593Smuzhiyun  * binary but with some sort of address randomization technique, thus we need
693*4882a593Smuzhiyun  * to compare just relative addresses. -acme
694*4882a593Smuzhiyun  */
match_chain_dso_addresses(struct map * left_map,u64 left_ip,struct map * right_map,u64 right_ip)695*4882a593Smuzhiyun static enum match_result match_chain_dso_addresses(struct map *left_map, u64 left_ip,
696*4882a593Smuzhiyun 						   struct map *right_map, u64 right_ip)
697*4882a593Smuzhiyun {
698*4882a593Smuzhiyun 	struct dso *left_dso = left_map ? left_map->dso : NULL;
699*4882a593Smuzhiyun 	struct dso *right_dso = right_map ? right_map->dso : NULL;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	if (left_dso != right_dso)
702*4882a593Smuzhiyun 		return left_dso < right_dso ? MATCH_LT : MATCH_GT;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	if (left_ip != right_ip)
705*4882a593Smuzhiyun  		return left_ip < right_ip ? MATCH_LT : MATCH_GT;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	return MATCH_EQ;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun 
match_chain(struct callchain_cursor_node * node,struct callchain_list * cnode)710*4882a593Smuzhiyun static enum match_result match_chain(struct callchain_cursor_node *node,
711*4882a593Smuzhiyun 				     struct callchain_list *cnode)
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun 	enum match_result match = MATCH_ERROR;
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 	switch (callchain_param.key) {
716*4882a593Smuzhiyun 	case CCKEY_SRCLINE:
717*4882a593Smuzhiyun 		match = match_chain_strings(cnode->srcline, node->srcline);
718*4882a593Smuzhiyun 		if (match != MATCH_ERROR)
719*4882a593Smuzhiyun 			break;
720*4882a593Smuzhiyun 		/* otherwise fall-back to symbol-based comparison below */
721*4882a593Smuzhiyun 		__fallthrough;
722*4882a593Smuzhiyun 	case CCKEY_FUNCTION:
723*4882a593Smuzhiyun 		if (node->ms.sym && cnode->ms.sym) {
724*4882a593Smuzhiyun 			/*
725*4882a593Smuzhiyun 			 * Compare inlined frames based on their symbol name
726*4882a593Smuzhiyun 			 * because different inlined frames will have the same
727*4882a593Smuzhiyun 			 * symbol start. Otherwise do a faster comparison based
728*4882a593Smuzhiyun 			 * on the symbol start address.
729*4882a593Smuzhiyun 			 */
730*4882a593Smuzhiyun 			if (cnode->ms.sym->inlined || node->ms.sym->inlined) {
731*4882a593Smuzhiyun 				match = match_chain_strings(cnode->ms.sym->name,
732*4882a593Smuzhiyun 							    node->ms.sym->name);
733*4882a593Smuzhiyun 				if (match != MATCH_ERROR)
734*4882a593Smuzhiyun 					break;
735*4882a593Smuzhiyun 			} else {
736*4882a593Smuzhiyun 				match = match_chain_dso_addresses(cnode->ms.map, cnode->ms.sym->start,
737*4882a593Smuzhiyun 								  node->ms.map, node->ms.sym->start);
738*4882a593Smuzhiyun 				break;
739*4882a593Smuzhiyun 			}
740*4882a593Smuzhiyun 		}
741*4882a593Smuzhiyun 		/* otherwise fall-back to IP-based comparison below */
742*4882a593Smuzhiyun 		__fallthrough;
743*4882a593Smuzhiyun 	case CCKEY_ADDRESS:
744*4882a593Smuzhiyun 	default:
745*4882a593Smuzhiyun 		match = match_chain_dso_addresses(cnode->ms.map, cnode->ip, node->ms.map, node->ip);
746*4882a593Smuzhiyun 		break;
747*4882a593Smuzhiyun 	}
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	if (match == MATCH_EQ && node->branch) {
750*4882a593Smuzhiyun 		cnode->branch_count++;
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 		if (node->branch_from) {
753*4882a593Smuzhiyun 			/*
754*4882a593Smuzhiyun 			 * It's "to" of a branch
755*4882a593Smuzhiyun 			 */
756*4882a593Smuzhiyun 			cnode->brtype_stat.branch_to = true;
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 			if (node->branch_flags.predicted)
759*4882a593Smuzhiyun 				cnode->predicted_count++;
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 			if (node->branch_flags.abort)
762*4882a593Smuzhiyun 				cnode->abort_count++;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 			branch_type_count(&cnode->brtype_stat,
765*4882a593Smuzhiyun 					  &node->branch_flags,
766*4882a593Smuzhiyun 					  node->branch_from,
767*4882a593Smuzhiyun 					  node->ip);
768*4882a593Smuzhiyun 		} else {
769*4882a593Smuzhiyun 			/*
770*4882a593Smuzhiyun 			 * It's "from" of a branch
771*4882a593Smuzhiyun 			 */
772*4882a593Smuzhiyun 			cnode->brtype_stat.branch_to = false;
773*4882a593Smuzhiyun 			cnode->cycles_count += node->branch_flags.cycles;
774*4882a593Smuzhiyun 			cnode->iter_count += node->nr_loop_iter;
775*4882a593Smuzhiyun 			cnode->iter_cycles += node->iter_cycles;
776*4882a593Smuzhiyun 			cnode->from_count++;
777*4882a593Smuzhiyun 		}
778*4882a593Smuzhiyun 	}
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun 	return match;
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun /*
784*4882a593Smuzhiyun  * Split the parent in two parts (a new child is created) and
785*4882a593Smuzhiyun  * give a part of its callchain to the created child.
786*4882a593Smuzhiyun  * Then create another child to host the given callchain of new branch
787*4882a593Smuzhiyun  */
788*4882a593Smuzhiyun static int
split_add_child(struct callchain_node * parent,struct callchain_cursor * cursor,struct callchain_list * to_split,u64 idx_parents,u64 idx_local,u64 period)789*4882a593Smuzhiyun split_add_child(struct callchain_node *parent,
790*4882a593Smuzhiyun 		struct callchain_cursor *cursor,
791*4882a593Smuzhiyun 		struct callchain_list *to_split,
792*4882a593Smuzhiyun 		u64 idx_parents, u64 idx_local, u64 period)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun 	struct callchain_node *new;
795*4882a593Smuzhiyun 	struct list_head *old_tail;
796*4882a593Smuzhiyun 	unsigned int idx_total = idx_parents + idx_local;
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	/* split */
799*4882a593Smuzhiyun 	new = create_child(parent, true);
800*4882a593Smuzhiyun 	if (new == NULL)
801*4882a593Smuzhiyun 		return -1;
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	/* split the callchain and move a part to the new child */
804*4882a593Smuzhiyun 	old_tail = parent->val.prev;
805*4882a593Smuzhiyun 	list_del_range(&to_split->list, old_tail);
806*4882a593Smuzhiyun 	new->val.next = &to_split->list;
807*4882a593Smuzhiyun 	new->val.prev = old_tail;
808*4882a593Smuzhiyun 	to_split->list.prev = &new->val;
809*4882a593Smuzhiyun 	old_tail->next = &new->val;
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun 	/* split the hits */
812*4882a593Smuzhiyun 	new->hit = parent->hit;
813*4882a593Smuzhiyun 	new->children_hit = parent->children_hit;
814*4882a593Smuzhiyun 	parent->children_hit = callchain_cumul_hits(new);
815*4882a593Smuzhiyun 	new->val_nr = parent->val_nr - idx_local;
816*4882a593Smuzhiyun 	parent->val_nr = idx_local;
817*4882a593Smuzhiyun 	new->count = parent->count;
818*4882a593Smuzhiyun 	new->children_count = parent->children_count;
819*4882a593Smuzhiyun 	parent->children_count = callchain_cumul_counts(new);
820*4882a593Smuzhiyun 
821*4882a593Smuzhiyun 	/* create a new child for the new branch if any */
822*4882a593Smuzhiyun 	if (idx_total < cursor->nr) {
823*4882a593Smuzhiyun 		struct callchain_node *first;
824*4882a593Smuzhiyun 		struct callchain_list *cnode;
825*4882a593Smuzhiyun 		struct callchain_cursor_node *node;
826*4882a593Smuzhiyun 		struct rb_node *p, **pp;
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 		parent->hit = 0;
829*4882a593Smuzhiyun 		parent->children_hit += period;
830*4882a593Smuzhiyun 		parent->count = 0;
831*4882a593Smuzhiyun 		parent->children_count += 1;
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun 		node = callchain_cursor_current(cursor);
834*4882a593Smuzhiyun 		new = add_child(parent, cursor, period);
835*4882a593Smuzhiyun 		if (new == NULL)
836*4882a593Smuzhiyun 			return -1;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 		/*
839*4882a593Smuzhiyun 		 * This is second child since we moved parent's children
840*4882a593Smuzhiyun 		 * to new (first) child above.
841*4882a593Smuzhiyun 		 */
842*4882a593Smuzhiyun 		p = parent->rb_root_in.rb_node;
843*4882a593Smuzhiyun 		first = rb_entry(p, struct callchain_node, rb_node_in);
844*4882a593Smuzhiyun 		cnode = list_first_entry(&first->val, struct callchain_list,
845*4882a593Smuzhiyun 					 list);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 		if (match_chain(node, cnode) == MATCH_LT)
848*4882a593Smuzhiyun 			pp = &p->rb_left;
849*4882a593Smuzhiyun 		else
850*4882a593Smuzhiyun 			pp = &p->rb_right;
851*4882a593Smuzhiyun 
852*4882a593Smuzhiyun 		rb_link_node(&new->rb_node_in, p, pp);
853*4882a593Smuzhiyun 		rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
854*4882a593Smuzhiyun 	} else {
855*4882a593Smuzhiyun 		parent->hit = period;
856*4882a593Smuzhiyun 		parent->count = 1;
857*4882a593Smuzhiyun 	}
858*4882a593Smuzhiyun 	return 0;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun static enum match_result
862*4882a593Smuzhiyun append_chain(struct callchain_node *root,
863*4882a593Smuzhiyun 	     struct callchain_cursor *cursor,
864*4882a593Smuzhiyun 	     u64 period);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun static int
append_chain_children(struct callchain_node * root,struct callchain_cursor * cursor,u64 period)867*4882a593Smuzhiyun append_chain_children(struct callchain_node *root,
868*4882a593Smuzhiyun 		      struct callchain_cursor *cursor,
869*4882a593Smuzhiyun 		      u64 period)
870*4882a593Smuzhiyun {
871*4882a593Smuzhiyun 	struct callchain_node *rnode;
872*4882a593Smuzhiyun 	struct callchain_cursor_node *node;
873*4882a593Smuzhiyun 	struct rb_node **p = &root->rb_root_in.rb_node;
874*4882a593Smuzhiyun 	struct rb_node *parent = NULL;
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun 	node = callchain_cursor_current(cursor);
877*4882a593Smuzhiyun 	if (!node)
878*4882a593Smuzhiyun 		return -1;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun 	/* lookup in childrens */
881*4882a593Smuzhiyun 	while (*p) {
882*4882a593Smuzhiyun 		enum match_result ret;
883*4882a593Smuzhiyun 
884*4882a593Smuzhiyun 		parent = *p;
885*4882a593Smuzhiyun 		rnode = rb_entry(parent, struct callchain_node, rb_node_in);
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 		/* If at least first entry matches, rely to children */
888*4882a593Smuzhiyun 		ret = append_chain(rnode, cursor, period);
889*4882a593Smuzhiyun 		if (ret == MATCH_EQ)
890*4882a593Smuzhiyun 			goto inc_children_hit;
891*4882a593Smuzhiyun 		if (ret == MATCH_ERROR)
892*4882a593Smuzhiyun 			return -1;
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 		if (ret == MATCH_LT)
895*4882a593Smuzhiyun 			p = &parent->rb_left;
896*4882a593Smuzhiyun 		else
897*4882a593Smuzhiyun 			p = &parent->rb_right;
898*4882a593Smuzhiyun 	}
899*4882a593Smuzhiyun 	/* nothing in children, add to the current node */
900*4882a593Smuzhiyun 	rnode = add_child(root, cursor, period);
901*4882a593Smuzhiyun 	if (rnode == NULL)
902*4882a593Smuzhiyun 		return -1;
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	rb_link_node(&rnode->rb_node_in, parent, p);
905*4882a593Smuzhiyun 	rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
906*4882a593Smuzhiyun 
907*4882a593Smuzhiyun inc_children_hit:
908*4882a593Smuzhiyun 	root->children_hit += period;
909*4882a593Smuzhiyun 	root->children_count++;
910*4882a593Smuzhiyun 	return 0;
911*4882a593Smuzhiyun }
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun static enum match_result
append_chain(struct callchain_node * root,struct callchain_cursor * cursor,u64 period)914*4882a593Smuzhiyun append_chain(struct callchain_node *root,
915*4882a593Smuzhiyun 	     struct callchain_cursor *cursor,
916*4882a593Smuzhiyun 	     u64 period)
917*4882a593Smuzhiyun {
918*4882a593Smuzhiyun 	struct callchain_list *cnode;
919*4882a593Smuzhiyun 	u64 start = cursor->pos;
920*4882a593Smuzhiyun 	bool found = false;
921*4882a593Smuzhiyun 	u64 matches;
922*4882a593Smuzhiyun 	enum match_result cmp = MATCH_ERROR;
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	/*
925*4882a593Smuzhiyun 	 * Lookup in the current node
926*4882a593Smuzhiyun 	 * If we have a symbol, then compare the start to match
927*4882a593Smuzhiyun 	 * anywhere inside a function, unless function
928*4882a593Smuzhiyun 	 * mode is disabled.
929*4882a593Smuzhiyun 	 */
930*4882a593Smuzhiyun 	list_for_each_entry(cnode, &root->val, list) {
931*4882a593Smuzhiyun 		struct callchain_cursor_node *node;
932*4882a593Smuzhiyun 
933*4882a593Smuzhiyun 		node = callchain_cursor_current(cursor);
934*4882a593Smuzhiyun 		if (!node)
935*4882a593Smuzhiyun 			break;
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun 		cmp = match_chain(node, cnode);
938*4882a593Smuzhiyun 		if (cmp != MATCH_EQ)
939*4882a593Smuzhiyun 			break;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 		found = true;
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 		callchain_cursor_advance(cursor);
944*4882a593Smuzhiyun 	}
945*4882a593Smuzhiyun 
946*4882a593Smuzhiyun 	/* matches not, relay no the parent */
947*4882a593Smuzhiyun 	if (!found) {
948*4882a593Smuzhiyun 		WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n");
949*4882a593Smuzhiyun 		return cmp;
950*4882a593Smuzhiyun 	}
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	matches = cursor->pos - start;
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 	/* we match only a part of the node. Split it and add the new chain */
955*4882a593Smuzhiyun 	if (matches < root->val_nr) {
956*4882a593Smuzhiyun 		if (split_add_child(root, cursor, cnode, start, matches,
957*4882a593Smuzhiyun 				    period) < 0)
958*4882a593Smuzhiyun 			return MATCH_ERROR;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun 		return MATCH_EQ;
961*4882a593Smuzhiyun 	}
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	/* we match 100% of the path, increment the hit */
964*4882a593Smuzhiyun 	if (matches == root->val_nr && cursor->pos == cursor->nr) {
965*4882a593Smuzhiyun 		root->hit += period;
966*4882a593Smuzhiyun 		root->count++;
967*4882a593Smuzhiyun 		return MATCH_EQ;
968*4882a593Smuzhiyun 	}
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun 	/* We match the node and still have a part remaining */
971*4882a593Smuzhiyun 	if (append_chain_children(root, cursor, period) < 0)
972*4882a593Smuzhiyun 		return MATCH_ERROR;
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun 	return MATCH_EQ;
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun 
callchain_append(struct callchain_root * root,struct callchain_cursor * cursor,u64 period)977*4882a593Smuzhiyun int callchain_append(struct callchain_root *root,
978*4882a593Smuzhiyun 		     struct callchain_cursor *cursor,
979*4882a593Smuzhiyun 		     u64 period)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun 	if (!cursor->nr)
982*4882a593Smuzhiyun 		return 0;
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun 	callchain_cursor_commit(cursor);
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun 	if (append_chain_children(&root->node, cursor, period) < 0)
987*4882a593Smuzhiyun 		return -1;
988*4882a593Smuzhiyun 
989*4882a593Smuzhiyun 	if (cursor->nr > root->max_depth)
990*4882a593Smuzhiyun 		root->max_depth = cursor->nr;
991*4882a593Smuzhiyun 
992*4882a593Smuzhiyun 	return 0;
993*4882a593Smuzhiyun }
994*4882a593Smuzhiyun 
995*4882a593Smuzhiyun static int
merge_chain_branch(struct callchain_cursor * cursor,struct callchain_node * dst,struct callchain_node * src)996*4882a593Smuzhiyun merge_chain_branch(struct callchain_cursor *cursor,
997*4882a593Smuzhiyun 		   struct callchain_node *dst, struct callchain_node *src)
998*4882a593Smuzhiyun {
999*4882a593Smuzhiyun 	struct callchain_cursor_node **old_last = cursor->last;
1000*4882a593Smuzhiyun 	struct callchain_node *child;
1001*4882a593Smuzhiyun 	struct callchain_list *list, *next_list;
1002*4882a593Smuzhiyun 	struct rb_node *n;
1003*4882a593Smuzhiyun 	int old_pos = cursor->nr;
1004*4882a593Smuzhiyun 	int err = 0;
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	list_for_each_entry_safe(list, next_list, &src->val, list) {
1007*4882a593Smuzhiyun 		callchain_cursor_append(cursor, list->ip, &list->ms,
1008*4882a593Smuzhiyun 					false, NULL, 0, 0, 0, list->srcline);
1009*4882a593Smuzhiyun 		list_del_init(&list->list);
1010*4882a593Smuzhiyun 		map__zput(list->ms.map);
1011*4882a593Smuzhiyun 		free(list);
1012*4882a593Smuzhiyun 	}
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun 	if (src->hit) {
1015*4882a593Smuzhiyun 		callchain_cursor_commit(cursor);
1016*4882a593Smuzhiyun 		if (append_chain_children(dst, cursor, src->hit) < 0)
1017*4882a593Smuzhiyun 			return -1;
1018*4882a593Smuzhiyun 	}
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 	n = rb_first(&src->rb_root_in);
1021*4882a593Smuzhiyun 	while (n) {
1022*4882a593Smuzhiyun 		child = container_of(n, struct callchain_node, rb_node_in);
1023*4882a593Smuzhiyun 		n = rb_next(n);
1024*4882a593Smuzhiyun 		rb_erase(&child->rb_node_in, &src->rb_root_in);
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 		err = merge_chain_branch(cursor, dst, child);
1027*4882a593Smuzhiyun 		if (err)
1028*4882a593Smuzhiyun 			break;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun 		free(child);
1031*4882a593Smuzhiyun 	}
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	cursor->nr = old_pos;
1034*4882a593Smuzhiyun 	cursor->last = old_last;
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun 	return err;
1037*4882a593Smuzhiyun }
1038*4882a593Smuzhiyun 
callchain_merge(struct callchain_cursor * cursor,struct callchain_root * dst,struct callchain_root * src)1039*4882a593Smuzhiyun int callchain_merge(struct callchain_cursor *cursor,
1040*4882a593Smuzhiyun 		    struct callchain_root *dst, struct callchain_root *src)
1041*4882a593Smuzhiyun {
1042*4882a593Smuzhiyun 	return merge_chain_branch(cursor, &dst->node, &src->node);
1043*4882a593Smuzhiyun }
1044*4882a593Smuzhiyun 
callchain_cursor_append(struct callchain_cursor * cursor,u64 ip,struct map_symbol * ms,bool branch,struct branch_flags * flags,int nr_loop_iter,u64 iter_cycles,u64 branch_from,const char * srcline)1045*4882a593Smuzhiyun int callchain_cursor_append(struct callchain_cursor *cursor,
1046*4882a593Smuzhiyun 			    u64 ip, struct map_symbol *ms,
1047*4882a593Smuzhiyun 			    bool branch, struct branch_flags *flags,
1048*4882a593Smuzhiyun 			    int nr_loop_iter, u64 iter_cycles, u64 branch_from,
1049*4882a593Smuzhiyun 			    const char *srcline)
1050*4882a593Smuzhiyun {
1051*4882a593Smuzhiyun 	struct callchain_cursor_node *node = *cursor->last;
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun 	if (!node) {
1054*4882a593Smuzhiyun 		node = calloc(1, sizeof(*node));
1055*4882a593Smuzhiyun 		if (!node)
1056*4882a593Smuzhiyun 			return -ENOMEM;
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun 		*cursor->last = node;
1059*4882a593Smuzhiyun 	}
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun 	node->ip = ip;
1062*4882a593Smuzhiyun 	map__zput(node->ms.map);
1063*4882a593Smuzhiyun 	node->ms = *ms;
1064*4882a593Smuzhiyun 	map__get(node->ms.map);
1065*4882a593Smuzhiyun 	node->branch = branch;
1066*4882a593Smuzhiyun 	node->nr_loop_iter = nr_loop_iter;
1067*4882a593Smuzhiyun 	node->iter_cycles = iter_cycles;
1068*4882a593Smuzhiyun 	node->srcline = srcline;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun 	if (flags)
1071*4882a593Smuzhiyun 		memcpy(&node->branch_flags, flags,
1072*4882a593Smuzhiyun 			sizeof(struct branch_flags));
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun 	node->branch_from = branch_from;
1075*4882a593Smuzhiyun 	cursor->nr++;
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun 	cursor->last = &node->next;
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun 	return 0;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun 
sample__resolve_callchain(struct perf_sample * sample,struct callchain_cursor * cursor,struct symbol ** parent,struct evsel * evsel,struct addr_location * al,int max_stack)1082*4882a593Smuzhiyun int sample__resolve_callchain(struct perf_sample *sample,
1083*4882a593Smuzhiyun 			      struct callchain_cursor *cursor, struct symbol **parent,
1084*4882a593Smuzhiyun 			      struct evsel *evsel, struct addr_location *al,
1085*4882a593Smuzhiyun 			      int max_stack)
1086*4882a593Smuzhiyun {
1087*4882a593Smuzhiyun 	if (sample->callchain == NULL && !symbol_conf.show_branchflag_count)
1088*4882a593Smuzhiyun 		return 0;
1089*4882a593Smuzhiyun 
1090*4882a593Smuzhiyun 	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
1091*4882a593Smuzhiyun 	    perf_hpp_list.parent || symbol_conf.show_branchflag_count) {
1092*4882a593Smuzhiyun 		return thread__resolve_callchain(al->thread, cursor, evsel, sample,
1093*4882a593Smuzhiyun 						 parent, al, max_stack);
1094*4882a593Smuzhiyun 	}
1095*4882a593Smuzhiyun 	return 0;
1096*4882a593Smuzhiyun }
1097*4882a593Smuzhiyun 
hist_entry__append_callchain(struct hist_entry * he,struct perf_sample * sample)1098*4882a593Smuzhiyun int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
1099*4882a593Smuzhiyun {
1100*4882a593Smuzhiyun 	if ((!symbol_conf.use_callchain || sample->callchain == NULL) &&
1101*4882a593Smuzhiyun 		!symbol_conf.show_branchflag_count)
1102*4882a593Smuzhiyun 		return 0;
1103*4882a593Smuzhiyun 	return callchain_append(he->callchain, &callchain_cursor, sample->period);
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun 
fill_callchain_info(struct addr_location * al,struct callchain_cursor_node * node,bool hide_unresolved)1106*4882a593Smuzhiyun int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
1107*4882a593Smuzhiyun 			bool hide_unresolved)
1108*4882a593Smuzhiyun {
1109*4882a593Smuzhiyun 	al->maps = node->ms.maps;
1110*4882a593Smuzhiyun 	al->map = node->ms.map;
1111*4882a593Smuzhiyun 	al->sym = node->ms.sym;
1112*4882a593Smuzhiyun 	al->srcline = node->srcline;
1113*4882a593Smuzhiyun 	al->addr = node->ip;
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	if (al->sym == NULL) {
1116*4882a593Smuzhiyun 		if (hide_unresolved)
1117*4882a593Smuzhiyun 			return 0;
1118*4882a593Smuzhiyun 		if (al->map == NULL)
1119*4882a593Smuzhiyun 			goto out;
1120*4882a593Smuzhiyun 	}
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun 	if (al->maps == &al->maps->machine->kmaps) {
1123*4882a593Smuzhiyun 		if (machine__is_host(al->maps->machine)) {
1124*4882a593Smuzhiyun 			al->cpumode = PERF_RECORD_MISC_KERNEL;
1125*4882a593Smuzhiyun 			al->level = 'k';
1126*4882a593Smuzhiyun 		} else {
1127*4882a593Smuzhiyun 			al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
1128*4882a593Smuzhiyun 			al->level = 'g';
1129*4882a593Smuzhiyun 		}
1130*4882a593Smuzhiyun 	} else {
1131*4882a593Smuzhiyun 		if (machine__is_host(al->maps->machine)) {
1132*4882a593Smuzhiyun 			al->cpumode = PERF_RECORD_MISC_USER;
1133*4882a593Smuzhiyun 			al->level = '.';
1134*4882a593Smuzhiyun 		} else if (perf_guest) {
1135*4882a593Smuzhiyun 			al->cpumode = PERF_RECORD_MISC_GUEST_USER;
1136*4882a593Smuzhiyun 			al->level = 'u';
1137*4882a593Smuzhiyun 		} else {
1138*4882a593Smuzhiyun 			al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
1139*4882a593Smuzhiyun 			al->level = 'H';
1140*4882a593Smuzhiyun 		}
1141*4882a593Smuzhiyun 	}
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun out:
1144*4882a593Smuzhiyun 	return 1;
1145*4882a593Smuzhiyun }
1146*4882a593Smuzhiyun 
callchain_list__sym_name(struct callchain_list * cl,char * bf,size_t bfsize,bool show_dso)1147*4882a593Smuzhiyun char *callchain_list__sym_name(struct callchain_list *cl,
1148*4882a593Smuzhiyun 			       char *bf, size_t bfsize, bool show_dso)
1149*4882a593Smuzhiyun {
1150*4882a593Smuzhiyun 	bool show_addr = callchain_param.key == CCKEY_ADDRESS;
1151*4882a593Smuzhiyun 	bool show_srcline = show_addr || callchain_param.key == CCKEY_SRCLINE;
1152*4882a593Smuzhiyun 	int printed;
1153*4882a593Smuzhiyun 
1154*4882a593Smuzhiyun 	if (cl->ms.sym) {
1155*4882a593Smuzhiyun 		const char *inlined = cl->ms.sym->inlined ? " (inlined)" : "";
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 		if (show_srcline && cl->srcline)
1158*4882a593Smuzhiyun 			printed = scnprintf(bf, bfsize, "%s %s%s",
1159*4882a593Smuzhiyun 					    cl->ms.sym->name, cl->srcline,
1160*4882a593Smuzhiyun 					    inlined);
1161*4882a593Smuzhiyun 		else
1162*4882a593Smuzhiyun 			printed = scnprintf(bf, bfsize, "%s%s",
1163*4882a593Smuzhiyun 					    cl->ms.sym->name, inlined);
1164*4882a593Smuzhiyun 	} else
1165*4882a593Smuzhiyun 		printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	if (show_dso)
1168*4882a593Smuzhiyun 		scnprintf(bf + printed, bfsize - printed, " %s",
1169*4882a593Smuzhiyun 			  cl->ms.map ?
1170*4882a593Smuzhiyun 			  cl->ms.map->dso->short_name :
1171*4882a593Smuzhiyun 			  "unknown");
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	return bf;
1174*4882a593Smuzhiyun }
1175*4882a593Smuzhiyun 
callchain_node__scnprintf_value(struct callchain_node * node,char * bf,size_t bfsize,u64 total)1176*4882a593Smuzhiyun char *callchain_node__scnprintf_value(struct callchain_node *node,
1177*4882a593Smuzhiyun 				      char *bf, size_t bfsize, u64 total)
1178*4882a593Smuzhiyun {
1179*4882a593Smuzhiyun 	double percent = 0.0;
1180*4882a593Smuzhiyun 	u64 period = callchain_cumul_hits(node);
1181*4882a593Smuzhiyun 	unsigned count = callchain_cumul_counts(node);
1182*4882a593Smuzhiyun 
1183*4882a593Smuzhiyun 	if (callchain_param.mode == CHAIN_FOLDED) {
1184*4882a593Smuzhiyun 		period = node->hit;
1185*4882a593Smuzhiyun 		count = node->count;
1186*4882a593Smuzhiyun 	}
1187*4882a593Smuzhiyun 
1188*4882a593Smuzhiyun 	switch (callchain_param.value) {
1189*4882a593Smuzhiyun 	case CCVAL_PERIOD:
1190*4882a593Smuzhiyun 		scnprintf(bf, bfsize, "%"PRIu64, period);
1191*4882a593Smuzhiyun 		break;
1192*4882a593Smuzhiyun 	case CCVAL_COUNT:
1193*4882a593Smuzhiyun 		scnprintf(bf, bfsize, "%u", count);
1194*4882a593Smuzhiyun 		break;
1195*4882a593Smuzhiyun 	case CCVAL_PERCENT:
1196*4882a593Smuzhiyun 	default:
1197*4882a593Smuzhiyun 		if (total)
1198*4882a593Smuzhiyun 			percent = period * 100.0 / total;
1199*4882a593Smuzhiyun 		scnprintf(bf, bfsize, "%.2f%%", percent);
1200*4882a593Smuzhiyun 		break;
1201*4882a593Smuzhiyun 	}
1202*4882a593Smuzhiyun 	return bf;
1203*4882a593Smuzhiyun }
1204*4882a593Smuzhiyun 
callchain_node__fprintf_value(struct callchain_node * node,FILE * fp,u64 total)1205*4882a593Smuzhiyun int callchain_node__fprintf_value(struct callchain_node *node,
1206*4882a593Smuzhiyun 				 FILE *fp, u64 total)
1207*4882a593Smuzhiyun {
1208*4882a593Smuzhiyun 	double percent = 0.0;
1209*4882a593Smuzhiyun 	u64 period = callchain_cumul_hits(node);
1210*4882a593Smuzhiyun 	unsigned count = callchain_cumul_counts(node);
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 	if (callchain_param.mode == CHAIN_FOLDED) {
1213*4882a593Smuzhiyun 		period = node->hit;
1214*4882a593Smuzhiyun 		count = node->count;
1215*4882a593Smuzhiyun 	}
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun 	switch (callchain_param.value) {
1218*4882a593Smuzhiyun 	case CCVAL_PERIOD:
1219*4882a593Smuzhiyun 		return fprintf(fp, "%"PRIu64, period);
1220*4882a593Smuzhiyun 	case CCVAL_COUNT:
1221*4882a593Smuzhiyun 		return fprintf(fp, "%u", count);
1222*4882a593Smuzhiyun 	case CCVAL_PERCENT:
1223*4882a593Smuzhiyun 	default:
1224*4882a593Smuzhiyun 		if (total)
1225*4882a593Smuzhiyun 			percent = period * 100.0 / total;
1226*4882a593Smuzhiyun 		return percent_color_fprintf(fp, "%.2f%%", percent);
1227*4882a593Smuzhiyun 	}
1228*4882a593Smuzhiyun 	return 0;
1229*4882a593Smuzhiyun }
1230*4882a593Smuzhiyun 
callchain_counts_value(struct callchain_node * node,u64 * branch_count,u64 * predicted_count,u64 * abort_count,u64 * cycles_count)1231*4882a593Smuzhiyun static void callchain_counts_value(struct callchain_node *node,
1232*4882a593Smuzhiyun 				   u64 *branch_count, u64 *predicted_count,
1233*4882a593Smuzhiyun 				   u64 *abort_count, u64 *cycles_count)
1234*4882a593Smuzhiyun {
1235*4882a593Smuzhiyun 	struct callchain_list *clist;
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun 	list_for_each_entry(clist, &node->val, list) {
1238*4882a593Smuzhiyun 		if (branch_count)
1239*4882a593Smuzhiyun 			*branch_count += clist->branch_count;
1240*4882a593Smuzhiyun 
1241*4882a593Smuzhiyun 		if (predicted_count)
1242*4882a593Smuzhiyun 			*predicted_count += clist->predicted_count;
1243*4882a593Smuzhiyun 
1244*4882a593Smuzhiyun 		if (abort_count)
1245*4882a593Smuzhiyun 			*abort_count += clist->abort_count;
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun 		if (cycles_count)
1248*4882a593Smuzhiyun 			*cycles_count += clist->cycles_count;
1249*4882a593Smuzhiyun 	}
1250*4882a593Smuzhiyun }
1251*4882a593Smuzhiyun 
callchain_node_branch_counts_cumul(struct callchain_node * node,u64 * branch_count,u64 * predicted_count,u64 * abort_count,u64 * cycles_count)1252*4882a593Smuzhiyun static int callchain_node_branch_counts_cumul(struct callchain_node *node,
1253*4882a593Smuzhiyun 					      u64 *branch_count,
1254*4882a593Smuzhiyun 					      u64 *predicted_count,
1255*4882a593Smuzhiyun 					      u64 *abort_count,
1256*4882a593Smuzhiyun 					      u64 *cycles_count)
1257*4882a593Smuzhiyun {
1258*4882a593Smuzhiyun 	struct callchain_node *child;
1259*4882a593Smuzhiyun 	struct rb_node *n;
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun 	n = rb_first(&node->rb_root_in);
1262*4882a593Smuzhiyun 	while (n) {
1263*4882a593Smuzhiyun 		child = rb_entry(n, struct callchain_node, rb_node_in);
1264*4882a593Smuzhiyun 		n = rb_next(n);
1265*4882a593Smuzhiyun 
1266*4882a593Smuzhiyun 		callchain_node_branch_counts_cumul(child, branch_count,
1267*4882a593Smuzhiyun 						   predicted_count,
1268*4882a593Smuzhiyun 						   abort_count,
1269*4882a593Smuzhiyun 						   cycles_count);
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun 		callchain_counts_value(child, branch_count,
1272*4882a593Smuzhiyun 				       predicted_count, abort_count,
1273*4882a593Smuzhiyun 				       cycles_count);
1274*4882a593Smuzhiyun 	}
1275*4882a593Smuzhiyun 
1276*4882a593Smuzhiyun 	return 0;
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun 
callchain_branch_counts(struct callchain_root * root,u64 * branch_count,u64 * predicted_count,u64 * abort_count,u64 * cycles_count)1279*4882a593Smuzhiyun int callchain_branch_counts(struct callchain_root *root,
1280*4882a593Smuzhiyun 			    u64 *branch_count, u64 *predicted_count,
1281*4882a593Smuzhiyun 			    u64 *abort_count, u64 *cycles_count)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun 	if (branch_count)
1284*4882a593Smuzhiyun 		*branch_count = 0;
1285*4882a593Smuzhiyun 
1286*4882a593Smuzhiyun 	if (predicted_count)
1287*4882a593Smuzhiyun 		*predicted_count = 0;
1288*4882a593Smuzhiyun 
1289*4882a593Smuzhiyun 	if (abort_count)
1290*4882a593Smuzhiyun 		*abort_count = 0;
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 	if (cycles_count)
1293*4882a593Smuzhiyun 		*cycles_count = 0;
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 	return callchain_node_branch_counts_cumul(&root->node,
1296*4882a593Smuzhiyun 						  branch_count,
1297*4882a593Smuzhiyun 						  predicted_count,
1298*4882a593Smuzhiyun 						  abort_count,
1299*4882a593Smuzhiyun 						  cycles_count);
1300*4882a593Smuzhiyun }
1301*4882a593Smuzhiyun 
count_pri64_printf(int idx,const char * str,u64 value,char * bf,int bfsize)1302*4882a593Smuzhiyun static int count_pri64_printf(int idx, const char *str, u64 value, char *bf, int bfsize)
1303*4882a593Smuzhiyun {
1304*4882a593Smuzhiyun 	int printed;
1305*4882a593Smuzhiyun 
1306*4882a593Smuzhiyun 	printed = scnprintf(bf, bfsize, "%s%s:%" PRId64 "", (idx) ? " " : " (", str, value);
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun 	return printed;
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun 
count_float_printf(int idx,const char * str,float value,char * bf,int bfsize,float threshold)1311*4882a593Smuzhiyun static int count_float_printf(int idx, const char *str, float value,
1312*4882a593Smuzhiyun 			      char *bf, int bfsize, float threshold)
1313*4882a593Smuzhiyun {
1314*4882a593Smuzhiyun 	int printed;
1315*4882a593Smuzhiyun 
1316*4882a593Smuzhiyun 	if (threshold != 0.0 && value < threshold)
1317*4882a593Smuzhiyun 		return 0;
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun 	printed = scnprintf(bf, bfsize, "%s%s:%.1f%%", (idx) ? " " : " (", str, value);
1320*4882a593Smuzhiyun 
1321*4882a593Smuzhiyun 	return printed;
1322*4882a593Smuzhiyun }
1323*4882a593Smuzhiyun 
branch_to_str(char * bf,int bfsize,u64 branch_count,u64 predicted_count,u64 abort_count,struct branch_type_stat * brtype_stat)1324*4882a593Smuzhiyun static int branch_to_str(char *bf, int bfsize,
1325*4882a593Smuzhiyun 			 u64 branch_count, u64 predicted_count,
1326*4882a593Smuzhiyun 			 u64 abort_count,
1327*4882a593Smuzhiyun 			 struct branch_type_stat *brtype_stat)
1328*4882a593Smuzhiyun {
1329*4882a593Smuzhiyun 	int printed, i = 0;
1330*4882a593Smuzhiyun 
1331*4882a593Smuzhiyun 	printed = branch_type_str(brtype_stat, bf, bfsize);
1332*4882a593Smuzhiyun 	if (printed)
1333*4882a593Smuzhiyun 		i++;
1334*4882a593Smuzhiyun 
1335*4882a593Smuzhiyun 	if (predicted_count < branch_count) {
1336*4882a593Smuzhiyun 		printed += count_float_printf(i++, "predicted",
1337*4882a593Smuzhiyun 				predicted_count * 100.0 / branch_count,
1338*4882a593Smuzhiyun 				bf + printed, bfsize - printed, 0.0);
1339*4882a593Smuzhiyun 	}
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun 	if (abort_count) {
1342*4882a593Smuzhiyun 		printed += count_float_printf(i++, "abort",
1343*4882a593Smuzhiyun 				abort_count * 100.0 / branch_count,
1344*4882a593Smuzhiyun 				bf + printed, bfsize - printed, 0.1);
1345*4882a593Smuzhiyun 	}
1346*4882a593Smuzhiyun 
1347*4882a593Smuzhiyun 	if (i)
1348*4882a593Smuzhiyun 		printed += scnprintf(bf + printed, bfsize - printed, ")");
1349*4882a593Smuzhiyun 
1350*4882a593Smuzhiyun 	return printed;
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun 
branch_from_str(char * bf,int bfsize,u64 branch_count,u64 cycles_count,u64 iter_count,u64 iter_cycles,u64 from_count)1353*4882a593Smuzhiyun static int branch_from_str(char *bf, int bfsize,
1354*4882a593Smuzhiyun 			   u64 branch_count,
1355*4882a593Smuzhiyun 			   u64 cycles_count, u64 iter_count,
1356*4882a593Smuzhiyun 			   u64 iter_cycles, u64 from_count)
1357*4882a593Smuzhiyun {
1358*4882a593Smuzhiyun 	int printed = 0, i = 0;
1359*4882a593Smuzhiyun 	u64 cycles, v = 0;
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun 	cycles = cycles_count / branch_count;
1362*4882a593Smuzhiyun 	if (cycles) {
1363*4882a593Smuzhiyun 		printed += count_pri64_printf(i++, "cycles",
1364*4882a593Smuzhiyun 				cycles,
1365*4882a593Smuzhiyun 				bf + printed, bfsize - printed);
1366*4882a593Smuzhiyun 	}
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun 	if (iter_count && from_count) {
1369*4882a593Smuzhiyun 		v = iter_count / from_count;
1370*4882a593Smuzhiyun 		if (v) {
1371*4882a593Smuzhiyun 			printed += count_pri64_printf(i++, "iter",
1372*4882a593Smuzhiyun 					v, bf + printed, bfsize - printed);
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun 			printed += count_pri64_printf(i++, "avg_cycles",
1375*4882a593Smuzhiyun 					iter_cycles / iter_count,
1376*4882a593Smuzhiyun 					bf + printed, bfsize - printed);
1377*4882a593Smuzhiyun 		}
1378*4882a593Smuzhiyun 	}
1379*4882a593Smuzhiyun 
1380*4882a593Smuzhiyun 	if (i)
1381*4882a593Smuzhiyun 		printed += scnprintf(bf + printed, bfsize - printed, ")");
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun 	return printed;
1384*4882a593Smuzhiyun }
1385*4882a593Smuzhiyun 
counts_str_build(char * bf,int bfsize,u64 branch_count,u64 predicted_count,u64 abort_count,u64 cycles_count,u64 iter_count,u64 iter_cycles,u64 from_count,struct branch_type_stat * brtype_stat)1386*4882a593Smuzhiyun static int counts_str_build(char *bf, int bfsize,
1387*4882a593Smuzhiyun 			     u64 branch_count, u64 predicted_count,
1388*4882a593Smuzhiyun 			     u64 abort_count, u64 cycles_count,
1389*4882a593Smuzhiyun 			     u64 iter_count, u64 iter_cycles,
1390*4882a593Smuzhiyun 			     u64 from_count,
1391*4882a593Smuzhiyun 			     struct branch_type_stat *brtype_stat)
1392*4882a593Smuzhiyun {
1393*4882a593Smuzhiyun 	int printed;
1394*4882a593Smuzhiyun 
1395*4882a593Smuzhiyun 	if (branch_count == 0)
1396*4882a593Smuzhiyun 		return scnprintf(bf, bfsize, " (calltrace)");
1397*4882a593Smuzhiyun 
1398*4882a593Smuzhiyun 	if (brtype_stat->branch_to) {
1399*4882a593Smuzhiyun 		printed = branch_to_str(bf, bfsize, branch_count,
1400*4882a593Smuzhiyun 				predicted_count, abort_count, brtype_stat);
1401*4882a593Smuzhiyun 	} else {
1402*4882a593Smuzhiyun 		printed = branch_from_str(bf, bfsize, branch_count,
1403*4882a593Smuzhiyun 				cycles_count, iter_count, iter_cycles,
1404*4882a593Smuzhiyun 				from_count);
1405*4882a593Smuzhiyun 	}
1406*4882a593Smuzhiyun 
1407*4882a593Smuzhiyun 	if (!printed)
1408*4882a593Smuzhiyun 		bf[0] = 0;
1409*4882a593Smuzhiyun 
1410*4882a593Smuzhiyun 	return printed;
1411*4882a593Smuzhiyun }
1412*4882a593Smuzhiyun 
callchain_counts_printf(FILE * fp,char * bf,int bfsize,u64 branch_count,u64 predicted_count,u64 abort_count,u64 cycles_count,u64 iter_count,u64 iter_cycles,u64 from_count,struct branch_type_stat * brtype_stat)1413*4882a593Smuzhiyun static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
1414*4882a593Smuzhiyun 				   u64 branch_count, u64 predicted_count,
1415*4882a593Smuzhiyun 				   u64 abort_count, u64 cycles_count,
1416*4882a593Smuzhiyun 				   u64 iter_count, u64 iter_cycles,
1417*4882a593Smuzhiyun 				   u64 from_count,
1418*4882a593Smuzhiyun 				   struct branch_type_stat *brtype_stat)
1419*4882a593Smuzhiyun {
1420*4882a593Smuzhiyun 	char str[256];
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	counts_str_build(str, sizeof(str), branch_count,
1423*4882a593Smuzhiyun 			 predicted_count, abort_count, cycles_count,
1424*4882a593Smuzhiyun 			 iter_count, iter_cycles, from_count, brtype_stat);
1425*4882a593Smuzhiyun 
1426*4882a593Smuzhiyun 	if (fp)
1427*4882a593Smuzhiyun 		return fprintf(fp, "%s", str);
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 	return scnprintf(bf, bfsize, "%s", str);
1430*4882a593Smuzhiyun }
1431*4882a593Smuzhiyun 
callchain_list_counts__printf_value(struct callchain_list * clist,FILE * fp,char * bf,int bfsize)1432*4882a593Smuzhiyun int callchain_list_counts__printf_value(struct callchain_list *clist,
1433*4882a593Smuzhiyun 					FILE *fp, char *bf, int bfsize)
1434*4882a593Smuzhiyun {
1435*4882a593Smuzhiyun 	u64 branch_count, predicted_count;
1436*4882a593Smuzhiyun 	u64 abort_count, cycles_count;
1437*4882a593Smuzhiyun 	u64 iter_count, iter_cycles;
1438*4882a593Smuzhiyun 	u64 from_count;
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun 	branch_count = clist->branch_count;
1441*4882a593Smuzhiyun 	predicted_count = clist->predicted_count;
1442*4882a593Smuzhiyun 	abort_count = clist->abort_count;
1443*4882a593Smuzhiyun 	cycles_count = clist->cycles_count;
1444*4882a593Smuzhiyun 	iter_count = clist->iter_count;
1445*4882a593Smuzhiyun 	iter_cycles = clist->iter_cycles;
1446*4882a593Smuzhiyun 	from_count = clist->from_count;
1447*4882a593Smuzhiyun 
1448*4882a593Smuzhiyun 	return callchain_counts_printf(fp, bf, bfsize, branch_count,
1449*4882a593Smuzhiyun 				       predicted_count, abort_count,
1450*4882a593Smuzhiyun 				       cycles_count, iter_count, iter_cycles,
1451*4882a593Smuzhiyun 				       from_count, &clist->brtype_stat);
1452*4882a593Smuzhiyun }
1453*4882a593Smuzhiyun 
free_callchain_node(struct callchain_node * node)1454*4882a593Smuzhiyun static void free_callchain_node(struct callchain_node *node)
1455*4882a593Smuzhiyun {
1456*4882a593Smuzhiyun 	struct callchain_list *list, *tmp;
1457*4882a593Smuzhiyun 	struct callchain_node *child;
1458*4882a593Smuzhiyun 	struct rb_node *n;
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun 	list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
1461*4882a593Smuzhiyun 		list_del_init(&list->list);
1462*4882a593Smuzhiyun 		map__zput(list->ms.map);
1463*4882a593Smuzhiyun 		free(list);
1464*4882a593Smuzhiyun 	}
1465*4882a593Smuzhiyun 
1466*4882a593Smuzhiyun 	list_for_each_entry_safe(list, tmp, &node->val, list) {
1467*4882a593Smuzhiyun 		list_del_init(&list->list);
1468*4882a593Smuzhiyun 		map__zput(list->ms.map);
1469*4882a593Smuzhiyun 		free(list);
1470*4882a593Smuzhiyun 	}
1471*4882a593Smuzhiyun 
1472*4882a593Smuzhiyun 	n = rb_first(&node->rb_root_in);
1473*4882a593Smuzhiyun 	while (n) {
1474*4882a593Smuzhiyun 		child = container_of(n, struct callchain_node, rb_node_in);
1475*4882a593Smuzhiyun 		n = rb_next(n);
1476*4882a593Smuzhiyun 		rb_erase(&child->rb_node_in, &node->rb_root_in);
1477*4882a593Smuzhiyun 
1478*4882a593Smuzhiyun 		free_callchain_node(child);
1479*4882a593Smuzhiyun 		free(child);
1480*4882a593Smuzhiyun 	}
1481*4882a593Smuzhiyun }
1482*4882a593Smuzhiyun 
free_callchain(struct callchain_root * root)1483*4882a593Smuzhiyun void free_callchain(struct callchain_root *root)
1484*4882a593Smuzhiyun {
1485*4882a593Smuzhiyun 	if (!symbol_conf.use_callchain)
1486*4882a593Smuzhiyun 		return;
1487*4882a593Smuzhiyun 
1488*4882a593Smuzhiyun 	free_callchain_node(&root->node);
1489*4882a593Smuzhiyun }
1490*4882a593Smuzhiyun 
decay_callchain_node(struct callchain_node * node)1491*4882a593Smuzhiyun static u64 decay_callchain_node(struct callchain_node *node)
1492*4882a593Smuzhiyun {
1493*4882a593Smuzhiyun 	struct callchain_node *child;
1494*4882a593Smuzhiyun 	struct rb_node *n;
1495*4882a593Smuzhiyun 	u64 child_hits = 0;
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun 	n = rb_first(&node->rb_root_in);
1498*4882a593Smuzhiyun 	while (n) {
1499*4882a593Smuzhiyun 		child = container_of(n, struct callchain_node, rb_node_in);
1500*4882a593Smuzhiyun 
1501*4882a593Smuzhiyun 		child_hits += decay_callchain_node(child);
1502*4882a593Smuzhiyun 		n = rb_next(n);
1503*4882a593Smuzhiyun 	}
1504*4882a593Smuzhiyun 
1505*4882a593Smuzhiyun 	node->hit = (node->hit * 7) / 8;
1506*4882a593Smuzhiyun 	node->children_hit = child_hits;
1507*4882a593Smuzhiyun 
1508*4882a593Smuzhiyun 	return node->hit;
1509*4882a593Smuzhiyun }
1510*4882a593Smuzhiyun 
decay_callchain(struct callchain_root * root)1511*4882a593Smuzhiyun void decay_callchain(struct callchain_root *root)
1512*4882a593Smuzhiyun {
1513*4882a593Smuzhiyun 	if (!symbol_conf.use_callchain)
1514*4882a593Smuzhiyun 		return;
1515*4882a593Smuzhiyun 
1516*4882a593Smuzhiyun 	decay_callchain_node(&root->node);
1517*4882a593Smuzhiyun }
1518*4882a593Smuzhiyun 
callchain_node__make_parent_list(struct callchain_node * node)1519*4882a593Smuzhiyun int callchain_node__make_parent_list(struct callchain_node *node)
1520*4882a593Smuzhiyun {
1521*4882a593Smuzhiyun 	struct callchain_node *parent = node->parent;
1522*4882a593Smuzhiyun 	struct callchain_list *chain, *new;
1523*4882a593Smuzhiyun 	LIST_HEAD(head);
1524*4882a593Smuzhiyun 
1525*4882a593Smuzhiyun 	while (parent) {
1526*4882a593Smuzhiyun 		list_for_each_entry_reverse(chain, &parent->val, list) {
1527*4882a593Smuzhiyun 			new = malloc(sizeof(*new));
1528*4882a593Smuzhiyun 			if (new == NULL)
1529*4882a593Smuzhiyun 				goto out;
1530*4882a593Smuzhiyun 			*new = *chain;
1531*4882a593Smuzhiyun 			new->has_children = false;
1532*4882a593Smuzhiyun 			map__get(new->ms.map);
1533*4882a593Smuzhiyun 			list_add_tail(&new->list, &head);
1534*4882a593Smuzhiyun 		}
1535*4882a593Smuzhiyun 		parent = parent->parent;
1536*4882a593Smuzhiyun 	}
1537*4882a593Smuzhiyun 
1538*4882a593Smuzhiyun 	list_for_each_entry_safe_reverse(chain, new, &head, list)
1539*4882a593Smuzhiyun 		list_move_tail(&chain->list, &node->parent_val);
1540*4882a593Smuzhiyun 
1541*4882a593Smuzhiyun 	if (!list_empty(&node->parent_val)) {
1542*4882a593Smuzhiyun 		chain = list_first_entry(&node->parent_val, struct callchain_list, list);
1543*4882a593Smuzhiyun 		chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 		chain = list_first_entry(&node->val, struct callchain_list, list);
1546*4882a593Smuzhiyun 		chain->has_children = false;
1547*4882a593Smuzhiyun 	}
1548*4882a593Smuzhiyun 	return 0;
1549*4882a593Smuzhiyun 
1550*4882a593Smuzhiyun out:
1551*4882a593Smuzhiyun 	list_for_each_entry_safe(chain, new, &head, list) {
1552*4882a593Smuzhiyun 		list_del_init(&chain->list);
1553*4882a593Smuzhiyun 		map__zput(chain->ms.map);
1554*4882a593Smuzhiyun 		free(chain);
1555*4882a593Smuzhiyun 	}
1556*4882a593Smuzhiyun 	return -ENOMEM;
1557*4882a593Smuzhiyun }
1558*4882a593Smuzhiyun 
callchain_cursor__copy(struct callchain_cursor * dst,struct callchain_cursor * src)1559*4882a593Smuzhiyun int callchain_cursor__copy(struct callchain_cursor *dst,
1560*4882a593Smuzhiyun 			   struct callchain_cursor *src)
1561*4882a593Smuzhiyun {
1562*4882a593Smuzhiyun 	int rc = 0;
1563*4882a593Smuzhiyun 
1564*4882a593Smuzhiyun 	callchain_cursor_reset(dst);
1565*4882a593Smuzhiyun 	callchain_cursor_commit(src);
1566*4882a593Smuzhiyun 
1567*4882a593Smuzhiyun 	while (true) {
1568*4882a593Smuzhiyun 		struct callchain_cursor_node *node;
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun 		node = callchain_cursor_current(src);
1571*4882a593Smuzhiyun 		if (node == NULL)
1572*4882a593Smuzhiyun 			break;
1573*4882a593Smuzhiyun 
1574*4882a593Smuzhiyun 		rc = callchain_cursor_append(dst, node->ip, &node->ms,
1575*4882a593Smuzhiyun 					     node->branch, &node->branch_flags,
1576*4882a593Smuzhiyun 					     node->nr_loop_iter,
1577*4882a593Smuzhiyun 					     node->iter_cycles,
1578*4882a593Smuzhiyun 					     node->branch_from, node->srcline);
1579*4882a593Smuzhiyun 		if (rc)
1580*4882a593Smuzhiyun 			break;
1581*4882a593Smuzhiyun 
1582*4882a593Smuzhiyun 		callchain_cursor_advance(src);
1583*4882a593Smuzhiyun 	}
1584*4882a593Smuzhiyun 
1585*4882a593Smuzhiyun 	return rc;
1586*4882a593Smuzhiyun }
1587*4882a593Smuzhiyun 
1588*4882a593Smuzhiyun /*
1589*4882a593Smuzhiyun  * Initialize a cursor before adding entries inside, but keep
1590*4882a593Smuzhiyun  * the previously allocated entries as a cache.
1591*4882a593Smuzhiyun  */
callchain_cursor_reset(struct callchain_cursor * cursor)1592*4882a593Smuzhiyun void callchain_cursor_reset(struct callchain_cursor *cursor)
1593*4882a593Smuzhiyun {
1594*4882a593Smuzhiyun 	struct callchain_cursor_node *node;
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun 	cursor->nr = 0;
1597*4882a593Smuzhiyun 	cursor->last = &cursor->first;
1598*4882a593Smuzhiyun 
1599*4882a593Smuzhiyun 	for (node = cursor->first; node != NULL; node = node->next)
1600*4882a593Smuzhiyun 		map__zput(node->ms.map);
1601*4882a593Smuzhiyun }
1602*4882a593Smuzhiyun 
callchain_param_setup(u64 sample_type)1603*4882a593Smuzhiyun void callchain_param_setup(u64 sample_type)
1604*4882a593Smuzhiyun {
1605*4882a593Smuzhiyun 	if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
1606*4882a593Smuzhiyun 		if ((sample_type & PERF_SAMPLE_REGS_USER) &&
1607*4882a593Smuzhiyun 		    (sample_type & PERF_SAMPLE_STACK_USER)) {
1608*4882a593Smuzhiyun 			callchain_param.record_mode = CALLCHAIN_DWARF;
1609*4882a593Smuzhiyun 			dwarf_callchain_users = true;
1610*4882a593Smuzhiyun 		} else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
1611*4882a593Smuzhiyun 			callchain_param.record_mode = CALLCHAIN_LBR;
1612*4882a593Smuzhiyun 		else
1613*4882a593Smuzhiyun 			callchain_param.record_mode = CALLCHAIN_FP;
1614*4882a593Smuzhiyun 	}
1615*4882a593Smuzhiyun }
1616*4882a593Smuzhiyun 
chain_match(struct callchain_list * base_chain,struct callchain_list * pair_chain)1617*4882a593Smuzhiyun static bool chain_match(struct callchain_list *base_chain,
1618*4882a593Smuzhiyun 			struct callchain_list *pair_chain)
1619*4882a593Smuzhiyun {
1620*4882a593Smuzhiyun 	enum match_result match;
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun 	match = match_chain_strings(base_chain->srcline,
1623*4882a593Smuzhiyun 				    pair_chain->srcline);
1624*4882a593Smuzhiyun 	if (match != MATCH_ERROR)
1625*4882a593Smuzhiyun 		return match == MATCH_EQ;
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun 	match = match_chain_dso_addresses(base_chain->ms.map,
1628*4882a593Smuzhiyun 					  base_chain->ip,
1629*4882a593Smuzhiyun 					  pair_chain->ms.map,
1630*4882a593Smuzhiyun 					  pair_chain->ip);
1631*4882a593Smuzhiyun 
1632*4882a593Smuzhiyun 	return match == MATCH_EQ;
1633*4882a593Smuzhiyun }
1634*4882a593Smuzhiyun 
callchain_cnode_matched(struct callchain_node * base_cnode,struct callchain_node * pair_cnode)1635*4882a593Smuzhiyun bool callchain_cnode_matched(struct callchain_node *base_cnode,
1636*4882a593Smuzhiyun 			     struct callchain_node *pair_cnode)
1637*4882a593Smuzhiyun {
1638*4882a593Smuzhiyun 	struct callchain_list *base_chain, *pair_chain;
1639*4882a593Smuzhiyun 	bool match = false;
1640*4882a593Smuzhiyun 
1641*4882a593Smuzhiyun 	pair_chain = list_first_entry(&pair_cnode->val,
1642*4882a593Smuzhiyun 				      struct callchain_list,
1643*4882a593Smuzhiyun 				      list);
1644*4882a593Smuzhiyun 
1645*4882a593Smuzhiyun 	list_for_each_entry(base_chain, &base_cnode->val, list) {
1646*4882a593Smuzhiyun 		if (&pair_chain->list == &pair_cnode->val)
1647*4882a593Smuzhiyun 			return false;
1648*4882a593Smuzhiyun 
1649*4882a593Smuzhiyun 		if (!base_chain->srcline || !pair_chain->srcline) {
1650*4882a593Smuzhiyun 			pair_chain = list_next_entry(pair_chain, list);
1651*4882a593Smuzhiyun 			continue;
1652*4882a593Smuzhiyun 		}
1653*4882a593Smuzhiyun 
1654*4882a593Smuzhiyun 		match = chain_match(base_chain, pair_chain);
1655*4882a593Smuzhiyun 		if (!match)
1656*4882a593Smuzhiyun 			return false;
1657*4882a593Smuzhiyun 
1658*4882a593Smuzhiyun 		pair_chain = list_next_entry(pair_chain, list);
1659*4882a593Smuzhiyun 	}
1660*4882a593Smuzhiyun 
1661*4882a593Smuzhiyun 	/*
1662*4882a593Smuzhiyun 	 * Say chain1 is ABC, chain2 is ABCD, we consider they are
1663*4882a593Smuzhiyun 	 * not fully matched.
1664*4882a593Smuzhiyun 	 */
1665*4882a593Smuzhiyun 	if (pair_chain && (&pair_chain->list != &pair_cnode->val))
1666*4882a593Smuzhiyun 		return false;
1667*4882a593Smuzhiyun 
1668*4882a593Smuzhiyun 	return match;
1669*4882a593Smuzhiyun }
1670*4882a593Smuzhiyun 
count_callchain_hits(struct hist_entry * he)1671*4882a593Smuzhiyun static u64 count_callchain_hits(struct hist_entry *he)
1672*4882a593Smuzhiyun {
1673*4882a593Smuzhiyun 	struct rb_root *root = &he->sorted_chain;
1674*4882a593Smuzhiyun 	struct rb_node *rb_node = rb_first(root);
1675*4882a593Smuzhiyun 	struct callchain_node *node;
1676*4882a593Smuzhiyun 	u64 chain_hits = 0;
1677*4882a593Smuzhiyun 
1678*4882a593Smuzhiyun 	while (rb_node) {
1679*4882a593Smuzhiyun 		node = rb_entry(rb_node, struct callchain_node, rb_node);
1680*4882a593Smuzhiyun 		chain_hits += node->hit;
1681*4882a593Smuzhiyun 		rb_node = rb_next(rb_node);
1682*4882a593Smuzhiyun 	}
1683*4882a593Smuzhiyun 
1684*4882a593Smuzhiyun 	return chain_hits;
1685*4882a593Smuzhiyun }
1686*4882a593Smuzhiyun 
callchain_total_hits(struct hists * hists)1687*4882a593Smuzhiyun u64 callchain_total_hits(struct hists *hists)
1688*4882a593Smuzhiyun {
1689*4882a593Smuzhiyun 	struct rb_node *next = rb_first_cached(&hists->entries);
1690*4882a593Smuzhiyun 	u64 chain_hits = 0;
1691*4882a593Smuzhiyun 
1692*4882a593Smuzhiyun 	while (next) {
1693*4882a593Smuzhiyun 		struct hist_entry *he = rb_entry(next, struct hist_entry,
1694*4882a593Smuzhiyun 						 rb_node);
1695*4882a593Smuzhiyun 
1696*4882a593Smuzhiyun 		chain_hits += count_callchain_hits(he);
1697*4882a593Smuzhiyun 		next = rb_next(&he->rb_node);
1698*4882a593Smuzhiyun 	}
1699*4882a593Smuzhiyun 
1700*4882a593Smuzhiyun 	return chain_hits;
1701*4882a593Smuzhiyun }
1702*4882a593Smuzhiyun 
callchain_avg_cycles(struct callchain_node * cnode)1703*4882a593Smuzhiyun s64 callchain_avg_cycles(struct callchain_node *cnode)
1704*4882a593Smuzhiyun {
1705*4882a593Smuzhiyun 	struct callchain_list *chain;
1706*4882a593Smuzhiyun 	s64 cycles = 0;
1707*4882a593Smuzhiyun 
1708*4882a593Smuzhiyun 	list_for_each_entry(chain, &cnode->val, list) {
1709*4882a593Smuzhiyun 		if (chain->srcline && chain->branch_count)
1710*4882a593Smuzhiyun 			cycles += chain->cycles_count / chain->branch_count;
1711*4882a593Smuzhiyun 	}
1712*4882a593Smuzhiyun 
1713*4882a593Smuzhiyun 	return cycles;
1714*4882a593Smuzhiyun }
1715