Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / tools / perf / util / stat-display.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <inttypes.h>
4 #include <linux/string.h>
5 #include <linux/time64.h>
6 #include <math.h>
7 #include "color.h"
8 #include "counts.h"
9 #include "evlist.h"
10 #include "evsel.h"
11 #include "stat.h"
12 #include "top.h"
13 #include "thread_map.h"
14 #include "cpumap.h"
15 #include "string2.h"
16 #include <linux/ctype.h>
17 #include "cgroup.h"
18 #include <api/fs/fs.h>
19 #include "util.h"
20 #include "iostat.h"
21 #include "pmu-hybrid.h"
22
23 #define CNTR_NOT_SUPPORTED      "<not supported>"
24 #define CNTR_NOT_COUNTED        "<not counted>"
25
26 static void print_running(struct perf_stat_config *config,
27                           u64 run, u64 ena)
28 {
29         if (config->csv_output) {
30                 fprintf(config->output, "%s%" PRIu64 "%s%.2f",
31                                         config->csv_sep,
32                                         run,
33                                         config->csv_sep,
34                                         ena ? 100.0 * run / ena : 100.0);
35         } else if (run != ena) {
36                 fprintf(config->output, "  (%.2f%%)", 100.0 * run / ena);
37         }
38 }
39
40 static void print_noise_pct(struct perf_stat_config *config,
41                             double total, double avg)
42 {
43         double pct = rel_stddev_stats(total, avg);
44
45         if (config->csv_output)
46                 fprintf(config->output, "%s%.2f%%", config->csv_sep, pct);
47         else if (pct)
48                 fprintf(config->output, "  ( +-%6.2f%% )", pct);
49 }
50
51 static void print_noise(struct perf_stat_config *config,
52                         struct evsel *evsel, double avg)
53 {
54         struct perf_stat_evsel *ps;
55
56         if (config->run_count == 1)
57                 return;
58
59         ps = evsel->stats;
60         print_noise_pct(config, stddev_stats(&ps->res_stats[0]), avg);
61 }
62
63 static void print_cgroup(struct perf_stat_config *config, struct evsel *evsel)
64 {
65         if (nr_cgroups) {
66                 const char *cgrp_name = evsel->cgrp ? evsel->cgrp->name  : "";
67                 fprintf(config->output, "%s%s", config->csv_sep, cgrp_name);
68         }
69 }
70
71
72 static void aggr_printout(struct perf_stat_config *config,
73                           struct evsel *evsel, struct aggr_cpu_id id, int nr)
74 {
75         switch (config->aggr_mode) {
76         case AGGR_CORE:
77                 fprintf(config->output, "S%d-D%d-C%*d%s%*d%s",
78                         id.socket,
79                         id.die,
80                         config->csv_output ? 0 : -8,
81                         id.core,
82                         config->csv_sep,
83                         config->csv_output ? 0 : 4,
84                         nr,
85                         config->csv_sep);
86                 break;
87         case AGGR_DIE:
88                 fprintf(config->output, "S%d-D%*d%s%*d%s",
89                         id.socket,
90                         config->csv_output ? 0 : -8,
91                         id.die,
92                         config->csv_sep,
93                         config->csv_output ? 0 : 4,
94                         nr,
95                         config->csv_sep);
96                 break;
97         case AGGR_SOCKET:
98                 fprintf(config->output, "S%*d%s%*d%s",
99                         config->csv_output ? 0 : -5,
100                         id.socket,
101                         config->csv_sep,
102                         config->csv_output ? 0 : 4,
103                         nr,
104                         config->csv_sep);
105                         break;
106         case AGGR_NODE:
107                 fprintf(config->output, "N%*d%s%*d%s",
108                         config->csv_output ? 0 : -5,
109                         id.node,
110                         config->csv_sep,
111                         config->csv_output ? 0 : 4,
112                         nr,
113                         config->csv_sep);
114                         break;
115         case AGGR_NONE:
116                 if (evsel->percore && !config->percore_show_thread) {
117                         fprintf(config->output, "S%d-D%d-C%*d%s",
118                                 id.socket,
119                                 id.die,
120                                 config->csv_output ? 0 : -3,
121                                 id.core, config->csv_sep);
122                 } else if (id.core > -1) {
123                         fprintf(config->output, "CPU%*d%s",
124                                 config->csv_output ? 0 : -7,
125                                 evsel__cpus(evsel)->map[id.core],
126                                 config->csv_sep);
127                 }
128                 break;
129         case AGGR_THREAD:
130                 fprintf(config->output, "%*s-%*d%s",
131                         config->csv_output ? 0 : 16,
132                         perf_thread_map__comm(evsel->core.threads, id.thread),
133                         config->csv_output ? 0 : -8,
134                         perf_thread_map__pid(evsel->core.threads, id.thread),
135                         config->csv_sep);
136                 break;
137         case AGGR_GLOBAL:
138         case AGGR_UNSET:
139         default:
140                 break;
141         }
142 }
143
144 struct outstate {
145         FILE *fh;
146         bool newline;
147         const char *prefix;
148         int  nfields;
149         int  nr;
150         struct aggr_cpu_id id;
151         struct evsel *evsel;
152 };
153
154 #define METRIC_LEN  35
155
156 static void new_line_std(struct perf_stat_config *config __maybe_unused,
157                          void *ctx)
158 {
159         struct outstate *os = ctx;
160
161         os->newline = true;
162 }
163
164 static void do_new_line_std(struct perf_stat_config *config,
165                             struct outstate *os)
166 {
167         fputc('\n', os->fh);
168         fputs(os->prefix, os->fh);
169         aggr_printout(config, os->evsel, os->id, os->nr);
170         if (config->aggr_mode == AGGR_NONE)
171                 fprintf(os->fh, "        ");
172         fprintf(os->fh, "                                                 ");
173 }
174
175 static void print_metric_std(struct perf_stat_config *config,
176                              void *ctx, const char *color, const char *fmt,
177                              const char *unit, double val)
178 {
179         struct outstate *os = ctx;
180         FILE *out = os->fh;
181         int n;
182         bool newline = os->newline;
183
184         os->newline = false;
185
186         if (unit == NULL || fmt == NULL) {
187                 fprintf(out, "%-*s", METRIC_LEN, "");
188                 return;
189         }
190
191         if (newline)
192                 do_new_line_std(config, os);
193
194         n = fprintf(out, " # ");
195         if (color)
196                 n += color_fprintf(out, color, fmt, val);
197         else
198                 n += fprintf(out, fmt, val);
199         fprintf(out, " %-*s", METRIC_LEN - n - 1, unit);
200 }
201
202 static void new_line_csv(struct perf_stat_config *config, void *ctx)
203 {
204         struct outstate *os = ctx;
205         int i;
206
207         fputc('\n', os->fh);
208         if (os->prefix)
209                 fprintf(os->fh, "%s%s", os->prefix, config->csv_sep);
210         aggr_printout(config, os->evsel, os->id, os->nr);
211         for (i = 0; i < os->nfields; i++)
212                 fputs(config->csv_sep, os->fh);
213 }
214
215 static void print_metric_csv(struct perf_stat_config *config __maybe_unused,
216                              void *ctx,
217                              const char *color __maybe_unused,
218                              const char *fmt, const char *unit, double val)
219 {
220         struct outstate *os = ctx;
221         FILE *out = os->fh;
222         char buf[64], *vals, *ends;
223
224         if (unit == NULL || fmt == NULL) {
225                 fprintf(out, "%s%s", config->csv_sep, config->csv_sep);
226                 return;
227         }
228         snprintf(buf, sizeof(buf), fmt, val);
229         ends = vals = skip_spaces(buf);
230         while (isdigit(*ends) || *ends == '.')
231                 ends++;
232         *ends = 0;
233         fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, skip_spaces(unit));
234 }
235
236 /* Filter out some columns that don't work well in metrics only mode */
237
238 static bool valid_only_metric(const char *unit)
239 {
240         if (!unit)
241                 return false;
242         if (strstr(unit, "/sec") ||
243             strstr(unit, "CPUs utilized"))
244                 return false;
245         return true;
246 }
247
248 static const char *fixunit(char *buf, struct evsel *evsel,
249                            const char *unit)
250 {
251         if (!strncmp(unit, "of all", 6)) {
252                 snprintf(buf, 1024, "%s %s", evsel__name(evsel),
253                          unit);
254                 return buf;
255         }
256         return unit;
257 }
258
259 static void print_metric_only(struct perf_stat_config *config,
260                               void *ctx, const char *color, const char *fmt,
261                               const char *unit, double val)
262 {
263         struct outstate *os = ctx;
264         FILE *out = os->fh;
265         char buf[1024], str[1024];
266         unsigned mlen = config->metric_only_len;
267
268         if (!valid_only_metric(unit))
269                 return;
270         unit = fixunit(buf, os->evsel, unit);
271         if (mlen < strlen(unit))
272                 mlen = strlen(unit) + 1;
273
274         if (color)
275                 mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
276
277         color_snprintf(str, sizeof(str), color ?: "", fmt, val);
278         fprintf(out, "%*s ", mlen, str);
279 }
280
281 static void print_metric_only_csv(struct perf_stat_config *config __maybe_unused,
282                                   void *ctx, const char *color __maybe_unused,
283                                   const char *fmt,
284                                   const char *unit, double val)
285 {
286         struct outstate *os = ctx;
287         FILE *out = os->fh;
288         char buf[64], *vals, *ends;
289         char tbuf[1024];
290
291         if (!valid_only_metric(unit))
292                 return;
293         unit = fixunit(tbuf, os->evsel, unit);
294         snprintf(buf, sizeof buf, fmt, val);
295         ends = vals = skip_spaces(buf);
296         while (isdigit(*ends) || *ends == '.')
297                 ends++;
298         *ends = 0;
299         fprintf(out, "%s%s", vals, config->csv_sep);
300 }
301
302 static void new_line_metric(struct perf_stat_config *config __maybe_unused,
303                             void *ctx __maybe_unused)
304 {
305 }
306
307 static void print_metric_header(struct perf_stat_config *config,
308                                 void *ctx, const char *color __maybe_unused,
309                                 const char *fmt __maybe_unused,
310                                 const char *unit, double val __maybe_unused)
311 {
312         struct outstate *os = ctx;
313         char tbuf[1024];
314
315         /* In case of iostat, print metric header for first root port only */
316         if (config->iostat_run &&
317             os->evsel->priv != os->evsel->evlist->selected->priv)
318                 return;
319
320         if (!valid_only_metric(unit))
321                 return;
322         unit = fixunit(tbuf, os->evsel, unit);
323         if (config->csv_output)
324                 fprintf(os->fh, "%s%s", unit, config->csv_sep);
325         else
326                 fprintf(os->fh, "%*s ", config->metric_only_len, unit);
327 }
328
329 static int first_shadow_cpu(struct perf_stat_config *config,
330                             struct evsel *evsel, struct aggr_cpu_id id)
331 {
332         struct evlist *evlist = evsel->evlist;
333         int i;
334
335         if (config->aggr_mode == AGGR_NONE)
336                 return id.core;
337
338         if (!config->aggr_get_id)
339                 return 0;
340
341         for (i = 0; i < evsel__nr_cpus(evsel); i++) {
342                 int cpu2 = evsel__cpus(evsel)->map[i];
343
344                 if (cpu_map__compare_aggr_cpu_id(
345                                         config->aggr_get_id(config, evlist->core.cpus, cpu2),
346                                         id)) {
347                         return cpu2;
348                 }
349         }
350         return 0;
351 }
352
353 static void abs_printout(struct perf_stat_config *config,
354                          struct aggr_cpu_id id, int nr, struct evsel *evsel, double avg)
355 {
356         FILE *output = config->output;
357         double sc =  evsel->scale;
358         const char *fmt;
359
360         if (config->csv_output) {
361                 fmt = floor(sc) != sc ?  "%.2f%s" : "%.0f%s";
362         } else {
363                 if (config->big_num)
364                         fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
365                 else
366                         fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
367         }
368
369         aggr_printout(config, evsel, id, nr);
370
371         fprintf(output, fmt, avg, config->csv_sep);
372
373         if (evsel->unit)
374                 fprintf(output, "%-*s%s",
375                         config->csv_output ? 0 : config->unit_width,
376                         evsel->unit, config->csv_sep);
377
378         fprintf(output, "%-*s", config->csv_output ? 0 : 25, evsel__name(evsel));
379
380         print_cgroup(config, evsel);
381 }
382
383 static bool is_mixed_hw_group(struct evsel *counter)
384 {
385         struct evlist *evlist = counter->evlist;
386         u32 pmu_type = counter->core.attr.type;
387         struct evsel *pos;
388
389         if (counter->core.nr_members < 2)
390                 return false;
391
392         evlist__for_each_entry(evlist, pos) {
393                 /* software events can be part of any hardware group */
394                 if (pos->core.attr.type == PERF_TYPE_SOFTWARE)
395                         continue;
396                 if (pmu_type == PERF_TYPE_SOFTWARE) {
397                         pmu_type = pos->core.attr.type;
398                         continue;
399                 }
400                 if (pmu_type != pos->core.attr.type)
401                         return true;
402         }
403
404         return false;
405 }
406
407 static void printout(struct perf_stat_config *config, struct aggr_cpu_id id, int nr,
408                      struct evsel *counter, double uval,
409                      char *prefix, u64 run, u64 ena, double noise,
410                      struct runtime_stat *st)
411 {
412         struct perf_stat_output_ctx out;
413         struct outstate os = {
414                 .fh = config->output,
415                 .prefix = prefix ? prefix : "",
416                 .id = id,
417                 .nr = nr,
418                 .evsel = counter,
419         };
420         print_metric_t pm = print_metric_std;
421         new_line_t nl;
422
423         if (config->metric_only) {
424                 nl = new_line_metric;
425                 if (config->csv_output)
426                         pm = print_metric_only_csv;
427                 else
428                         pm = print_metric_only;
429         } else
430                 nl = new_line_std;
431
432         if (config->csv_output && !config->metric_only) {
433                 static int aggr_fields[] = {
434                         [AGGR_GLOBAL] = 0,
435                         [AGGR_THREAD] = 1,
436                         [AGGR_NONE] = 1,
437                         [AGGR_SOCKET] = 2,
438                         [AGGR_DIE] = 2,
439                         [AGGR_CORE] = 2,
440                 };
441
442                 pm = print_metric_csv;
443                 nl = new_line_csv;
444                 os.nfields = 3;
445                 os.nfields += aggr_fields[config->aggr_mode];
446                 if (counter->cgrp)
447                         os.nfields++;
448         }
449
450         if (!config->no_csv_summary && config->csv_output &&
451             config->summary && !config->interval) {
452                 fprintf(config->output, "%16s%s", "summary", config->csv_sep);
453         }
454
455         if (run == 0 || ena == 0 || counter->counts->scaled == -1) {
456                 if (config->metric_only) {
457                         pm(config, &os, NULL, "", "", 0);
458                         return;
459                 }
460                 aggr_printout(config, counter, id, nr);
461
462                 fprintf(config->output, "%*s%s",
463                         config->csv_output ? 0 : 18,
464                         counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
465                         config->csv_sep);
466
467                 if (counter->supported) {
468                         config->print_free_counters_hint = 1;
469                         if (is_mixed_hw_group(counter))
470                                 config->print_mixed_hw_group_error = 1;
471                 }
472
473                 fprintf(config->output, "%-*s%s",
474                         config->csv_output ? 0 : config->unit_width,
475                         counter->unit, config->csv_sep);
476
477                 fprintf(config->output, "%*s",
478                         config->csv_output ? 0 : -25, evsel__name(counter));
479
480                 print_cgroup(config, counter);
481
482                 if (!config->csv_output)
483                         pm(config, &os, NULL, NULL, "", 0);
484                 print_noise(config, counter, noise);
485                 print_running(config, run, ena);
486                 if (config->csv_output)
487                         pm(config, &os, NULL, NULL, "", 0);
488                 return;
489         }
490
491         if (!config->metric_only)
492                 abs_printout(config, id, nr, counter, uval);
493
494         out.print_metric = pm;
495         out.new_line = nl;
496         out.ctx = &os;
497         out.force_header = false;
498
499         if (config->csv_output && !config->metric_only) {
500                 print_noise(config, counter, noise);
501                 print_running(config, run, ena);
502         }
503
504         perf_stat__print_shadow_stats(config, counter, uval,
505                                 first_shadow_cpu(config, counter, id),
506                                 &out, &config->metric_events, st);
507         if (!config->csv_output && !config->metric_only) {
508                 print_noise(config, counter, noise);
509                 print_running(config, run, ena);
510         }
511 }
512
513 static void aggr_update_shadow(struct perf_stat_config *config,
514                                struct evlist *evlist)
515 {
516         int cpu, s;
517         struct aggr_cpu_id s2, id;
518         u64 val;
519         struct evsel *counter;
520
521         for (s = 0; s < config->aggr_map->nr; s++) {
522                 id = config->aggr_map->map[s];
523                 evlist__for_each_entry(evlist, counter) {
524                         val = 0;
525                         for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
526                                 s2 = config->aggr_get_id(config, evlist->core.cpus, cpu);
527                                 if (!cpu_map__compare_aggr_cpu_id(s2, id))
528                                         continue;
529                                 val += perf_counts(counter->counts, cpu, 0)->val;
530                         }
531                         perf_stat__update_shadow_stats(counter, val,
532                                         first_shadow_cpu(config, counter, id),
533                                         &rt_stat);
534                 }
535         }
536 }
537
538 static void uniquify_event_name(struct evsel *counter)
539 {
540         char *new_name;
541         char *config;
542         int ret = 0;
543
544         if (counter->uniquified_name || counter->use_config_name ||
545             !counter->pmu_name || !strncmp(counter->name, counter->pmu_name,
546                                            strlen(counter->pmu_name)))
547                 return;
548
549         config = strchr(counter->name, '/');
550         if (config) {
551                 if (asprintf(&new_name,
552                              "%s%s", counter->pmu_name, config) > 0) {
553                         free(counter->name);
554                         counter->name = new_name;
555                 }
556         } else {
557                 if (perf_pmu__has_hybrid()) {
558                         ret = asprintf(&new_name, "%s/%s/",
559                                        counter->pmu_name, counter->name);
560                 } else {
561                         ret = asprintf(&new_name, "%s [%s]",
562                                        counter->name, counter->pmu_name);
563                 }
564
565                 if (ret) {
566                         free(counter->name);
567                         counter->name = new_name;
568                 }
569         }
570
571         counter->uniquified_name = true;
572 }
573
574 static void collect_all_aliases(struct perf_stat_config *config, struct evsel *counter,
575                             void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
576                                        bool first),
577                             void *data)
578 {
579         struct evlist *evlist = counter->evlist;
580         struct evsel *alias;
581
582         alias = list_prepare_entry(counter, &(evlist->core.entries), core.node);
583         list_for_each_entry_continue (alias, &evlist->core.entries, core.node) {
584                 if (strcmp(evsel__name(alias), evsel__name(counter)) ||
585                     alias->scale != counter->scale ||
586                     alias->cgrp != counter->cgrp ||
587                     strcmp(alias->unit, counter->unit) ||
588                     evsel__is_clock(alias) != evsel__is_clock(counter) ||
589                     !strcmp(alias->pmu_name, counter->pmu_name))
590                         break;
591                 alias->merged_stat = true;
592                 cb(config, alias, data, false);
593         }
594 }
595
596 static bool collect_data(struct perf_stat_config *config, struct evsel *counter,
597                             void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
598                                        bool first),
599                             void *data)
600 {
601         if (counter->merged_stat)
602                 return false;
603         cb(config, counter, data, true);
604         if (config->no_merge)
605                 uniquify_event_name(counter);
606         else if (counter->auto_merge_stats)
607                 collect_all_aliases(config, counter, cb, data);
608         return true;
609 }
610
611 struct aggr_data {
612         u64 ena, run, val;
613         struct aggr_cpu_id id;
614         int nr;
615         int cpu;
616 };
617
618 static void aggr_cb(struct perf_stat_config *config,
619                     struct evsel *counter, void *data, bool first)
620 {
621         struct aggr_data *ad = data;
622         int cpu;
623         struct aggr_cpu_id s2;
624
625         for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
626                 struct perf_counts_values *counts;
627
628                 s2 = config->aggr_get_id(config, evsel__cpus(counter), cpu);
629                 if (!cpu_map__compare_aggr_cpu_id(s2, ad->id))
630                         continue;
631                 if (first)
632                         ad->nr++;
633                 counts = perf_counts(counter->counts, cpu, 0);
634                 /*
635                  * When any result is bad, make them all to give
636                  * consistent output in interval mode.
637                  */
638                 if (counts->ena == 0 || counts->run == 0 ||
639                     counter->counts->scaled == -1) {
640                         ad->ena = 0;
641                         ad->run = 0;
642                         break;
643                 }
644                 ad->val += counts->val;
645                 ad->ena += counts->ena;
646                 ad->run += counts->run;
647         }
648 }
649
650 static void print_counter_aggrdata(struct perf_stat_config *config,
651                                    struct evsel *counter, int s,
652                                    char *prefix, bool metric_only,
653                                    bool *first, int cpu)
654 {
655         struct aggr_data ad;
656         FILE *output = config->output;
657         u64 ena, run, val;
658         int nr;
659         struct aggr_cpu_id id;
660         double uval;
661
662         ad.id = id = config->aggr_map->map[s];
663         ad.val = ad.ena = ad.run = 0;
664         ad.nr = 0;
665         if (!collect_data(config, counter, aggr_cb, &ad))
666                 return;
667
668         if (perf_pmu__has_hybrid() && ad.ena == 0)
669                 return;
670
671         nr = ad.nr;
672         ena = ad.ena;
673         run = ad.run;
674         val = ad.val;
675         if (*first && metric_only) {
676                 *first = false;
677                 aggr_printout(config, counter, id, nr);
678         }
679         if (prefix && !metric_only)
680                 fprintf(output, "%s", prefix);
681
682         uval = val * counter->scale;
683         if (cpu != -1) {
684                 id = cpu_map__empty_aggr_cpu_id();
685                 id.core = cpu;
686         }
687         printout(config, id, nr, counter, uval,
688                  prefix, run, ena, 1.0, &rt_stat);
689         if (!metric_only)
690                 fputc('\n', output);
691 }
692
693 static void print_aggr(struct perf_stat_config *config,
694                        struct evlist *evlist,
695                        char *prefix)
696 {
697         bool metric_only = config->metric_only;
698         FILE *output = config->output;
699         struct evsel *counter;
700         int s;
701         bool first;
702
703         if (!config->aggr_map || !config->aggr_get_id)
704                 return;
705
706         aggr_update_shadow(config, evlist);
707
708         /*
709          * With metric_only everything is on a single line.
710          * Without each counter has its own line.
711          */
712         for (s = 0; s < config->aggr_map->nr; s++) {
713                 if (prefix && metric_only)
714                         fprintf(output, "%s", prefix);
715
716                 first = true;
717                 evlist__for_each_entry(evlist, counter) {
718                         print_counter_aggrdata(config, counter, s,
719                                                prefix, metric_only,
720                                                &first, -1);
721                 }
722                 if (metric_only)
723                         fputc('\n', output);
724         }
725 }
726
727 static int cmp_val(const void *a, const void *b)
728 {
729         return ((struct perf_aggr_thread_value *)b)->val -
730                 ((struct perf_aggr_thread_value *)a)->val;
731 }
732
733 static struct perf_aggr_thread_value *sort_aggr_thread(
734                                         struct evsel *counter,
735                                         int nthreads, int ncpus,
736                                         int *ret,
737                                         struct target *_target)
738 {
739         int cpu, thread, i = 0;
740         double uval;
741         struct perf_aggr_thread_value *buf;
742
743         buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
744         if (!buf)
745                 return NULL;
746
747         for (thread = 0; thread < nthreads; thread++) {
748                 u64 ena = 0, run = 0, val = 0;
749
750                 for (cpu = 0; cpu < ncpus; cpu++) {
751                         val += perf_counts(counter->counts, cpu, thread)->val;
752                         ena += perf_counts(counter->counts, cpu, thread)->ena;
753                         run += perf_counts(counter->counts, cpu, thread)->run;
754                 }
755
756                 uval = val * counter->scale;
757
758                 /*
759                  * Skip value 0 when enabling --per-thread globally,
760                  * otherwise too many 0 output.
761                  */
762                 if (uval == 0.0 && target__has_per_thread(_target))
763                         continue;
764
765                 buf[i].counter = counter;
766                 buf[i].id = cpu_map__empty_aggr_cpu_id();
767                 buf[i].id.thread = thread;
768                 buf[i].uval = uval;
769                 buf[i].val = val;
770                 buf[i].run = run;
771                 buf[i].ena = ena;
772                 i++;
773         }
774
775         qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
776
777         if (ret)
778                 *ret = i;
779
780         return buf;
781 }
782
783 static void print_aggr_thread(struct perf_stat_config *config,
784                               struct target *_target,
785                               struct evsel *counter, char *prefix)
786 {
787         FILE *output = config->output;
788         int nthreads = perf_thread_map__nr(counter->core.threads);
789         int ncpus = perf_cpu_map__nr(counter->core.cpus);
790         int thread, sorted_threads;
791         struct aggr_cpu_id id;
792         struct perf_aggr_thread_value *buf;
793
794         buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
795         if (!buf) {
796                 perror("cannot sort aggr thread");
797                 return;
798         }
799
800         for (thread = 0; thread < sorted_threads; thread++) {
801                 if (prefix)
802                         fprintf(output, "%s", prefix);
803
804                 id = buf[thread].id;
805                 if (config->stats)
806                         printout(config, id, 0, buf[thread].counter, buf[thread].uval,
807                                  prefix, buf[thread].run, buf[thread].ena, 1.0,
808                                  &config->stats[id.thread]);
809                 else
810                         printout(config, id, 0, buf[thread].counter, buf[thread].uval,
811                                  prefix, buf[thread].run, buf[thread].ena, 1.0,
812                                  &rt_stat);
813                 fputc('\n', output);
814         }
815
816         free(buf);
817 }
818
819 struct caggr_data {
820         double avg, avg_enabled, avg_running;
821 };
822
823 static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
824                             struct evsel *counter, void *data,
825                             bool first __maybe_unused)
826 {
827         struct caggr_data *cd = data;
828         struct perf_stat_evsel *ps = counter->stats;
829
830         cd->avg += avg_stats(&ps->res_stats[0]);
831         cd->avg_enabled += avg_stats(&ps->res_stats[1]);
832         cd->avg_running += avg_stats(&ps->res_stats[2]);
833 }
834
835 /*
836  * Print out the results of a single counter:
837  * aggregated counts in system-wide mode
838  */
839 static void print_counter_aggr(struct perf_stat_config *config,
840                                struct evsel *counter, char *prefix)
841 {
842         bool metric_only = config->metric_only;
843         FILE *output = config->output;
844         double uval;
845         struct caggr_data cd = { .avg = 0.0 };
846
847         if (!collect_data(config, counter, counter_aggr_cb, &cd))
848                 return;
849
850         if (prefix && !metric_only)
851                 fprintf(output, "%s", prefix);
852
853         uval = cd.avg * counter->scale;
854         printout(config, cpu_map__empty_aggr_cpu_id(), 0, counter, uval, prefix, cd.avg_running,
855                  cd.avg_enabled, cd.avg, &rt_stat);
856         if (!metric_only)
857                 fprintf(output, "\n");
858 }
859
860 static void counter_cb(struct perf_stat_config *config __maybe_unused,
861                        struct evsel *counter, void *data,
862                        bool first __maybe_unused)
863 {
864         struct aggr_data *ad = data;
865
866         ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
867         ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
868         ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
869 }
870
871 /*
872  * Print out the results of a single counter:
873  * does not use aggregated count in system-wide
874  */
875 static void print_counter(struct perf_stat_config *config,
876                           struct evsel *counter, char *prefix)
877 {
878         FILE *output = config->output;
879         u64 ena, run, val;
880         double uval;
881         int cpu;
882         struct aggr_cpu_id id;
883
884         for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
885                 struct aggr_data ad = { .cpu = cpu };
886
887                 if (!collect_data(config, counter, counter_cb, &ad))
888                         return;
889                 val = ad.val;
890                 ena = ad.ena;
891                 run = ad.run;
892
893                 if (prefix)
894                         fprintf(output, "%s", prefix);
895
896                 uval = val * counter->scale;
897                 id = cpu_map__empty_aggr_cpu_id();
898                 id.core = cpu;
899                 printout(config, id, 0, counter, uval, prefix,
900                          run, ena, 1.0, &rt_stat);
901
902                 fputc('\n', output);
903         }
904 }
905
906 static void print_no_aggr_metric(struct perf_stat_config *config,
907                                  struct evlist *evlist,
908                                  char *prefix)
909 {
910         int cpu;
911         int nrcpus = 0;
912         struct evsel *counter;
913         u64 ena, run, val;
914         double uval;
915         struct aggr_cpu_id id;
916
917         nrcpus = evlist->core.cpus->nr;
918         for (cpu = 0; cpu < nrcpus; cpu++) {
919                 bool first = true;
920
921                 if (prefix)
922                         fputs(prefix, config->output);
923                 evlist__for_each_entry(evlist, counter) {
924                         id = cpu_map__empty_aggr_cpu_id();
925                         id.core = cpu;
926                         if (first) {
927                                 aggr_printout(config, counter, id, 0);
928                                 first = false;
929                         }
930                         val = perf_counts(counter->counts, cpu, 0)->val;
931                         ena = perf_counts(counter->counts, cpu, 0)->ena;
932                         run = perf_counts(counter->counts, cpu, 0)->run;
933
934                         uval = val * counter->scale;
935                         printout(config, id, 0, counter, uval, prefix,
936                                  run, ena, 1.0, &rt_stat);
937                 }
938                 fputc('\n', config->output);
939         }
940 }
941
942 static int aggr_header_lens[] = {
943         [AGGR_CORE] = 24,
944         [AGGR_DIE] = 18,
945         [AGGR_SOCKET] = 12,
946         [AGGR_NONE] = 6,
947         [AGGR_THREAD] = 24,
948         [AGGR_GLOBAL] = 0,
949 };
950
951 static const char *aggr_header_csv[] = {
952         [AGGR_CORE]     =       "core,cpus,",
953         [AGGR_DIE]      =       "die,cpus",
954         [AGGR_SOCKET]   =       "socket,cpus",
955         [AGGR_NONE]     =       "cpu,",
956         [AGGR_THREAD]   =       "comm-pid,",
957         [AGGR_GLOBAL]   =       ""
958 };
959
960 static void print_metric_headers(struct perf_stat_config *config,
961                                  struct evlist *evlist,
962                                  const char *prefix, bool no_indent)
963 {
964         struct perf_stat_output_ctx out;
965         struct evsel *counter;
966         struct outstate os = {
967                 .fh = config->output
968         };
969
970         if (prefix)
971                 fprintf(config->output, "%s", prefix);
972
973         if (!config->csv_output && !no_indent)
974                 fprintf(config->output, "%*s",
975                         aggr_header_lens[config->aggr_mode], "");
976         if (config->csv_output) {
977                 if (config->interval)
978                         fputs("time,", config->output);
979                 if (!config->iostat_run)
980                         fputs(aggr_header_csv[config->aggr_mode], config->output);
981         }
982         if (config->iostat_run)
983                 iostat_print_header_prefix(config);
984
985         /* Print metrics headers only */
986         evlist__for_each_entry(evlist, counter) {
987                 os.evsel = counter;
988                 out.ctx = &os;
989                 out.print_metric = print_metric_header;
990                 out.new_line = new_line_metric;
991                 out.force_header = true;
992                 perf_stat__print_shadow_stats(config, counter, 0,
993                                               0,
994                                               &out,
995                                               &config->metric_events,
996                                               &rt_stat);
997         }
998         fputc('\n', config->output);
999 }
1000
1001 static void print_interval(struct perf_stat_config *config,
1002                            struct evlist *evlist,
1003                            char *prefix, struct timespec *ts)
1004 {
1005         bool metric_only = config->metric_only;
1006         unsigned int unit_width = config->unit_width;
1007         FILE *output = config->output;
1008         static int num_print_interval;
1009
1010         if (config->interval_clear)
1011                 puts(CONSOLE_CLEAR);
1012
1013         if (!config->iostat_run)
1014                 sprintf(prefix, "%6lu.%09lu%s", (unsigned long) ts->tv_sec, ts->tv_nsec, config->csv_sep);
1015
1016         if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
1017                 switch (config->aggr_mode) {
1018                 case AGGR_NODE:
1019                         fprintf(output, "#           time node   cpus");
1020                         if (!metric_only)
1021                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1022                         break;
1023                 case AGGR_SOCKET:
1024                         fprintf(output, "#           time socket cpus");
1025                         if (!metric_only)
1026                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1027                         break;
1028                 case AGGR_DIE:
1029                         fprintf(output, "#           time die          cpus");
1030                         if (!metric_only)
1031                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1032                         break;
1033                 case AGGR_CORE:
1034                         fprintf(output, "#           time core            cpus");
1035                         if (!metric_only)
1036                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1037                         break;
1038                 case AGGR_NONE:
1039                         fprintf(output, "#           time CPU    ");
1040                         if (!metric_only)
1041                                 fprintf(output, "                counts %*s events\n", unit_width, "unit");
1042                         break;
1043                 case AGGR_THREAD:
1044                         fprintf(output, "#           time             comm-pid");
1045                         if (!metric_only)
1046                                 fprintf(output, "                  counts %*s events\n", unit_width, "unit");
1047                         break;
1048                 case AGGR_GLOBAL:
1049                 default:
1050                         if (!config->iostat_run) {
1051                                 fprintf(output, "#           time");
1052                                 if (!metric_only)
1053                                         fprintf(output, "             counts %*s events\n", unit_width, "unit");
1054                         }
1055                 case AGGR_UNSET:
1056                         break;
1057                 }
1058         }
1059
1060         if ((num_print_interval == 0 || config->interval_clear) && metric_only)
1061                 print_metric_headers(config, evlist, " ", true);
1062         if (++num_print_interval == 25)
1063                 num_print_interval = 0;
1064 }
1065
1066 static void print_header(struct perf_stat_config *config,
1067                          struct target *_target,
1068                          int argc, const char **argv)
1069 {
1070         FILE *output = config->output;
1071         int i;
1072
1073         fflush(stdout);
1074
1075         if (!config->csv_output) {
1076                 fprintf(output, "\n");
1077                 fprintf(output, " Performance counter stats for ");
1078                 if (_target->bpf_str)
1079                         fprintf(output, "\'BPF program(s) %s", _target->bpf_str);
1080                 else if (_target->system_wide)
1081                         fprintf(output, "\'system wide");
1082                 else if (_target->cpu_list)
1083                         fprintf(output, "\'CPU(s) %s", _target->cpu_list);
1084                 else if (!target__has_task(_target)) {
1085                         fprintf(output, "\'%s", argv ? argv[0] : "pipe");
1086                         for (i = 1; argv && (i < argc); i++)
1087                                 fprintf(output, " %s", argv[i]);
1088                 } else if (_target->pid)
1089                         fprintf(output, "process id \'%s", _target->pid);
1090                 else
1091                         fprintf(output, "thread id \'%s", _target->tid);
1092
1093                 fprintf(output, "\'");
1094                 if (config->run_count > 1)
1095                         fprintf(output, " (%d runs)", config->run_count);
1096                 fprintf(output, ":\n\n");
1097         }
1098 }
1099
1100 static int get_precision(double num)
1101 {
1102         if (num > 1)
1103                 return 0;
1104
1105         return lround(ceil(-log10(num)));
1106 }
1107
1108 static void print_table(struct perf_stat_config *config,
1109                         FILE *output, int precision, double avg)
1110 {
1111         char tmp[64];
1112         int idx, indent = 0;
1113
1114         scnprintf(tmp, 64, " %17.*f", precision, avg);
1115         while (tmp[indent] == ' ')
1116                 indent++;
1117
1118         fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1119
1120         for (idx = 0; idx < config->run_count; idx++) {
1121                 double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
1122                 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1123
1124                 fprintf(output, " %17.*f (%+.*f) ",
1125                         precision, run, precision, run - avg);
1126
1127                 for (h = 0; h < n; h++)
1128                         fprintf(output, "#");
1129
1130                 fprintf(output, "\n");
1131         }
1132
1133         fprintf(output, "\n%*s# Final result:\n", indent, "");
1134 }
1135
1136 static double timeval2double(struct timeval *t)
1137 {
1138         return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1139 }
1140
1141 static void print_footer(struct perf_stat_config *config)
1142 {
1143         double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1144         FILE *output = config->output;
1145
1146         if (!config->null_run)
1147                 fprintf(output, "\n");
1148
1149         if (config->run_count == 1) {
1150                 fprintf(output, " %17.9f seconds time elapsed", avg);
1151
1152                 if (config->ru_display) {
1153                         double ru_utime = timeval2double(&config->ru_data.ru_utime);
1154                         double ru_stime = timeval2double(&config->ru_data.ru_stime);
1155
1156                         fprintf(output, "\n\n");
1157                         fprintf(output, " %17.9f seconds user\n", ru_utime);
1158                         fprintf(output, " %17.9f seconds sys\n", ru_stime);
1159                 }
1160         } else {
1161                 double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1162                 /*
1163                  * Display at most 2 more significant
1164                  * digits than the stddev inaccuracy.
1165                  */
1166                 int precision = get_precision(sd) + 2;
1167
1168                 if (config->walltime_run_table)
1169                         print_table(config, output, precision, avg);
1170
1171                 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1172                         precision, avg, precision, sd);
1173
1174                 print_noise_pct(config, sd, avg);
1175         }
1176         fprintf(output, "\n\n");
1177
1178         if (config->print_free_counters_hint && sysctl__nmi_watchdog_enabled())
1179                 fprintf(output,
1180 "Some events weren't counted. Try disabling the NMI watchdog:\n"
1181 "       echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1182 "       perf stat ...\n"
1183 "       echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1184
1185         if (config->print_mixed_hw_group_error)
1186                 fprintf(output,
1187                         "The events in group usually have to be from "
1188                         "the same PMU. Try reorganizing the group.\n");
1189 }
1190
1191 static void print_percore_thread(struct perf_stat_config *config,
1192                                  struct evsel *counter, char *prefix)
1193 {
1194         int s;
1195         struct aggr_cpu_id s2, id;
1196         bool first = true;
1197
1198         for (int i = 0; i < evsel__nr_cpus(counter); i++) {
1199                 s2 = config->aggr_get_id(config, evsel__cpus(counter), i);
1200                 for (s = 0; s < config->aggr_map->nr; s++) {
1201                         id = config->aggr_map->map[s];
1202                         if (cpu_map__compare_aggr_cpu_id(s2, id))
1203                                 break;
1204                 }
1205
1206                 print_counter_aggrdata(config, counter, s,
1207                                        prefix, false,
1208                                        &first, i);
1209         }
1210 }
1211
1212 static void print_percore(struct perf_stat_config *config,
1213                           struct evsel *counter, char *prefix)
1214 {
1215         bool metric_only = config->metric_only;
1216         FILE *output = config->output;
1217         int s;
1218         bool first = true;
1219
1220         if (!config->aggr_map || !config->aggr_get_id)
1221                 return;
1222
1223         if (config->percore_show_thread)
1224                 return print_percore_thread(config, counter, prefix);
1225
1226         for (s = 0; s < config->aggr_map->nr; s++) {
1227                 if (prefix && metric_only)
1228                         fprintf(output, "%s", prefix);
1229
1230                 print_counter_aggrdata(config, counter, s,
1231                                        prefix, metric_only,
1232                                        &first, -1);
1233         }
1234
1235         if (metric_only)
1236                 fputc('\n', output);
1237 }
1238
1239 void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config,
1240                             struct target *_target, struct timespec *ts, int argc, const char **argv)
1241 {
1242         bool metric_only = config->metric_only;
1243         int interval = config->interval;
1244         struct evsel *counter;
1245         char buf[64], *prefix = NULL;
1246
1247         if (config->iostat_run)
1248                 evlist->selected = evlist__first(evlist);
1249
1250         if (interval)
1251                 print_interval(config, evlist, prefix = buf, ts);
1252         else
1253                 print_header(config, _target, argc, argv);
1254
1255         if (metric_only) {
1256                 static int num_print_iv;
1257
1258                 if (num_print_iv == 0 && !interval)
1259                         print_metric_headers(config, evlist, prefix, false);
1260                 if (num_print_iv++ == 25)
1261                         num_print_iv = 0;
1262                 if (config->aggr_mode == AGGR_GLOBAL && prefix && !config->iostat_run)
1263                         fprintf(config->output, "%s", prefix);
1264         }
1265
1266         switch (config->aggr_mode) {
1267         case AGGR_CORE:
1268         case AGGR_DIE:
1269         case AGGR_SOCKET:
1270         case AGGR_NODE:
1271                 print_aggr(config, evlist, prefix);
1272                 break;
1273         case AGGR_THREAD:
1274                 evlist__for_each_entry(evlist, counter) {
1275                         print_aggr_thread(config, _target, counter, prefix);
1276                 }
1277                 break;
1278         case AGGR_GLOBAL:
1279                 if (config->iostat_run)
1280                         iostat_print_counters(evlist, config, ts, prefix = buf,
1281                                               print_counter_aggr);
1282                 else {
1283                         evlist__for_each_entry(evlist, counter) {
1284                                 print_counter_aggr(config, counter, prefix);
1285                         }
1286                         if (metric_only)
1287                                 fputc('\n', config->output);
1288                 }
1289                 break;
1290         case AGGR_NONE:
1291                 if (metric_only)
1292                         print_no_aggr_metric(config, evlist, prefix);
1293                 else {
1294                         evlist__for_each_entry(evlist, counter) {
1295                                 if (counter->percore)
1296                                         print_percore(config, counter, prefix);
1297                                 else
1298                                         print_counter(config, counter, prefix);
1299                         }
1300                 }
1301                 break;
1302         case AGGR_UNSET:
1303         default:
1304                 break;
1305         }
1306
1307         if (!interval && !config->csv_output)
1308                 print_footer(config);
1309
1310         fflush(config->output);
1311 }