xref: /OK3568_Linux_fs/kernel/tools/perf/util/block-info.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <stdlib.h>
3*4882a593Smuzhiyun #include <string.h>
4*4882a593Smuzhiyun #include <linux/zalloc.h>
5*4882a593Smuzhiyun #include "block-info.h"
6*4882a593Smuzhiyun #include "sort.h"
7*4882a593Smuzhiyun #include "annotate.h"
8*4882a593Smuzhiyun #include "symbol.h"
9*4882a593Smuzhiyun #include "dso.h"
10*4882a593Smuzhiyun #include "map.h"
11*4882a593Smuzhiyun #include "srcline.h"
12*4882a593Smuzhiyun #include "evlist.h"
13*4882a593Smuzhiyun #include "hist.h"
14*4882a593Smuzhiyun #include "ui/browsers/hists.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun static struct block_header_column {
17*4882a593Smuzhiyun 	const char *name;
18*4882a593Smuzhiyun 	int width;
19*4882a593Smuzhiyun } block_columns[PERF_HPP_REPORT__BLOCK_MAX_INDEX] = {
20*4882a593Smuzhiyun 	[PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT] = {
21*4882a593Smuzhiyun 		.name = "Sampled Cycles%",
22*4882a593Smuzhiyun 		.width = 15,
23*4882a593Smuzhiyun 	},
24*4882a593Smuzhiyun 	[PERF_HPP_REPORT__BLOCK_LBR_CYCLES] = {
25*4882a593Smuzhiyun 		.name = "Sampled Cycles",
26*4882a593Smuzhiyun 		.width = 14,
27*4882a593Smuzhiyun 	},
28*4882a593Smuzhiyun 	[PERF_HPP_REPORT__BLOCK_CYCLES_PCT] = {
29*4882a593Smuzhiyun 		.name = "Avg Cycles%",
30*4882a593Smuzhiyun 		.width = 11,
31*4882a593Smuzhiyun 	},
32*4882a593Smuzhiyun 	[PERF_HPP_REPORT__BLOCK_AVG_CYCLES] = {
33*4882a593Smuzhiyun 		.name = "Avg Cycles",
34*4882a593Smuzhiyun 		.width = 10,
35*4882a593Smuzhiyun 	},
36*4882a593Smuzhiyun 	[PERF_HPP_REPORT__BLOCK_RANGE] = {
37*4882a593Smuzhiyun 		.name = "[Program Block Range]",
38*4882a593Smuzhiyun 		.width = 70,
39*4882a593Smuzhiyun 	},
40*4882a593Smuzhiyun 	[PERF_HPP_REPORT__BLOCK_DSO] = {
41*4882a593Smuzhiyun 		.name = "Shared Object",
42*4882a593Smuzhiyun 		.width = 20,
43*4882a593Smuzhiyun 	}
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun 
block_info__get(struct block_info * bi)46*4882a593Smuzhiyun struct block_info *block_info__get(struct block_info *bi)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	if (bi)
49*4882a593Smuzhiyun 		refcount_inc(&bi->refcnt);
50*4882a593Smuzhiyun 	return bi;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
block_info__put(struct block_info * bi)53*4882a593Smuzhiyun void block_info__put(struct block_info *bi)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	if (bi && refcount_dec_and_test(&bi->refcnt))
56*4882a593Smuzhiyun 		free(bi);
57*4882a593Smuzhiyun }
58*4882a593Smuzhiyun 
block_info__new(void)59*4882a593Smuzhiyun struct block_info *block_info__new(void)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct block_info *bi = zalloc(sizeof(*bi));
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (bi)
64*4882a593Smuzhiyun 		refcount_set(&bi->refcnt, 1);
65*4882a593Smuzhiyun 	return bi;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
__block_info__cmp(struct hist_entry * left,struct hist_entry * right)68*4882a593Smuzhiyun int64_t __block_info__cmp(struct hist_entry *left, struct hist_entry *right)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	struct block_info *bi_l = left->block_info;
71*4882a593Smuzhiyun 	struct block_info *bi_r = right->block_info;
72*4882a593Smuzhiyun 	int cmp;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	if (!bi_l->sym || !bi_r->sym) {
75*4882a593Smuzhiyun 		if (!bi_l->sym && !bi_r->sym)
76*4882a593Smuzhiyun 			return -1;
77*4882a593Smuzhiyun 		else if (!bi_l->sym)
78*4882a593Smuzhiyun 			return -1;
79*4882a593Smuzhiyun 		else
80*4882a593Smuzhiyun 			return 1;
81*4882a593Smuzhiyun 	}
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	cmp = strcmp(bi_l->sym->name, bi_r->sym->name);
84*4882a593Smuzhiyun 	if (cmp)
85*4882a593Smuzhiyun 		return cmp;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (bi_l->start != bi_r->start)
88*4882a593Smuzhiyun 		return (int64_t)(bi_r->start - bi_l->start);
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	return (int64_t)(bi_r->end - bi_l->end);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
block_info__cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)93*4882a593Smuzhiyun int64_t block_info__cmp(struct perf_hpp_fmt *fmt __maybe_unused,
94*4882a593Smuzhiyun 			struct hist_entry *left, struct hist_entry *right)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	return __block_info__cmp(left, right);
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
init_block_info(struct block_info * bi,struct symbol * sym,struct cyc_hist * ch,int offset,u64 total_cycles)99*4882a593Smuzhiyun static void init_block_info(struct block_info *bi, struct symbol *sym,
100*4882a593Smuzhiyun 			    struct cyc_hist *ch, int offset,
101*4882a593Smuzhiyun 			    u64 total_cycles)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	bi->sym = sym;
104*4882a593Smuzhiyun 	bi->start = ch->start;
105*4882a593Smuzhiyun 	bi->end = offset;
106*4882a593Smuzhiyun 	bi->cycles = ch->cycles;
107*4882a593Smuzhiyun 	bi->cycles_aggr = ch->cycles_aggr;
108*4882a593Smuzhiyun 	bi->num = ch->num;
109*4882a593Smuzhiyun 	bi->num_aggr = ch->num_aggr;
110*4882a593Smuzhiyun 	bi->total_cycles = total_cycles;
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	memcpy(bi->cycles_spark, ch->cycles_spark,
113*4882a593Smuzhiyun 	       NUM_SPARKS * sizeof(u64));
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
block_info__process_sym(struct hist_entry * he,struct block_hist * bh,u64 * block_cycles_aggr,u64 total_cycles)116*4882a593Smuzhiyun int block_info__process_sym(struct hist_entry *he, struct block_hist *bh,
117*4882a593Smuzhiyun 			    u64 *block_cycles_aggr, u64 total_cycles)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	struct annotation *notes;
120*4882a593Smuzhiyun 	struct cyc_hist *ch;
121*4882a593Smuzhiyun 	static struct addr_location al;
122*4882a593Smuzhiyun 	u64 cycles = 0;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	if (!he->ms.map || !he->ms.sym)
125*4882a593Smuzhiyun 		return 0;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	memset(&al, 0, sizeof(al));
128*4882a593Smuzhiyun 	al.map = he->ms.map;
129*4882a593Smuzhiyun 	al.sym = he->ms.sym;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	notes = symbol__annotation(he->ms.sym);
132*4882a593Smuzhiyun 	if (!notes || !notes->src || !notes->src->cycles_hist)
133*4882a593Smuzhiyun 		return 0;
134*4882a593Smuzhiyun 	ch = notes->src->cycles_hist;
135*4882a593Smuzhiyun 	for (unsigned int i = 0; i < symbol__size(he->ms.sym); i++) {
136*4882a593Smuzhiyun 		if (ch[i].num_aggr) {
137*4882a593Smuzhiyun 			struct block_info *bi;
138*4882a593Smuzhiyun 			struct hist_entry *he_block;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 			bi = block_info__new();
141*4882a593Smuzhiyun 			if (!bi)
142*4882a593Smuzhiyun 				return -1;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 			init_block_info(bi, he->ms.sym, &ch[i], i,
145*4882a593Smuzhiyun 					total_cycles);
146*4882a593Smuzhiyun 			cycles += bi->cycles_aggr / bi->num_aggr;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 			he_block = hists__add_entry_block(&bh->block_hists,
149*4882a593Smuzhiyun 							  &al, bi);
150*4882a593Smuzhiyun 			if (!he_block) {
151*4882a593Smuzhiyun 				block_info__put(bi);
152*4882a593Smuzhiyun 				return -1;
153*4882a593Smuzhiyun 			}
154*4882a593Smuzhiyun 		}
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (block_cycles_aggr)
158*4882a593Smuzhiyun 		*block_cycles_aggr += cycles;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	return 0;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
block_column_header(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hists * hists __maybe_unused,int line __maybe_unused,int * span __maybe_unused)163*4882a593Smuzhiyun static int block_column_header(struct perf_hpp_fmt *fmt,
164*4882a593Smuzhiyun 			       struct perf_hpp *hpp,
165*4882a593Smuzhiyun 			       struct hists *hists __maybe_unused,
166*4882a593Smuzhiyun 			       int line __maybe_unused,
167*4882a593Smuzhiyun 			       int *span __maybe_unused)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width,
172*4882a593Smuzhiyun 			 block_fmt->header);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
block_column_width(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp __maybe_unused,struct hists * hists __maybe_unused)175*4882a593Smuzhiyun static int block_column_width(struct perf_hpp_fmt *fmt,
176*4882a593Smuzhiyun 			      struct perf_hpp *hpp __maybe_unused,
177*4882a593Smuzhiyun 			      struct hists *hists __maybe_unused)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	return block_fmt->width;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
color_pct(struct perf_hpp * hpp,int width,double pct)184*4882a593Smuzhiyun static int color_pct(struct perf_hpp *hpp, int width, double pct)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun #ifdef HAVE_SLANG_SUPPORT
187*4882a593Smuzhiyun 	if (use_browser) {
188*4882a593Smuzhiyun 		return __hpp__slsmg_color_printf(hpp, "%*.2f%%",
189*4882a593Smuzhiyun 						 width - 1, pct);
190*4882a593Smuzhiyun 	}
191*4882a593Smuzhiyun #endif
192*4882a593Smuzhiyun 	return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, pct);
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
block_total_cycles_pct_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)195*4882a593Smuzhiyun static int block_total_cycles_pct_entry(struct perf_hpp_fmt *fmt,
196*4882a593Smuzhiyun 					struct perf_hpp *hpp,
197*4882a593Smuzhiyun 					struct hist_entry *he)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
200*4882a593Smuzhiyun 	struct block_info *bi = he->block_info;
201*4882a593Smuzhiyun 	double ratio = 0.0;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (block_fmt->total_cycles)
204*4882a593Smuzhiyun 		ratio = (double)bi->cycles_aggr / (double)block_fmt->total_cycles;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	return color_pct(hpp, block_fmt->width, 100.0 * ratio);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun 
block_total_cycles_pct_sort(struct perf_hpp_fmt * fmt,struct hist_entry * left,struct hist_entry * right)209*4882a593Smuzhiyun static int64_t block_total_cycles_pct_sort(struct perf_hpp_fmt *fmt,
210*4882a593Smuzhiyun 					   struct hist_entry *left,
211*4882a593Smuzhiyun 					   struct hist_entry *right)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
214*4882a593Smuzhiyun 	struct block_info *bi_l = left->block_info;
215*4882a593Smuzhiyun 	struct block_info *bi_r = right->block_info;
216*4882a593Smuzhiyun 	double l, r;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	if (block_fmt->total_cycles) {
219*4882a593Smuzhiyun 		l = ((double)bi_l->cycles_aggr /
220*4882a593Smuzhiyun 			(double)block_fmt->total_cycles) * 100000.0;
221*4882a593Smuzhiyun 		r = ((double)bi_r->cycles_aggr /
222*4882a593Smuzhiyun 			(double)block_fmt->total_cycles) * 100000.0;
223*4882a593Smuzhiyun 		return (int64_t)l - (int64_t)r;
224*4882a593Smuzhiyun 	}
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	return 0;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
cycles_string(u64 cycles,char * buf,int size)229*4882a593Smuzhiyun static void cycles_string(u64 cycles, char *buf, int size)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	if (cycles >= 1000000)
232*4882a593Smuzhiyun 		scnprintf(buf, size, "%.1fM", (double)cycles / 1000000.0);
233*4882a593Smuzhiyun 	else if (cycles >= 1000)
234*4882a593Smuzhiyun 		scnprintf(buf, size, "%.1fK", (double)cycles / 1000.0);
235*4882a593Smuzhiyun 	else
236*4882a593Smuzhiyun 		scnprintf(buf, size, "%1d", cycles);
237*4882a593Smuzhiyun }
238*4882a593Smuzhiyun 
block_cycles_lbr_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)239*4882a593Smuzhiyun static int block_cycles_lbr_entry(struct perf_hpp_fmt *fmt,
240*4882a593Smuzhiyun 				  struct perf_hpp *hpp, struct hist_entry *he)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
243*4882a593Smuzhiyun 	struct block_info *bi = he->block_info;
244*4882a593Smuzhiyun 	char cycles_buf[16];
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	cycles_string(bi->cycles_aggr, cycles_buf, sizeof(cycles_buf));
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width,
249*4882a593Smuzhiyun 			 cycles_buf);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
block_cycles_pct_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)252*4882a593Smuzhiyun static int block_cycles_pct_entry(struct perf_hpp_fmt *fmt,
253*4882a593Smuzhiyun 				  struct perf_hpp *hpp, struct hist_entry *he)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
256*4882a593Smuzhiyun 	struct block_info *bi = he->block_info;
257*4882a593Smuzhiyun 	double ratio = 0.0;
258*4882a593Smuzhiyun 	u64 avg;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	if (block_fmt->block_cycles && bi->num_aggr) {
261*4882a593Smuzhiyun 		avg = bi->cycles_aggr / bi->num_aggr;
262*4882a593Smuzhiyun 		ratio = (double)avg / (double)block_fmt->block_cycles;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	return color_pct(hpp, block_fmt->width, 100.0 * ratio);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
block_avg_cycles_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)268*4882a593Smuzhiyun static int block_avg_cycles_entry(struct perf_hpp_fmt *fmt,
269*4882a593Smuzhiyun 				  struct perf_hpp *hpp,
270*4882a593Smuzhiyun 				  struct hist_entry *he)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
273*4882a593Smuzhiyun 	struct block_info *bi = he->block_info;
274*4882a593Smuzhiyun 	char cycles_buf[16];
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	cycles_string(bi->cycles_aggr / bi->num_aggr, cycles_buf,
277*4882a593Smuzhiyun 		      sizeof(cycles_buf));
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width,
280*4882a593Smuzhiyun 			 cycles_buf);
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
block_range_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)283*4882a593Smuzhiyun static int block_range_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
284*4882a593Smuzhiyun 			     struct hist_entry *he)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
287*4882a593Smuzhiyun 	struct block_info *bi = he->block_info;
288*4882a593Smuzhiyun 	char buf[128];
289*4882a593Smuzhiyun 	char *start_line, *end_line;
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	symbol_conf.disable_add2line_warn = true;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	start_line = map__srcline(he->ms.map, bi->sym->start + bi->start,
294*4882a593Smuzhiyun 				  he->ms.sym);
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	end_line = map__srcline(he->ms.map, bi->sym->start + bi->end,
297*4882a593Smuzhiyun 				he->ms.sym);
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	if ((strncmp(start_line, SRCLINE_UNKNOWN, strlen(SRCLINE_UNKNOWN)) != 0) &&
300*4882a593Smuzhiyun 	    (strncmp(end_line, SRCLINE_UNKNOWN, strlen(SRCLINE_UNKNOWN)) != 0)) {
301*4882a593Smuzhiyun 		scnprintf(buf, sizeof(buf), "[%s -> %s]",
302*4882a593Smuzhiyun 			  start_line, end_line);
303*4882a593Smuzhiyun 	} else {
304*4882a593Smuzhiyun 		scnprintf(buf, sizeof(buf), "[%7lx -> %7lx]",
305*4882a593Smuzhiyun 			  bi->start, bi->end);
306*4882a593Smuzhiyun 	}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	free_srcline(start_line);
309*4882a593Smuzhiyun 	free_srcline(end_line);
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width, buf);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
block_dso_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)314*4882a593Smuzhiyun static int block_dso_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
315*4882a593Smuzhiyun 			   struct hist_entry *he)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun 	struct block_fmt *block_fmt = container_of(fmt, struct block_fmt, fmt);
318*4882a593Smuzhiyun 	struct map *map = he->ms.map;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	if (map && map->dso) {
321*4882a593Smuzhiyun 		return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width,
322*4882a593Smuzhiyun 				 map->dso->short_name);
323*4882a593Smuzhiyun 	}
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	return scnprintf(hpp->buf, hpp->size, "%*s", block_fmt->width,
326*4882a593Smuzhiyun 			 "[unknown]");
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
init_block_header(struct block_fmt * block_fmt)329*4882a593Smuzhiyun static void init_block_header(struct block_fmt *block_fmt)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	struct perf_hpp_fmt *fmt = &block_fmt->fmt;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	BUG_ON(block_fmt->idx >= PERF_HPP_REPORT__BLOCK_MAX_INDEX);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	block_fmt->header = block_columns[block_fmt->idx].name;
336*4882a593Smuzhiyun 	block_fmt->width = block_columns[block_fmt->idx].width;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	fmt->header = block_column_header;
339*4882a593Smuzhiyun 	fmt->width = block_column_width;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun 
hpp_register(struct block_fmt * block_fmt,int idx,struct perf_hpp_list * hpp_list)342*4882a593Smuzhiyun static void hpp_register(struct block_fmt *block_fmt, int idx,
343*4882a593Smuzhiyun 			 struct perf_hpp_list *hpp_list)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun 	struct perf_hpp_fmt *fmt = &block_fmt->fmt;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	block_fmt->idx = idx;
348*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fmt->list);
349*4882a593Smuzhiyun 	INIT_LIST_HEAD(&fmt->sort_list);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	switch (idx) {
352*4882a593Smuzhiyun 	case PERF_HPP_REPORT__BLOCK_TOTAL_CYCLES_PCT:
353*4882a593Smuzhiyun 		fmt->color = block_total_cycles_pct_entry;
354*4882a593Smuzhiyun 		fmt->cmp = block_info__cmp;
355*4882a593Smuzhiyun 		fmt->sort = block_total_cycles_pct_sort;
356*4882a593Smuzhiyun 		break;
357*4882a593Smuzhiyun 	case PERF_HPP_REPORT__BLOCK_LBR_CYCLES:
358*4882a593Smuzhiyun 		fmt->entry = block_cycles_lbr_entry;
359*4882a593Smuzhiyun 		break;
360*4882a593Smuzhiyun 	case PERF_HPP_REPORT__BLOCK_CYCLES_PCT:
361*4882a593Smuzhiyun 		fmt->color = block_cycles_pct_entry;
362*4882a593Smuzhiyun 		break;
363*4882a593Smuzhiyun 	case PERF_HPP_REPORT__BLOCK_AVG_CYCLES:
364*4882a593Smuzhiyun 		fmt->entry = block_avg_cycles_entry;
365*4882a593Smuzhiyun 		break;
366*4882a593Smuzhiyun 	case PERF_HPP_REPORT__BLOCK_RANGE:
367*4882a593Smuzhiyun 		fmt->entry = block_range_entry;
368*4882a593Smuzhiyun 		break;
369*4882a593Smuzhiyun 	case PERF_HPP_REPORT__BLOCK_DSO:
370*4882a593Smuzhiyun 		fmt->entry = block_dso_entry;
371*4882a593Smuzhiyun 		break;
372*4882a593Smuzhiyun 	default:
373*4882a593Smuzhiyun 		return;
374*4882a593Smuzhiyun 	}
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	init_block_header(block_fmt);
377*4882a593Smuzhiyun 	perf_hpp_list__column_register(hpp_list, fmt);
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
register_block_columns(struct perf_hpp_list * hpp_list,struct block_fmt * block_fmts,int * block_hpps,int nr_hpps)380*4882a593Smuzhiyun static void register_block_columns(struct perf_hpp_list *hpp_list,
381*4882a593Smuzhiyun 				   struct block_fmt *block_fmts,
382*4882a593Smuzhiyun 				   int *block_hpps, int nr_hpps)
383*4882a593Smuzhiyun {
384*4882a593Smuzhiyun 	for (int i = 0; i < nr_hpps; i++)
385*4882a593Smuzhiyun 		hpp_register(&block_fmts[i], block_hpps[i], hpp_list);
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
init_block_hist(struct block_hist * bh,struct block_fmt * block_fmts,int * block_hpps,int nr_hpps)388*4882a593Smuzhiyun static void init_block_hist(struct block_hist *bh, struct block_fmt *block_fmts,
389*4882a593Smuzhiyun 			    int *block_hpps, int nr_hpps)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun 	__hists__init(&bh->block_hists, &bh->block_list);
392*4882a593Smuzhiyun 	perf_hpp_list__init(&bh->block_list);
393*4882a593Smuzhiyun 	bh->block_list.nr_header_lines = 1;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	register_block_columns(&bh->block_list, block_fmts,
396*4882a593Smuzhiyun 			       block_hpps, nr_hpps);
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun 	/* Sort by the first fmt */
399*4882a593Smuzhiyun 	perf_hpp_list__register_sort_field(&bh->block_list, &block_fmts[0].fmt);
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun 
process_block_report(struct hists * hists,struct block_report * block_report,u64 total_cycles,int * block_hpps,int nr_hpps)402*4882a593Smuzhiyun static int process_block_report(struct hists *hists,
403*4882a593Smuzhiyun 				struct block_report *block_report,
404*4882a593Smuzhiyun 				u64 total_cycles, int *block_hpps,
405*4882a593Smuzhiyun 				int nr_hpps)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun 	struct rb_node *next = rb_first_cached(&hists->entries);
408*4882a593Smuzhiyun 	struct block_hist *bh = &block_report->hist;
409*4882a593Smuzhiyun 	struct hist_entry *he;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	if (nr_hpps > PERF_HPP_REPORT__BLOCK_MAX_INDEX)
412*4882a593Smuzhiyun 		return -1;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	block_report->nr_fmts = nr_hpps;
415*4882a593Smuzhiyun 	init_block_hist(bh, block_report->fmts, block_hpps, nr_hpps);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	while (next) {
418*4882a593Smuzhiyun 		he = rb_entry(next, struct hist_entry, rb_node);
419*4882a593Smuzhiyun 		block_info__process_sym(he, bh, &block_report->cycles,
420*4882a593Smuzhiyun 					total_cycles);
421*4882a593Smuzhiyun 		next = rb_next(&he->rb_node);
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	for (int i = 0; i < nr_hpps; i++) {
425*4882a593Smuzhiyun 		block_report->fmts[i].total_cycles = total_cycles;
426*4882a593Smuzhiyun 		block_report->fmts[i].block_cycles = block_report->cycles;
427*4882a593Smuzhiyun 	}
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	hists__output_resort(&bh->block_hists, NULL);
430*4882a593Smuzhiyun 	return 0;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
block_info__create_report(struct evlist * evlist,u64 total_cycles,int * block_hpps,int nr_hpps,int * nr_reps)433*4882a593Smuzhiyun struct block_report *block_info__create_report(struct evlist *evlist,
434*4882a593Smuzhiyun 					       u64 total_cycles,
435*4882a593Smuzhiyun 					       int *block_hpps, int nr_hpps,
436*4882a593Smuzhiyun 					       int *nr_reps)
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun 	struct block_report *block_reports;
439*4882a593Smuzhiyun 	int nr_hists = evlist->core.nr_entries, i = 0;
440*4882a593Smuzhiyun 	struct evsel *pos;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	block_reports = calloc(nr_hists, sizeof(struct block_report));
443*4882a593Smuzhiyun 	if (!block_reports)
444*4882a593Smuzhiyun 		return NULL;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	evlist__for_each_entry(evlist, pos) {
447*4882a593Smuzhiyun 		struct hists *hists = evsel__hists(pos);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun 		process_block_report(hists, &block_reports[i], total_cycles,
450*4882a593Smuzhiyun 				     block_hpps, nr_hpps);
451*4882a593Smuzhiyun 		i++;
452*4882a593Smuzhiyun 	}
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	*nr_reps = nr_hists;
455*4882a593Smuzhiyun 	return block_reports;
456*4882a593Smuzhiyun }
457*4882a593Smuzhiyun 
block_info__free_report(struct block_report * reps,int nr_reps)458*4882a593Smuzhiyun void block_info__free_report(struct block_report *reps, int nr_reps)
459*4882a593Smuzhiyun {
460*4882a593Smuzhiyun 	for (int i = 0; i < nr_reps; i++)
461*4882a593Smuzhiyun 		hists__delete_entries(&reps[i].hist.block_hists);
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	free(reps);
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
report__browse_block_hists(struct block_hist * bh,float min_percent,struct evsel * evsel,struct perf_env * env,struct annotation_options * annotation_opts)466*4882a593Smuzhiyun int report__browse_block_hists(struct block_hist *bh, float min_percent,
467*4882a593Smuzhiyun 			       struct evsel *evsel, struct perf_env *env,
468*4882a593Smuzhiyun 			       struct annotation_options *annotation_opts)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	int ret;
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	switch (use_browser) {
473*4882a593Smuzhiyun 	case 0:
474*4882a593Smuzhiyun 		symbol_conf.report_individual_block = true;
475*4882a593Smuzhiyun 		hists__fprintf(&bh->block_hists, true, 0, 0, min_percent,
476*4882a593Smuzhiyun 			       stdout, true);
477*4882a593Smuzhiyun 		return 0;
478*4882a593Smuzhiyun 	case 1:
479*4882a593Smuzhiyun 		symbol_conf.report_individual_block = true;
480*4882a593Smuzhiyun 		ret = block_hists_tui_browse(bh, evsel, min_percent,
481*4882a593Smuzhiyun 					     env, annotation_opts);
482*4882a593Smuzhiyun 		return ret;
483*4882a593Smuzhiyun 	default:
484*4882a593Smuzhiyun 		return -1;
485*4882a593Smuzhiyun 	}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
block_info__total_cycles_percent(struct hist_entry * he)490*4882a593Smuzhiyun float block_info__total_cycles_percent(struct hist_entry *he)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun 	struct block_info *bi = he->block_info;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	if (bi->total_cycles)
495*4882a593Smuzhiyun 		return bi->cycles * 100.0 / bi->total_cycles;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	return 0.0;
498*4882a593Smuzhiyun }
499