aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/ui/hist.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/ui/hist.c')
-rw-r--r--tools/perf/ui/hist.c138
1 files changed, 100 insertions, 38 deletions
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 78f4c92e9b73..0f403b83e9d1 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -8,16 +8,27 @@
8 8
9/* hist period print (hpp) functions */ 9/* hist period print (hpp) functions */
10 10
11typedef int (*hpp_snprint_fn)(char *buf, size_t size, const char *fmt, ...); 11#define hpp__call_print_fn(hpp, fn, fmt, ...) \
12 12({ \
13static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 13 int __ret = fn(hpp, fmt, ##__VA_ARGS__); \
14 u64 (*get_field)(struct hist_entry *), 14 advance_hpp(hpp, __ret); \
15 const char *fmt, hpp_snprint_fn print_fn, 15 __ret; \
16 bool fmt_percent) 16})
17
18int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
19 hpp_field_fn get_field, hpp_callback_fn callback,
20 const char *fmt, hpp_snprint_fn print_fn, bool fmt_percent)
17{ 21{
18 int ret; 22 int ret = 0;
19 struct hists *hists = he->hists; 23 struct hists *hists = he->hists;
20 struct perf_evsel *evsel = hists_to_evsel(hists); 24 struct perf_evsel *evsel = hists_to_evsel(hists);
25 char *buf = hpp->buf;
26 size_t size = hpp->size;
27
28 if (callback) {
29 ret = callback(hpp, true);
30 advance_hpp(hpp, ret);
31 }
21 32
22 if (fmt_percent) { 33 if (fmt_percent) {
23 double percent = 0.0; 34 double percent = 0.0;
@@ -26,9 +37,9 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
26 percent = 100.0 * get_field(he) / 37 percent = 100.0 * get_field(he) /
27 hists->stats.total_period; 38 hists->stats.total_period;
28 39
29 ret = print_fn(hpp->buf, hpp->size, fmt, percent); 40 ret += hpp__call_print_fn(hpp, print_fn, fmt, percent);
30 } else 41 } else
31 ret = print_fn(hpp->buf, hpp->size, fmt, get_field(he)); 42 ret += hpp__call_print_fn(hpp, print_fn, fmt, get_field(he));
32 43
33 if (perf_evsel__is_group_event(evsel)) { 44 if (perf_evsel__is_group_event(evsel)) {
34 int prev_idx, idx_delta; 45 int prev_idx, idx_delta;
@@ -52,16 +63,22 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
52 * zero-fill group members in the middle which 63 * zero-fill group members in the middle which
53 * have no sample 64 * have no sample
54 */ 65 */
55 ret += print_fn(hpp->buf + ret, hpp->size - ret, 66 if (fmt_percent) {
56 fmt, 0); 67 ret += hpp__call_print_fn(hpp, print_fn,
68 fmt, 0.0);
69 } else {
70 ret += hpp__call_print_fn(hpp, print_fn,
71 fmt, 0ULL);
72 }
57 } 73 }
58 74
59 if (fmt_percent) 75 if (fmt_percent) {
60 ret += print_fn(hpp->buf + ret, hpp->size - ret, 76 ret += hpp__call_print_fn(hpp, print_fn, fmt,
61 fmt, 100.0 * period / total); 77 100.0 * period / total);
62 else 78 } else {
63 ret += print_fn(hpp->buf + ret, hpp->size - ret, 79 ret += hpp__call_print_fn(hpp, print_fn, fmt,
64 fmt, period); 80 period);
81 }
65 82
66 prev_idx = perf_evsel__group_idx(evsel); 83 prev_idx = perf_evsel__group_idx(evsel);
67 } 84 }
@@ -72,41 +89,87 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
72 /* 89 /*
73 * zero-fill group members at last which have no sample 90 * zero-fill group members at last which have no sample
74 */ 91 */
75 ret += print_fn(hpp->buf + ret, hpp->size - ret, 92 if (fmt_percent) {
76 fmt, 0); 93 ret += hpp__call_print_fn(hpp, print_fn,
94 fmt, 0.0);
95 } else {
96 ret += hpp__call_print_fn(hpp, print_fn,
97 fmt, 0ULL);
98 }
77 } 99 }
78 } 100 }
101
102 if (callback) {
103 int __ret = callback(hpp, false);
104
105 advance_hpp(hpp, __ret);
106 ret += __ret;
107 }
108
109 /*
110 * Restore original buf and size as it's where caller expects
111 * the result will be saved.
112 */
113 hpp->buf = buf;
114 hpp->size = size;
115
79 return ret; 116 return ret;
80} 117}
81 118
82#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 119#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
83static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 120static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
84 struct perf_hpp *hpp) \ 121 struct perf_hpp *hpp, \
122 struct perf_evsel *evsel) \
85{ \ 123{ \
86 int len = _min_width; \ 124 int len = _min_width; \
87 \ 125 \
88 if (symbol_conf.event_group) { \ 126 if (symbol_conf.event_group) \
89 struct perf_evsel *evsel = hpp->ptr; \
90 \
91 len = max(len, evsel->nr_members * _unit_width); \ 127 len = max(len, evsel->nr_members * _unit_width); \
92 } \ 128 \
93 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ 129 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \
94} 130}
95 131
96#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 132#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \
97static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 133static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
98 struct perf_hpp *hpp __maybe_unused) \ 134 struct perf_hpp *hpp __maybe_unused, \
135 struct perf_evsel *evsel) \
99{ \ 136{ \
100 int len = _min_width; \ 137 int len = _min_width; \
101 \ 138 \
102 if (symbol_conf.event_group) { \ 139 if (symbol_conf.event_group) \
103 struct perf_evsel *evsel = hpp->ptr; \
104 \
105 len = max(len, evsel->nr_members * _unit_width); \ 140 len = max(len, evsel->nr_members * _unit_width); \
106 } \ 141 \
107 return len; \ 142 return len; \
108} 143}
109 144
145static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
146{
147 va_list args;
148 ssize_t ssize = hpp->size;
149 double percent;
150 int ret;
151
152 va_start(args, fmt);
153 percent = va_arg(args, double);
154 ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent);
155 va_end(args);
156
157 return (ret >= ssize) ? (ssize - 1) : ret;
158}
159
160static int hpp_entry_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
161{
162 va_list args;
163 ssize_t ssize = hpp->size;
164 int ret;
165
166 va_start(args, fmt);
167 ret = vsnprintf(hpp->buf, hpp->size, fmt, args);
168 va_end(args);
169
170 return (ret >= ssize) ? (ssize - 1) : ret;
171}
172
110#define __HPP_COLOR_PERCENT_FN(_type, _field) \ 173#define __HPP_COLOR_PERCENT_FN(_type, _field) \
111static u64 he_get_##_field(struct hist_entry *he) \ 174static u64 he_get_##_field(struct hist_entry *he) \
112{ \ 175{ \
@@ -116,8 +179,8 @@ static u64 he_get_##_field(struct hist_entry *he) \
116static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 179static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \
117 struct perf_hpp *hpp, struct hist_entry *he) \ 180 struct perf_hpp *hpp, struct hist_entry *he) \
118{ \ 181{ \
119 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 182 return __hpp__fmt(hpp, he, he_get_##_field, NULL, " %6.2f%%", \
120 percent_color_snprintf, true); \ 183 hpp_color_scnprintf, true); \
121} 184}
122 185
123#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 186#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
@@ -125,8 +188,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
125 struct perf_hpp *hpp, struct hist_entry *he) \ 188 struct perf_hpp *hpp, struct hist_entry *he) \
126{ \ 189{ \
127 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 190 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \
128 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 191 return __hpp__fmt(hpp, he, he_get_##_field, NULL, fmt, \
129 scnprintf, true); \ 192 hpp_entry_scnprintf, true); \
130} 193}
131 194
132#define __HPP_ENTRY_RAW_FN(_type, _field) \ 195#define __HPP_ENTRY_RAW_FN(_type, _field) \
@@ -139,7 +202,8 @@ static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \
139 struct perf_hpp *hpp, struct hist_entry *he) \ 202 struct perf_hpp *hpp, struct hist_entry *he) \
140{ \ 203{ \
141 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 204 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \
142 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, scnprintf, false); \ 205 return __hpp__fmt(hpp, he, he_get_raw_##_field, NULL, fmt, \
206 hpp_entry_scnprintf, false); \
143} 207}
144 208
145#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ 209#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \
@@ -263,15 +327,13 @@ unsigned int hists__sort_list_width(struct hists *hists)
263 struct perf_hpp_fmt *fmt; 327 struct perf_hpp_fmt *fmt;
264 struct sort_entry *se; 328 struct sort_entry *se;
265 int i = 0, ret = 0; 329 int i = 0, ret = 0;
266 struct perf_hpp dummy_hpp = { 330 struct perf_hpp dummy_hpp;
267 .ptr = hists_to_evsel(hists),
268 };
269 331
270 perf_hpp__for_each_format(fmt) { 332 perf_hpp__for_each_format(fmt) {
271 if (i) 333 if (i)
272 ret += 2; 334 ret += 2;
273 335
274 ret += fmt->width(fmt, &dummy_hpp); 336 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
275 } 337 }
276 338
277 list_for_each_entry(se, &hist_entry__sort_list, list) 339 list_for_each_entry(se, &hist_entry__sort_list, list)