Merge branch 'fixes-rc1' into fixes
[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 ||
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                         if (!counter->use_config_name) {
559                                 ret = asprintf(&new_name, "%s/%s/",
560                                                counter->pmu_name, counter->name);
561                         }
562                 } else {
563                         ret = asprintf(&new_name, "%s [%s]",
564                                        counter->name, counter->pmu_name);
565                 }
566
567                 if (ret) {
568                         free(counter->name);
569                         counter->name = new_name;
570                 }
571         }
572
573         counter->uniquified_name = true;
574 }
575
576 static void collect_all_aliases(struct perf_stat_config *config, struct evsel *counter,
577                             void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
578                                        bool first),
579                             void *data)
580 {
581         struct evlist *evlist = counter->evlist;
582         struct evsel *alias;
583
584         alias = list_prepare_entry(counter, &(evlist->core.entries), core.node);
585         list_for_each_entry_continue (alias, &evlist->core.entries, core.node) {
586                 if (strcmp(evsel__name(alias), evsel__name(counter)) ||
587                     alias->scale != counter->scale ||
588                     alias->cgrp != counter->cgrp ||
589                     strcmp(alias->unit, counter->unit) ||
590                     evsel__is_clock(alias) != evsel__is_clock(counter) ||
591                     !strcmp(alias->pmu_name, counter->pmu_name))
592                         break;
593                 alias->merged_stat = true;
594                 cb(config, alias, data, false);
595         }
596 }
597
598 static bool collect_data(struct perf_stat_config *config, struct evsel *counter,
599                             void (*cb)(struct perf_stat_config *config, struct evsel *counter, void *data,
600                                        bool first),
601                             void *data)
602 {
603         if (counter->merged_stat)
604                 return false;
605         cb(config, counter, data, true);
606         if (config->no_merge)
607                 uniquify_event_name(counter);
608         else if (counter->auto_merge_stats)
609                 collect_all_aliases(config, counter, cb, data);
610         return true;
611 }
612
613 struct aggr_data {
614         u64 ena, run, val;
615         struct aggr_cpu_id id;
616         int nr;
617         int cpu;
618 };
619
620 static void aggr_cb(struct perf_stat_config *config,
621                     struct evsel *counter, void *data, bool first)
622 {
623         struct aggr_data *ad = data;
624         int cpu;
625         struct aggr_cpu_id s2;
626
627         for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
628                 struct perf_counts_values *counts;
629
630                 s2 = config->aggr_get_id(config, evsel__cpus(counter), cpu);
631                 if (!cpu_map__compare_aggr_cpu_id(s2, ad->id))
632                         continue;
633                 if (first)
634                         ad->nr++;
635                 counts = perf_counts(counter->counts, cpu, 0);
636                 /*
637                  * When any result is bad, make them all to give
638                  * consistent output in interval mode.
639                  */
640                 if (counts->ena == 0 || counts->run == 0 ||
641                     counter->counts->scaled == -1) {
642                         ad->ena = 0;
643                         ad->run = 0;
644                         break;
645                 }
646                 ad->val += counts->val;
647                 ad->ena += counts->ena;
648                 ad->run += counts->run;
649         }
650 }
651
652 static void print_counter_aggrdata(struct perf_stat_config *config,
653                                    struct evsel *counter, int s,
654                                    char *prefix, bool metric_only,
655                                    bool *first, int cpu)
656 {
657         struct aggr_data ad;
658         FILE *output = config->output;
659         u64 ena, run, val;
660         int nr;
661         struct aggr_cpu_id id;
662         double uval;
663
664         ad.id = id = config->aggr_map->map[s];
665         ad.val = ad.ena = ad.run = 0;
666         ad.nr = 0;
667         if (!collect_data(config, counter, aggr_cb, &ad))
668                 return;
669
670         if (perf_pmu__has_hybrid() && ad.ena == 0)
671                 return;
672
673         nr = ad.nr;
674         ena = ad.ena;
675         run = ad.run;
676         val = ad.val;
677         if (*first && metric_only) {
678                 *first = false;
679                 aggr_printout(config, counter, id, nr);
680         }
681         if (prefix && !metric_only)
682                 fprintf(output, "%s", prefix);
683
684         uval = val * counter->scale;
685         if (cpu != -1) {
686                 id = cpu_map__empty_aggr_cpu_id();
687                 id.core = cpu;
688         }
689         printout(config, id, nr, counter, uval,
690                  prefix, run, ena, 1.0, &rt_stat);
691         if (!metric_only)
692                 fputc('\n', output);
693 }
694
695 static void print_aggr(struct perf_stat_config *config,
696                        struct evlist *evlist,
697                        char *prefix)
698 {
699         bool metric_only = config->metric_only;
700         FILE *output = config->output;
701         struct evsel *counter;
702         int s;
703         bool first;
704
705         if (!config->aggr_map || !config->aggr_get_id)
706                 return;
707
708         aggr_update_shadow(config, evlist);
709
710         /*
711          * With metric_only everything is on a single line.
712          * Without each counter has its own line.
713          */
714         for (s = 0; s < config->aggr_map->nr; s++) {
715                 if (prefix && metric_only)
716                         fprintf(output, "%s", prefix);
717
718                 first = true;
719                 evlist__for_each_entry(evlist, counter) {
720                         print_counter_aggrdata(config, counter, s,
721                                                prefix, metric_only,
722                                                &first, -1);
723                 }
724                 if (metric_only)
725                         fputc('\n', output);
726         }
727 }
728
729 static int cmp_val(const void *a, const void *b)
730 {
731         return ((struct perf_aggr_thread_value *)b)->val -
732                 ((struct perf_aggr_thread_value *)a)->val;
733 }
734
735 static struct perf_aggr_thread_value *sort_aggr_thread(
736                                         struct evsel *counter,
737                                         int nthreads, int ncpus,
738                                         int *ret,
739                                         struct target *_target)
740 {
741         int cpu, thread, i = 0;
742         double uval;
743         struct perf_aggr_thread_value *buf;
744
745         buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value));
746         if (!buf)
747                 return NULL;
748
749         for (thread = 0; thread < nthreads; thread++) {
750                 u64 ena = 0, run = 0, val = 0;
751
752                 for (cpu = 0; cpu < ncpus; cpu++) {
753                         val += perf_counts(counter->counts, cpu, thread)->val;
754                         ena += perf_counts(counter->counts, cpu, thread)->ena;
755                         run += perf_counts(counter->counts, cpu, thread)->run;
756                 }
757
758                 uval = val * counter->scale;
759
760                 /*
761                  * Skip value 0 when enabling --per-thread globally,
762                  * otherwise too many 0 output.
763                  */
764                 if (uval == 0.0 && target__has_per_thread(_target))
765                         continue;
766
767                 buf[i].counter = counter;
768                 buf[i].id = cpu_map__empty_aggr_cpu_id();
769                 buf[i].id.thread = thread;
770                 buf[i].uval = uval;
771                 buf[i].val = val;
772                 buf[i].run = run;
773                 buf[i].ena = ena;
774                 i++;
775         }
776
777         qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val);
778
779         if (ret)
780                 *ret = i;
781
782         return buf;
783 }
784
785 static void print_aggr_thread(struct perf_stat_config *config,
786                               struct target *_target,
787                               struct evsel *counter, char *prefix)
788 {
789         FILE *output = config->output;
790         int nthreads = perf_thread_map__nr(counter->core.threads);
791         int ncpus = perf_cpu_map__nr(counter->core.cpus);
792         int thread, sorted_threads;
793         struct aggr_cpu_id id;
794         struct perf_aggr_thread_value *buf;
795
796         buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads, _target);
797         if (!buf) {
798                 perror("cannot sort aggr thread");
799                 return;
800         }
801
802         for (thread = 0; thread < sorted_threads; thread++) {
803                 if (prefix)
804                         fprintf(output, "%s", prefix);
805
806                 id = buf[thread].id;
807                 if (config->stats)
808                         printout(config, id, 0, buf[thread].counter, buf[thread].uval,
809                                  prefix, buf[thread].run, buf[thread].ena, 1.0,
810                                  &config->stats[id.thread]);
811                 else
812                         printout(config, id, 0, buf[thread].counter, buf[thread].uval,
813                                  prefix, buf[thread].run, buf[thread].ena, 1.0,
814                                  &rt_stat);
815                 fputc('\n', output);
816         }
817
818         free(buf);
819 }
820
821 struct caggr_data {
822         double avg, avg_enabled, avg_running;
823 };
824
825 static void counter_aggr_cb(struct perf_stat_config *config __maybe_unused,
826                             struct evsel *counter, void *data,
827                             bool first __maybe_unused)
828 {
829         struct caggr_data *cd = data;
830         struct perf_stat_evsel *ps = counter->stats;
831
832         cd->avg += avg_stats(&ps->res_stats[0]);
833         cd->avg_enabled += avg_stats(&ps->res_stats[1]);
834         cd->avg_running += avg_stats(&ps->res_stats[2]);
835 }
836
837 /*
838  * Print out the results of a single counter:
839  * aggregated counts in system-wide mode
840  */
841 static void print_counter_aggr(struct perf_stat_config *config,
842                                struct evsel *counter, char *prefix)
843 {
844         bool metric_only = config->metric_only;
845         FILE *output = config->output;
846         double uval;
847         struct caggr_data cd = { .avg = 0.0 };
848
849         if (!collect_data(config, counter, counter_aggr_cb, &cd))
850                 return;
851
852         if (prefix && !metric_only)
853                 fprintf(output, "%s", prefix);
854
855         uval = cd.avg * counter->scale;
856         printout(config, cpu_map__empty_aggr_cpu_id(), 0, counter, uval, prefix, cd.avg_running,
857                  cd.avg_enabled, cd.avg, &rt_stat);
858         if (!metric_only)
859                 fprintf(output, "\n");
860 }
861
862 static void counter_cb(struct perf_stat_config *config __maybe_unused,
863                        struct evsel *counter, void *data,
864                        bool first __maybe_unused)
865 {
866         struct aggr_data *ad = data;
867
868         ad->val += perf_counts(counter->counts, ad->cpu, 0)->val;
869         ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena;
870         ad->run += perf_counts(counter->counts, ad->cpu, 0)->run;
871 }
872
873 /*
874  * Print out the results of a single counter:
875  * does not use aggregated count in system-wide
876  */
877 static void print_counter(struct perf_stat_config *config,
878                           struct evsel *counter, char *prefix)
879 {
880         FILE *output = config->output;
881         u64 ena, run, val;
882         double uval;
883         int cpu;
884         struct aggr_cpu_id id;
885
886         for (cpu = 0; cpu < evsel__nr_cpus(counter); cpu++) {
887                 struct aggr_data ad = { .cpu = cpu };
888
889                 if (!collect_data(config, counter, counter_cb, &ad))
890                         return;
891                 val = ad.val;
892                 ena = ad.ena;
893                 run = ad.run;
894
895                 if (prefix)
896                         fprintf(output, "%s", prefix);
897
898                 uval = val * counter->scale;
899                 id = cpu_map__empty_aggr_cpu_id();
900                 id.core = cpu;
901                 printout(config, id, 0, counter, uval, prefix,
902                          run, ena, 1.0, &rt_stat);
903
904                 fputc('\n', output);
905         }
906 }
907
908 static void print_no_aggr_metric(struct perf_stat_config *config,
909                                  struct evlist *evlist,
910                                  char *prefix)
911 {
912         int cpu;
913         int nrcpus = 0;
914         struct evsel *counter;
915         u64 ena, run, val;
916         double uval;
917         struct aggr_cpu_id id;
918
919         nrcpus = evlist->core.cpus->nr;
920         for (cpu = 0; cpu < nrcpus; cpu++) {
921                 bool first = true;
922
923                 if (prefix)
924                         fputs(prefix, config->output);
925                 evlist__for_each_entry(evlist, counter) {
926                         id = cpu_map__empty_aggr_cpu_id();
927                         id.core = cpu;
928                         if (first) {
929                                 aggr_printout(config, counter, id, 0);
930                                 first = false;
931                         }
932                         val = perf_counts(counter->counts, cpu, 0)->val;
933                         ena = perf_counts(counter->counts, cpu, 0)->ena;
934                         run = perf_counts(counter->counts, cpu, 0)->run;
935
936                         uval = val * counter->scale;
937                         printout(config, id, 0, counter, uval, prefix,
938                                  run, ena, 1.0, &rt_stat);
939                 }
940                 fputc('\n', config->output);
941         }
942 }
943
944 static int aggr_header_lens[] = {
945         [AGGR_CORE] = 24,
946         [AGGR_DIE] = 18,
947         [AGGR_SOCKET] = 12,
948         [AGGR_NONE] = 6,
949         [AGGR_THREAD] = 24,
950         [AGGR_GLOBAL] = 0,
951 };
952
953 static const char *aggr_header_csv[] = {
954         [AGGR_CORE]     =       "core,cpus,",
955         [AGGR_DIE]      =       "die,cpus",
956         [AGGR_SOCKET]   =       "socket,cpus",
957         [AGGR_NONE]     =       "cpu,",
958         [AGGR_THREAD]   =       "comm-pid,",
959         [AGGR_GLOBAL]   =       ""
960 };
961
962 static void print_metric_headers(struct perf_stat_config *config,
963                                  struct evlist *evlist,
964                                  const char *prefix, bool no_indent)
965 {
966         struct perf_stat_output_ctx out;
967         struct evsel *counter;
968         struct outstate os = {
969                 .fh = config->output
970         };
971
972         if (prefix)
973                 fprintf(config->output, "%s", prefix);
974
975         if (!config->csv_output && !no_indent)
976                 fprintf(config->output, "%*s",
977                         aggr_header_lens[config->aggr_mode], "");
978         if (config->csv_output) {
979                 if (config->interval)
980                         fputs("time,", config->output);
981                 if (!config->iostat_run)
982                         fputs(aggr_header_csv[config->aggr_mode], config->output);
983         }
984         if (config->iostat_run)
985                 iostat_print_header_prefix(config);
986
987         /* Print metrics headers only */
988         evlist__for_each_entry(evlist, counter) {
989                 os.evsel = counter;
990                 out.ctx = &os;
991                 out.print_metric = print_metric_header;
992                 out.new_line = new_line_metric;
993                 out.force_header = true;
994                 perf_stat__print_shadow_stats(config, counter, 0,
995                                               0,
996                                               &out,
997                                               &config->metric_events,
998                                               &rt_stat);
999         }
1000         fputc('\n', config->output);
1001 }
1002
1003 static void print_interval(struct perf_stat_config *config,
1004                            struct evlist *evlist,
1005                            char *prefix, struct timespec *ts)
1006 {
1007         bool metric_only = config->metric_only;
1008         unsigned int unit_width = config->unit_width;
1009         FILE *output = config->output;
1010         static int num_print_interval;
1011
1012         if (config->interval_clear)
1013                 puts(CONSOLE_CLEAR);
1014
1015         if (!config->iostat_run)
1016                 sprintf(prefix, "%6lu.%09lu%s", (unsigned long) ts->tv_sec, ts->tv_nsec, config->csv_sep);
1017
1018         if ((num_print_interval == 0 && !config->csv_output) || config->interval_clear) {
1019                 switch (config->aggr_mode) {
1020                 case AGGR_NODE:
1021                         fprintf(output, "#           time node   cpus");
1022                         if (!metric_only)
1023                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1024                         break;
1025                 case AGGR_SOCKET:
1026                         fprintf(output, "#           time socket cpus");
1027                         if (!metric_only)
1028                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1029                         break;
1030                 case AGGR_DIE:
1031                         fprintf(output, "#           time die          cpus");
1032                         if (!metric_only)
1033                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1034                         break;
1035                 case AGGR_CORE:
1036                         fprintf(output, "#           time core            cpus");
1037                         if (!metric_only)
1038                                 fprintf(output, "             counts %*s events\n", unit_width, "unit");
1039                         break;
1040                 case AGGR_NONE:
1041                         fprintf(output, "#           time CPU    ");
1042                         if (!metric_only)
1043                                 fprintf(output, "                counts %*s events\n", unit_width, "unit");
1044                         break;
1045                 case AGGR_THREAD:
1046                         fprintf(output, "#           time             comm-pid");
1047                         if (!metric_only)
1048                                 fprintf(output, "                  counts %*s events\n", unit_width, "unit");
1049                         break;
1050                 case AGGR_GLOBAL:
1051                 default:
1052                         if (!config->iostat_run) {
1053                                 fprintf(output, "#           time");
1054                                 if (!metric_only)
1055                                         fprintf(output, "             counts %*s events\n", unit_width, "unit");
1056                         }
1057                 case AGGR_UNSET:
1058                         break;
1059                 }
1060         }
1061
1062         if ((num_print_interval == 0 || config->interval_clear) && metric_only)
1063                 print_metric_headers(config, evlist, " ", true);
1064         if (++num_print_interval == 25)
1065                 num_print_interval = 0;
1066 }
1067
1068 static void print_header(struct perf_stat_config *config,
1069                          struct target *_target,
1070                          int argc, const char **argv)
1071 {
1072         FILE *output = config->output;
1073         int i;
1074
1075         fflush(stdout);
1076
1077         if (!config->csv_output) {
1078                 fprintf(output, "\n");
1079                 fprintf(output, " Performance counter stats for ");
1080                 if (_target->bpf_str)
1081                         fprintf(output, "\'BPF program(s) %s", _target->bpf_str);
1082                 else if (_target->system_wide)
1083                         fprintf(output, "\'system wide");
1084                 else if (_target->cpu_list)
1085                         fprintf(output, "\'CPU(s) %s", _target->cpu_list);
1086                 else if (!target__has_task(_target)) {
1087                         fprintf(output, "\'%s", argv ? argv[0] : "pipe");
1088                         for (i = 1; argv && (i < argc); i++)
1089                                 fprintf(output, " %s", argv[i]);
1090                 } else if (_target->pid)
1091                         fprintf(output, "process id \'%s", _target->pid);
1092                 else
1093                         fprintf(output, "thread id \'%s", _target->tid);
1094
1095                 fprintf(output, "\'");
1096                 if (config->run_count > 1)
1097                         fprintf(output, " (%d runs)", config->run_count);
1098                 fprintf(output, ":\n\n");
1099         }
1100 }
1101
1102 static int get_precision(double num)
1103 {
1104         if (num > 1)
1105                 return 0;
1106
1107         return lround(ceil(-log10(num)));
1108 }
1109
1110 static void print_table(struct perf_stat_config *config,
1111                         FILE *output, int precision, double avg)
1112 {
1113         char tmp[64];
1114         int idx, indent = 0;
1115
1116         scnprintf(tmp, 64, " %17.*f", precision, avg);
1117         while (tmp[indent] == ' ')
1118                 indent++;
1119
1120         fprintf(output, "%*s# Table of individual measurements:\n", indent, "");
1121
1122         for (idx = 0; idx < config->run_count; idx++) {
1123                 double run = (double) config->walltime_run[idx] / NSEC_PER_SEC;
1124                 int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5);
1125
1126                 fprintf(output, " %17.*f (%+.*f) ",
1127                         precision, run, precision, run - avg);
1128
1129                 for (h = 0; h < n; h++)
1130                         fprintf(output, "#");
1131
1132                 fprintf(output, "\n");
1133         }
1134
1135         fprintf(output, "\n%*s# Final result:\n", indent, "");
1136 }
1137
1138 static double timeval2double(struct timeval *t)
1139 {
1140         return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC;
1141 }
1142
1143 static void print_footer(struct perf_stat_config *config)
1144 {
1145         double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1146         FILE *output = config->output;
1147
1148         if (!config->null_run)
1149                 fprintf(output, "\n");
1150
1151         if (config->run_count == 1) {
1152                 fprintf(output, " %17.9f seconds time elapsed", avg);
1153
1154                 if (config->ru_display) {
1155                         double ru_utime = timeval2double(&config->ru_data.ru_utime);
1156                         double ru_stime = timeval2double(&config->ru_data.ru_stime);
1157
1158                         fprintf(output, "\n\n");
1159                         fprintf(output, " %17.9f seconds user\n", ru_utime);
1160                         fprintf(output, " %17.9f seconds sys\n", ru_stime);
1161                 }
1162         } else {
1163                 double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
1164                 /*
1165                  * Display at most 2 more significant
1166                  * digits than the stddev inaccuracy.
1167                  */
1168                 int precision = get_precision(sd) + 2;
1169
1170                 if (config->walltime_run_table)
1171                         print_table(config, output, precision, avg);
1172
1173                 fprintf(output, " %17.*f +- %.*f seconds time elapsed",
1174                         precision, avg, precision, sd);
1175
1176                 print_noise_pct(config, sd, avg);
1177         }
1178         fprintf(output, "\n\n");
1179
1180         if (config->print_free_counters_hint && sysctl__nmi_watchdog_enabled())
1181                 fprintf(output,
1182 "Some events weren't counted. Try disabling the NMI watchdog:\n"
1183 "       echo 0 > /proc/sys/kernel/nmi_watchdog\n"
1184 "       perf stat ...\n"
1185 "       echo 1 > /proc/sys/kernel/nmi_watchdog\n");
1186
1187         if (config->print_mixed_hw_group_error)
1188                 fprintf(output,
1189                         "The events in group usually have to be from "
1190                         "the same PMU. Try reorganizing the group.\n");
1191 }
1192
1193 static void print_percore_thread(struct perf_stat_config *config,
1194                                  struct evsel *counter, char *prefix)
1195 {
1196         int s;
1197         struct aggr_cpu_id s2, id;
1198         bool first = true;
1199
1200         for (int i = 0; i < evsel__nr_cpus(counter); i++) {
1201                 s2 = config->aggr_get_id(config, evsel__cpus(counter), i);
1202                 for (s = 0; s < config->aggr_map->nr; s++) {
1203                         id = config->aggr_map->map[s];
1204                         if (cpu_map__compare_aggr_cpu_id(s2, id))
1205                                 break;
1206                 }
1207
1208                 print_counter_aggrdata(config, counter, s,
1209                                        prefix, false,
1210                                        &first, i);
1211         }
1212 }
1213
1214 static void print_percore(struct perf_stat_config *config,
1215                           struct evsel *counter, char *prefix)
1216 {
1217         bool metric_only = config->metric_only;
1218         FILE *output = config->output;
1219         int s;
1220         bool first = true;
1221
1222         if (!config->aggr_map || !config->aggr_get_id)
1223                 return;
1224
1225         if (config->percore_show_thread)
1226                 return print_percore_thread(config, counter, prefix);
1227
1228         for (s = 0; s < config->aggr_map->nr; s++) {
1229                 if (prefix && metric_only)
1230                         fprintf(output, "%s", prefix);
1231
1232                 print_counter_aggrdata(config, counter, s,
1233                                        prefix, metric_only,
1234                                        &first, -1);
1235         }
1236
1237         if (metric_only)
1238                 fputc('\n', output);
1239 }
1240
1241 void evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config,
1242                             struct target *_target, struct timespec *ts, int argc, const char **argv)
1243 {
1244         bool metric_only = config->metric_only;
1245         int interval = config->interval;
1246         struct evsel *counter;
1247         char buf[64], *prefix = NULL;
1248
1249         if (config->iostat_run)
1250                 evlist->selected = evlist__first(evlist);
1251
1252         if (interval)
1253                 print_interval(config, evlist, prefix = buf, ts);
1254         else
1255                 print_header(config, _target, argc, argv);
1256
1257         if (metric_only) {
1258                 static int num_print_iv;
1259
1260                 if (num_print_iv == 0 && !interval)
1261                         print_metric_headers(config, evlist, prefix, false);
1262                 if (num_print_iv++ == 25)
1263                         num_print_iv = 0;
1264                 if (config->aggr_mode == AGGR_GLOBAL && prefix && !config->iostat_run)
1265                         fprintf(config->output, "%s", prefix);
1266         }
1267
1268         switch (config->aggr_mode) {
1269         case AGGR_CORE:
1270         case AGGR_DIE:
1271         case AGGR_SOCKET:
1272         case AGGR_NODE:
1273                 print_aggr(config, evlist, prefix);
1274                 break;
1275         case AGGR_THREAD:
1276                 evlist__for_each_entry(evlist, counter) {
1277                         print_aggr_thread(config, _target, counter, prefix);
1278                 }
1279                 break;
1280         case AGGR_GLOBAL:
1281                 if (config->iostat_run)
1282                         iostat_print_counters(evlist, config, ts, prefix = buf,
1283                                               print_counter_aggr);
1284                 else {
1285                         evlist__for_each_entry(evlist, counter) {
1286                                 print_counter_aggr(config, counter, prefix);
1287                         }
1288                         if (metric_only)
1289                                 fputc('\n', config->output);
1290                 }
1291                 break;
1292         case AGGR_NONE:
1293                 if (metric_only)
1294                         print_no_aggr_metric(config, evlist, prefix);
1295                 else {
1296                         evlist__for_each_entry(evlist, counter) {
1297                                 if (counter->percore)
1298                                         print_percore(config, counter, prefix);
1299                                 else
1300                                         print_counter(config, counter, prefix);
1301                         }
1302                 }
1303                 break;
1304         case AGGR_UNSET:
1305         default:
1306                 break;
1307         }
1308
1309         if (!interval && !config->csv_output)
1310                 print_footer(config);
1311
1312         fflush(config->output);
1313 }