162306a36Sopenharmony_ci#include <stdlib.h> 262306a36Sopenharmony_ci#include <stdio.h> 362306a36Sopenharmony_ci#include <inttypes.h> 462306a36Sopenharmony_ci#include <linux/string.h> 562306a36Sopenharmony_ci#include <linux/time64.h> 662306a36Sopenharmony_ci#include <math.h> 762306a36Sopenharmony_ci#include <perf/cpumap.h> 862306a36Sopenharmony_ci#include "color.h" 962306a36Sopenharmony_ci#include "counts.h" 1062306a36Sopenharmony_ci#include "evlist.h" 1162306a36Sopenharmony_ci#include "evsel.h" 1262306a36Sopenharmony_ci#include "stat.h" 1362306a36Sopenharmony_ci#include "top.h" 1462306a36Sopenharmony_ci#include "thread_map.h" 1562306a36Sopenharmony_ci#include "cpumap.h" 1662306a36Sopenharmony_ci#include "string2.h" 1762306a36Sopenharmony_ci#include <linux/ctype.h> 1862306a36Sopenharmony_ci#include "cgroup.h" 1962306a36Sopenharmony_ci#include <api/fs/fs.h> 2062306a36Sopenharmony_ci#include "util.h" 2162306a36Sopenharmony_ci#include "iostat.h" 2262306a36Sopenharmony_ci#include "pmu.h" 2362306a36Sopenharmony_ci#include "pmus.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#define CNTR_NOT_SUPPORTED "<not supported>" 2662306a36Sopenharmony_ci#define CNTR_NOT_COUNTED "<not counted>" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define MGROUP_LEN 50 2962306a36Sopenharmony_ci#define METRIC_LEN 38 3062306a36Sopenharmony_ci#define EVNAME_LEN 32 3162306a36Sopenharmony_ci#define COUNTS_LEN 18 3262306a36Sopenharmony_ci#define INTERVAL_LEN 16 3362306a36Sopenharmony_ci#define CGROUP_LEN 16 3462306a36Sopenharmony_ci#define COMM_LEN 16 3562306a36Sopenharmony_ci#define PID_LEN 7 3662306a36Sopenharmony_ci#define CPUS_LEN 4 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic int aggr_header_lens[] = { 3962306a36Sopenharmony_ci [AGGR_CORE] = 18, 4062306a36Sopenharmony_ci [AGGR_CACHE] = 22, 4162306a36Sopenharmony_ci [AGGR_DIE] = 12, 4262306a36Sopenharmony_ci [AGGR_SOCKET] = 6, 4362306a36Sopenharmony_ci [AGGR_NODE] = 6, 4462306a36Sopenharmony_ci [AGGR_NONE] = 6, 4562306a36Sopenharmony_ci [AGGR_THREAD] = 16, 4662306a36Sopenharmony_ci [AGGR_GLOBAL] = 0, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic const char *aggr_header_csv[] = { 5062306a36Sopenharmony_ci [AGGR_CORE] = "core,cpus,", 5162306a36Sopenharmony_ci [AGGR_CACHE] = "cache,cpus,", 5262306a36Sopenharmony_ci [AGGR_DIE] = "die,cpus,", 5362306a36Sopenharmony_ci [AGGR_SOCKET] = "socket,cpus,", 5462306a36Sopenharmony_ci [AGGR_NONE] = "cpu,", 5562306a36Sopenharmony_ci [AGGR_THREAD] = "comm-pid,", 5662306a36Sopenharmony_ci [AGGR_NODE] = "node,", 5762306a36Sopenharmony_ci [AGGR_GLOBAL] = "" 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic const char *aggr_header_std[] = { 6162306a36Sopenharmony_ci [AGGR_CORE] = "core", 6262306a36Sopenharmony_ci [AGGR_CACHE] = "cache", 6362306a36Sopenharmony_ci [AGGR_DIE] = "die", 6462306a36Sopenharmony_ci [AGGR_SOCKET] = "socket", 6562306a36Sopenharmony_ci [AGGR_NONE] = "cpu", 6662306a36Sopenharmony_ci [AGGR_THREAD] = "comm-pid", 6762306a36Sopenharmony_ci [AGGR_NODE] = "node", 6862306a36Sopenharmony_ci [AGGR_GLOBAL] = "" 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic void print_running_std(struct perf_stat_config *config, u64 run, u64 ena) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci if (run != ena) 7462306a36Sopenharmony_ci fprintf(config->output, " (%.2f%%)", 100.0 * run / ena); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic void print_running_csv(struct perf_stat_config *config, u64 run, u64 ena) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci double enabled_percent = 100; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (run != ena) 8262306a36Sopenharmony_ci enabled_percent = 100 * run / ena; 8362306a36Sopenharmony_ci fprintf(config->output, "%s%" PRIu64 "%s%.2f", 8462306a36Sopenharmony_ci config->csv_sep, run, config->csv_sep, enabled_percent); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void print_running_json(struct perf_stat_config *config, u64 run, u64 ena) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci double enabled_percent = 100; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (run != ena) 9262306a36Sopenharmony_ci enabled_percent = 100 * run / ena; 9362306a36Sopenharmony_ci fprintf(config->output, "\"event-runtime\" : %" PRIu64 ", \"pcnt-running\" : %.2f, ", 9462306a36Sopenharmony_ci run, enabled_percent); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic void print_running(struct perf_stat_config *config, 9862306a36Sopenharmony_ci u64 run, u64 ena, bool before_metric) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci if (config->json_output) { 10162306a36Sopenharmony_ci if (before_metric) 10262306a36Sopenharmony_ci print_running_json(config, run, ena); 10362306a36Sopenharmony_ci } else if (config->csv_output) { 10462306a36Sopenharmony_ci if (before_metric) 10562306a36Sopenharmony_ci print_running_csv(config, run, ena); 10662306a36Sopenharmony_ci } else { 10762306a36Sopenharmony_ci if (!before_metric) 10862306a36Sopenharmony_ci print_running_std(config, run, ena); 10962306a36Sopenharmony_ci } 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic void print_noise_pct_std(struct perf_stat_config *config, 11362306a36Sopenharmony_ci double pct) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci if (pct) 11662306a36Sopenharmony_ci fprintf(config->output, " ( +-%6.2f%% )", pct); 11762306a36Sopenharmony_ci} 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic void print_noise_pct_csv(struct perf_stat_config *config, 12062306a36Sopenharmony_ci double pct) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci fprintf(config->output, "%s%.2f%%", config->csv_sep, pct); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic void print_noise_pct_json(struct perf_stat_config *config, 12662306a36Sopenharmony_ci double pct) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci fprintf(config->output, "\"variance\" : %.2f, ", pct); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic void print_noise_pct(struct perf_stat_config *config, 13262306a36Sopenharmony_ci double total, double avg, bool before_metric) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci double pct = rel_stddev_stats(total, avg); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (config->json_output) { 13762306a36Sopenharmony_ci if (before_metric) 13862306a36Sopenharmony_ci print_noise_pct_json(config, pct); 13962306a36Sopenharmony_ci } else if (config->csv_output) { 14062306a36Sopenharmony_ci if (before_metric) 14162306a36Sopenharmony_ci print_noise_pct_csv(config, pct); 14262306a36Sopenharmony_ci } else { 14362306a36Sopenharmony_ci if (!before_metric) 14462306a36Sopenharmony_ci print_noise_pct_std(config, pct); 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_cistatic void print_noise(struct perf_stat_config *config, 14962306a36Sopenharmony_ci struct evsel *evsel, double avg, bool before_metric) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci struct perf_stat_evsel *ps; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (config->run_count == 1) 15462306a36Sopenharmony_ci return; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci ps = evsel->stats; 15762306a36Sopenharmony_ci print_noise_pct(config, stddev_stats(&ps->res_stats), avg, before_metric); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic void print_cgroup_std(struct perf_stat_config *config, const char *cgrp_name) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci fprintf(config->output, " %-*s", CGROUP_LEN, cgrp_name); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic void print_cgroup_csv(struct perf_stat_config *config, const char *cgrp_name) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci fprintf(config->output, "%s%s", config->csv_sep, cgrp_name); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic void print_cgroup_json(struct perf_stat_config *config, const char *cgrp_name) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci fprintf(config->output, "\"cgroup\" : \"%s\", ", cgrp_name); 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic void print_cgroup(struct perf_stat_config *config, struct cgroup *cgrp) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci if (nr_cgroups || config->cgroup_list) { 17862306a36Sopenharmony_ci const char *cgrp_name = cgrp ? cgrp->name : ""; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci if (config->json_output) 18162306a36Sopenharmony_ci print_cgroup_json(config, cgrp_name); 18262306a36Sopenharmony_ci else if (config->csv_output) 18362306a36Sopenharmony_ci print_cgroup_csv(config, cgrp_name); 18462306a36Sopenharmony_ci else 18562306a36Sopenharmony_ci print_cgroup_std(config, cgrp_name); 18662306a36Sopenharmony_ci } 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void print_aggr_id_std(struct perf_stat_config *config, 19062306a36Sopenharmony_ci struct evsel *evsel, struct aggr_cpu_id id, int aggr_nr) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci FILE *output = config->output; 19362306a36Sopenharmony_ci int idx = config->aggr_mode; 19462306a36Sopenharmony_ci char buf[128]; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci switch (config->aggr_mode) { 19762306a36Sopenharmony_ci case AGGR_CORE: 19862306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "S%d-D%d-C%d", id.socket, id.die, id.core); 19962306a36Sopenharmony_ci break; 20062306a36Sopenharmony_ci case AGGR_CACHE: 20162306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "S%d-D%d-L%d-ID%d", 20262306a36Sopenharmony_ci id.socket, id.die, id.cache_lvl, id.cache); 20362306a36Sopenharmony_ci break; 20462306a36Sopenharmony_ci case AGGR_DIE: 20562306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "S%d-D%d", id.socket, id.die); 20662306a36Sopenharmony_ci break; 20762306a36Sopenharmony_ci case AGGR_SOCKET: 20862306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "S%d", id.socket); 20962306a36Sopenharmony_ci break; 21062306a36Sopenharmony_ci case AGGR_NODE: 21162306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "N%d", id.node); 21262306a36Sopenharmony_ci break; 21362306a36Sopenharmony_ci case AGGR_NONE: 21462306a36Sopenharmony_ci if (evsel->percore && !config->percore_show_thread) { 21562306a36Sopenharmony_ci snprintf(buf, sizeof(buf), "S%d-D%d-C%d ", 21662306a36Sopenharmony_ci id.socket, id.die, id.core); 21762306a36Sopenharmony_ci fprintf(output, "%-*s ", 21862306a36Sopenharmony_ci aggr_header_lens[AGGR_CORE], buf); 21962306a36Sopenharmony_ci } else if (id.cpu.cpu > -1) { 22062306a36Sopenharmony_ci fprintf(output, "CPU%-*d ", 22162306a36Sopenharmony_ci aggr_header_lens[AGGR_NONE] - 3, id.cpu.cpu); 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci return; 22462306a36Sopenharmony_ci case AGGR_THREAD: 22562306a36Sopenharmony_ci fprintf(output, "%*s-%-*d ", 22662306a36Sopenharmony_ci COMM_LEN, perf_thread_map__comm(evsel->core.threads, id.thread_idx), 22762306a36Sopenharmony_ci PID_LEN, perf_thread_map__pid(evsel->core.threads, id.thread_idx)); 22862306a36Sopenharmony_ci return; 22962306a36Sopenharmony_ci case AGGR_GLOBAL: 23062306a36Sopenharmony_ci case AGGR_UNSET: 23162306a36Sopenharmony_ci case AGGR_MAX: 23262306a36Sopenharmony_ci default: 23362306a36Sopenharmony_ci return; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci fprintf(output, "%-*s %*d ", aggr_header_lens[idx], buf, 4, aggr_nr); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic void print_aggr_id_csv(struct perf_stat_config *config, 24062306a36Sopenharmony_ci struct evsel *evsel, struct aggr_cpu_id id, int aggr_nr) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci FILE *output = config->output; 24362306a36Sopenharmony_ci const char *sep = config->csv_sep; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci switch (config->aggr_mode) { 24662306a36Sopenharmony_ci case AGGR_CORE: 24762306a36Sopenharmony_ci fprintf(output, "S%d-D%d-C%d%s%d%s", 24862306a36Sopenharmony_ci id.socket, id.die, id.core, sep, aggr_nr, sep); 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci case AGGR_CACHE: 25162306a36Sopenharmony_ci fprintf(config->output, "S%d-D%d-L%d-ID%d%s%d%s", 25262306a36Sopenharmony_ci id.socket, id.die, id.cache_lvl, id.cache, sep, aggr_nr, sep); 25362306a36Sopenharmony_ci break; 25462306a36Sopenharmony_ci case AGGR_DIE: 25562306a36Sopenharmony_ci fprintf(output, "S%d-D%d%s%d%s", 25662306a36Sopenharmony_ci id.socket, id.die, sep, aggr_nr, sep); 25762306a36Sopenharmony_ci break; 25862306a36Sopenharmony_ci case AGGR_SOCKET: 25962306a36Sopenharmony_ci fprintf(output, "S%d%s%d%s", 26062306a36Sopenharmony_ci id.socket, sep, aggr_nr, sep); 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case AGGR_NODE: 26362306a36Sopenharmony_ci fprintf(output, "N%d%s%d%s", 26462306a36Sopenharmony_ci id.node, sep, aggr_nr, sep); 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci case AGGR_NONE: 26762306a36Sopenharmony_ci if (evsel->percore && !config->percore_show_thread) { 26862306a36Sopenharmony_ci fprintf(output, "S%d-D%d-C%d%s", 26962306a36Sopenharmony_ci id.socket, id.die, id.core, sep); 27062306a36Sopenharmony_ci } else if (id.cpu.cpu > -1) { 27162306a36Sopenharmony_ci fprintf(output, "CPU%d%s", 27262306a36Sopenharmony_ci id.cpu.cpu, sep); 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci break; 27562306a36Sopenharmony_ci case AGGR_THREAD: 27662306a36Sopenharmony_ci fprintf(output, "%s-%d%s", 27762306a36Sopenharmony_ci perf_thread_map__comm(evsel->core.threads, id.thread_idx), 27862306a36Sopenharmony_ci perf_thread_map__pid(evsel->core.threads, id.thread_idx), 27962306a36Sopenharmony_ci sep); 28062306a36Sopenharmony_ci break; 28162306a36Sopenharmony_ci case AGGR_GLOBAL: 28262306a36Sopenharmony_ci case AGGR_UNSET: 28362306a36Sopenharmony_ci case AGGR_MAX: 28462306a36Sopenharmony_ci default: 28562306a36Sopenharmony_ci break; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic void print_aggr_id_json(struct perf_stat_config *config, 29062306a36Sopenharmony_ci struct evsel *evsel, struct aggr_cpu_id id, int aggr_nr) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci FILE *output = config->output; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci switch (config->aggr_mode) { 29562306a36Sopenharmony_ci case AGGR_CORE: 29662306a36Sopenharmony_ci fprintf(output, "\"core\" : \"S%d-D%d-C%d\", \"aggregate-number\" : %d, ", 29762306a36Sopenharmony_ci id.socket, id.die, id.core, aggr_nr); 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci case AGGR_CACHE: 30062306a36Sopenharmony_ci fprintf(output, "\"cache\" : \"S%d-D%d-L%d-ID%d\", \"aggregate-number\" : %d, ", 30162306a36Sopenharmony_ci id.socket, id.die, id.cache_lvl, id.cache, aggr_nr); 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci case AGGR_DIE: 30462306a36Sopenharmony_ci fprintf(output, "\"die\" : \"S%d-D%d\", \"aggregate-number\" : %d, ", 30562306a36Sopenharmony_ci id.socket, id.die, aggr_nr); 30662306a36Sopenharmony_ci break; 30762306a36Sopenharmony_ci case AGGR_SOCKET: 30862306a36Sopenharmony_ci fprintf(output, "\"socket\" : \"S%d\", \"aggregate-number\" : %d, ", 30962306a36Sopenharmony_ci id.socket, aggr_nr); 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci case AGGR_NODE: 31262306a36Sopenharmony_ci fprintf(output, "\"node\" : \"N%d\", \"aggregate-number\" : %d, ", 31362306a36Sopenharmony_ci id.node, aggr_nr); 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci case AGGR_NONE: 31662306a36Sopenharmony_ci if (evsel->percore && !config->percore_show_thread) { 31762306a36Sopenharmony_ci fprintf(output, "\"core\" : \"S%d-D%d-C%d\"", 31862306a36Sopenharmony_ci id.socket, id.die, id.core); 31962306a36Sopenharmony_ci } else if (id.cpu.cpu > -1) { 32062306a36Sopenharmony_ci fprintf(output, "\"cpu\" : \"%d\", ", 32162306a36Sopenharmony_ci id.cpu.cpu); 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci break; 32462306a36Sopenharmony_ci case AGGR_THREAD: 32562306a36Sopenharmony_ci fprintf(output, "\"thread\" : \"%s-%d\", ", 32662306a36Sopenharmony_ci perf_thread_map__comm(evsel->core.threads, id.thread_idx), 32762306a36Sopenharmony_ci perf_thread_map__pid(evsel->core.threads, id.thread_idx)); 32862306a36Sopenharmony_ci break; 32962306a36Sopenharmony_ci case AGGR_GLOBAL: 33062306a36Sopenharmony_ci case AGGR_UNSET: 33162306a36Sopenharmony_ci case AGGR_MAX: 33262306a36Sopenharmony_ci default: 33362306a36Sopenharmony_ci break; 33462306a36Sopenharmony_ci } 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic void aggr_printout(struct perf_stat_config *config, 33862306a36Sopenharmony_ci struct evsel *evsel, struct aggr_cpu_id id, int aggr_nr) 33962306a36Sopenharmony_ci{ 34062306a36Sopenharmony_ci if (config->json_output) 34162306a36Sopenharmony_ci print_aggr_id_json(config, evsel, id, aggr_nr); 34262306a36Sopenharmony_ci else if (config->csv_output) 34362306a36Sopenharmony_ci print_aggr_id_csv(config, evsel, id, aggr_nr); 34462306a36Sopenharmony_ci else 34562306a36Sopenharmony_ci print_aggr_id_std(config, evsel, id, aggr_nr); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_cistruct outstate { 34962306a36Sopenharmony_ci FILE *fh; 35062306a36Sopenharmony_ci bool newline; 35162306a36Sopenharmony_ci bool first; 35262306a36Sopenharmony_ci const char *prefix; 35362306a36Sopenharmony_ci int nfields; 35462306a36Sopenharmony_ci int aggr_nr; 35562306a36Sopenharmony_ci struct aggr_cpu_id id; 35662306a36Sopenharmony_ci struct evsel *evsel; 35762306a36Sopenharmony_ci struct cgroup *cgrp; 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic void new_line_std(struct perf_stat_config *config __maybe_unused, 36162306a36Sopenharmony_ci void *ctx) 36262306a36Sopenharmony_ci{ 36362306a36Sopenharmony_ci struct outstate *os = ctx; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci os->newline = true; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic inline void __new_line_std_csv(struct perf_stat_config *config, 36962306a36Sopenharmony_ci struct outstate *os) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci fputc('\n', os->fh); 37262306a36Sopenharmony_ci if (os->prefix) 37362306a36Sopenharmony_ci fputs(os->prefix, os->fh); 37462306a36Sopenharmony_ci aggr_printout(config, os->evsel, os->id, os->aggr_nr); 37562306a36Sopenharmony_ci} 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic inline void __new_line_std(struct outstate *os) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci fprintf(os->fh, " "); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic void do_new_line_std(struct perf_stat_config *config, 38362306a36Sopenharmony_ci struct outstate *os) 38462306a36Sopenharmony_ci{ 38562306a36Sopenharmony_ci __new_line_std_csv(config, os); 38662306a36Sopenharmony_ci if (config->aggr_mode == AGGR_NONE) 38762306a36Sopenharmony_ci fprintf(os->fh, " "); 38862306a36Sopenharmony_ci __new_line_std(os); 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic void print_metric_std(struct perf_stat_config *config, 39262306a36Sopenharmony_ci void *ctx, const char *color, const char *fmt, 39362306a36Sopenharmony_ci const char *unit, double val) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci struct outstate *os = ctx; 39662306a36Sopenharmony_ci FILE *out = os->fh; 39762306a36Sopenharmony_ci int n; 39862306a36Sopenharmony_ci bool newline = os->newline; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci os->newline = false; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (unit == NULL || fmt == NULL) { 40362306a36Sopenharmony_ci fprintf(out, "%-*s", METRIC_LEN, ""); 40462306a36Sopenharmony_ci return; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci if (newline) 40862306a36Sopenharmony_ci do_new_line_std(config, os); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci n = fprintf(out, " # "); 41162306a36Sopenharmony_ci if (color) 41262306a36Sopenharmony_ci n += color_fprintf(out, color, fmt, val); 41362306a36Sopenharmony_ci else 41462306a36Sopenharmony_ci n += fprintf(out, fmt, val); 41562306a36Sopenharmony_ci fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic void new_line_csv(struct perf_stat_config *config, void *ctx) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct outstate *os = ctx; 42162306a36Sopenharmony_ci int i; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci __new_line_std_csv(config, os); 42462306a36Sopenharmony_ci for (i = 0; i < os->nfields; i++) 42562306a36Sopenharmony_ci fputs(config->csv_sep, os->fh); 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic void print_metric_csv(struct perf_stat_config *config __maybe_unused, 42962306a36Sopenharmony_ci void *ctx, 43062306a36Sopenharmony_ci const char *color __maybe_unused, 43162306a36Sopenharmony_ci const char *fmt, const char *unit, double val) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci struct outstate *os = ctx; 43462306a36Sopenharmony_ci FILE *out = os->fh; 43562306a36Sopenharmony_ci char buf[64], *vals, *ends; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (unit == NULL || fmt == NULL) { 43862306a36Sopenharmony_ci fprintf(out, "%s%s", config->csv_sep, config->csv_sep); 43962306a36Sopenharmony_ci return; 44062306a36Sopenharmony_ci } 44162306a36Sopenharmony_ci snprintf(buf, sizeof(buf), fmt, val); 44262306a36Sopenharmony_ci ends = vals = skip_spaces(buf); 44362306a36Sopenharmony_ci while (isdigit(*ends) || *ends == '.') 44462306a36Sopenharmony_ci ends++; 44562306a36Sopenharmony_ci *ends = 0; 44662306a36Sopenharmony_ci fprintf(out, "%s%s%s%s", config->csv_sep, vals, config->csv_sep, skip_spaces(unit)); 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic void print_metric_json(struct perf_stat_config *config __maybe_unused, 45062306a36Sopenharmony_ci void *ctx, 45162306a36Sopenharmony_ci const char *color __maybe_unused, 45262306a36Sopenharmony_ci const char *fmt __maybe_unused, 45362306a36Sopenharmony_ci const char *unit, double val) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct outstate *os = ctx; 45662306a36Sopenharmony_ci FILE *out = os->fh; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci fprintf(out, "\"metric-value\" : \"%f\", ", val); 45962306a36Sopenharmony_ci fprintf(out, "\"metric-unit\" : \"%s\"", unit); 46062306a36Sopenharmony_ci if (!config->metric_only) 46162306a36Sopenharmony_ci fprintf(out, "}"); 46262306a36Sopenharmony_ci} 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_cistatic void new_line_json(struct perf_stat_config *config, void *ctx) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct outstate *os = ctx; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci fputs("\n{", os->fh); 46962306a36Sopenharmony_ci if (os->prefix) 47062306a36Sopenharmony_ci fprintf(os->fh, "%s", os->prefix); 47162306a36Sopenharmony_ci aggr_printout(config, os->evsel, os->id, os->aggr_nr); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic void print_metricgroup_header_json(struct perf_stat_config *config, 47562306a36Sopenharmony_ci void *ctx, 47662306a36Sopenharmony_ci const char *metricgroup_name) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci if (!metricgroup_name) 47962306a36Sopenharmony_ci return; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci fprintf(config->output, "\"metricgroup\" : \"%s\"}", metricgroup_name); 48262306a36Sopenharmony_ci new_line_json(config, ctx); 48362306a36Sopenharmony_ci} 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_cistatic void print_metricgroup_header_csv(struct perf_stat_config *config, 48662306a36Sopenharmony_ci void *ctx, 48762306a36Sopenharmony_ci const char *metricgroup_name) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci struct outstate *os = ctx; 49062306a36Sopenharmony_ci int i; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (!metricgroup_name) { 49362306a36Sopenharmony_ci /* Leave space for running and enabling */ 49462306a36Sopenharmony_ci for (i = 0; i < os->nfields - 2; i++) 49562306a36Sopenharmony_ci fputs(config->csv_sep, os->fh); 49662306a36Sopenharmony_ci return; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci for (i = 0; i < os->nfields; i++) 50062306a36Sopenharmony_ci fputs(config->csv_sep, os->fh); 50162306a36Sopenharmony_ci fprintf(config->output, "%s", metricgroup_name); 50262306a36Sopenharmony_ci new_line_csv(config, ctx); 50362306a36Sopenharmony_ci} 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic void print_metricgroup_header_std(struct perf_stat_config *config, 50662306a36Sopenharmony_ci void *ctx, 50762306a36Sopenharmony_ci const char *metricgroup_name) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci struct outstate *os = ctx; 51062306a36Sopenharmony_ci int n; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci if (!metricgroup_name) { 51362306a36Sopenharmony_ci __new_line_std(os); 51462306a36Sopenharmony_ci return; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci n = fprintf(config->output, " %*s", EVNAME_LEN, metricgroup_name); 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci fprintf(config->output, "%*s", MGROUP_LEN - n - 1, ""); 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci/* Filter out some columns that don't work well in metrics only mode */ 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_cistatic bool valid_only_metric(const char *unit) 52562306a36Sopenharmony_ci{ 52662306a36Sopenharmony_ci if (!unit) 52762306a36Sopenharmony_ci return false; 52862306a36Sopenharmony_ci if (strstr(unit, "/sec") || 52962306a36Sopenharmony_ci strstr(unit, "CPUs utilized")) 53062306a36Sopenharmony_ci return false; 53162306a36Sopenharmony_ci return true; 53262306a36Sopenharmony_ci} 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_cistatic const char *fixunit(char *buf, struct evsel *evsel, 53562306a36Sopenharmony_ci const char *unit) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci if (!strncmp(unit, "of all", 6)) { 53862306a36Sopenharmony_ci snprintf(buf, 1024, "%s %s", evsel__name(evsel), 53962306a36Sopenharmony_ci unit); 54062306a36Sopenharmony_ci return buf; 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci return unit; 54362306a36Sopenharmony_ci} 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_cistatic void print_metric_only(struct perf_stat_config *config, 54662306a36Sopenharmony_ci void *ctx, const char *color, const char *fmt, 54762306a36Sopenharmony_ci const char *unit, double val) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci struct outstate *os = ctx; 55062306a36Sopenharmony_ci FILE *out = os->fh; 55162306a36Sopenharmony_ci char buf[1024], str[1024]; 55262306a36Sopenharmony_ci unsigned mlen = config->metric_only_len; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (!valid_only_metric(unit)) 55562306a36Sopenharmony_ci return; 55662306a36Sopenharmony_ci unit = fixunit(buf, os->evsel, unit); 55762306a36Sopenharmony_ci if (mlen < strlen(unit)) 55862306a36Sopenharmony_ci mlen = strlen(unit) + 1; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci if (color) 56162306a36Sopenharmony_ci mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci color_snprintf(str, sizeof(str), color ?: "", fmt ?: "", val); 56462306a36Sopenharmony_ci fprintf(out, "%*s ", mlen, str); 56562306a36Sopenharmony_ci os->first = false; 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic void print_metric_only_csv(struct perf_stat_config *config __maybe_unused, 56962306a36Sopenharmony_ci void *ctx, const char *color __maybe_unused, 57062306a36Sopenharmony_ci const char *fmt, 57162306a36Sopenharmony_ci const char *unit, double val) 57262306a36Sopenharmony_ci{ 57362306a36Sopenharmony_ci struct outstate *os = ctx; 57462306a36Sopenharmony_ci FILE *out = os->fh; 57562306a36Sopenharmony_ci char buf[64], *vals, *ends; 57662306a36Sopenharmony_ci char tbuf[1024]; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (!valid_only_metric(unit)) 57962306a36Sopenharmony_ci return; 58062306a36Sopenharmony_ci unit = fixunit(tbuf, os->evsel, unit); 58162306a36Sopenharmony_ci snprintf(buf, sizeof(buf), fmt ?: "", val); 58262306a36Sopenharmony_ci ends = vals = skip_spaces(buf); 58362306a36Sopenharmony_ci while (isdigit(*ends) || *ends == '.') 58462306a36Sopenharmony_ci ends++; 58562306a36Sopenharmony_ci *ends = 0; 58662306a36Sopenharmony_ci fprintf(out, "%s%s", vals, config->csv_sep); 58762306a36Sopenharmony_ci os->first = false; 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic void print_metric_only_json(struct perf_stat_config *config __maybe_unused, 59162306a36Sopenharmony_ci void *ctx, const char *color __maybe_unused, 59262306a36Sopenharmony_ci const char *fmt, 59362306a36Sopenharmony_ci const char *unit, double val) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci struct outstate *os = ctx; 59662306a36Sopenharmony_ci FILE *out = os->fh; 59762306a36Sopenharmony_ci char buf[64], *vals, *ends; 59862306a36Sopenharmony_ci char tbuf[1024]; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci if (!valid_only_metric(unit)) 60162306a36Sopenharmony_ci return; 60262306a36Sopenharmony_ci unit = fixunit(tbuf, os->evsel, unit); 60362306a36Sopenharmony_ci snprintf(buf, sizeof(buf), fmt ?: "", val); 60462306a36Sopenharmony_ci ends = vals = skip_spaces(buf); 60562306a36Sopenharmony_ci while (isdigit(*ends) || *ends == '.') 60662306a36Sopenharmony_ci ends++; 60762306a36Sopenharmony_ci *ends = 0; 60862306a36Sopenharmony_ci if (!unit[0] || !vals[0]) 60962306a36Sopenharmony_ci return; 61062306a36Sopenharmony_ci fprintf(out, "%s\"%s\" : \"%s\"", os->first ? "" : ", ", unit, vals); 61162306a36Sopenharmony_ci os->first = false; 61262306a36Sopenharmony_ci} 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cistatic void new_line_metric(struct perf_stat_config *config __maybe_unused, 61562306a36Sopenharmony_ci void *ctx __maybe_unused) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_cistatic void print_metric_header(struct perf_stat_config *config, 62062306a36Sopenharmony_ci void *ctx, const char *color __maybe_unused, 62162306a36Sopenharmony_ci const char *fmt __maybe_unused, 62262306a36Sopenharmony_ci const char *unit, double val __maybe_unused) 62362306a36Sopenharmony_ci{ 62462306a36Sopenharmony_ci struct outstate *os = ctx; 62562306a36Sopenharmony_ci char tbuf[1024]; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* In case of iostat, print metric header for first root port only */ 62862306a36Sopenharmony_ci if (config->iostat_run && 62962306a36Sopenharmony_ci os->evsel->priv != os->evsel->evlist->selected->priv) 63062306a36Sopenharmony_ci return; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (os->evsel->cgrp != os->cgrp) 63362306a36Sopenharmony_ci return; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if (!valid_only_metric(unit)) 63662306a36Sopenharmony_ci return; 63762306a36Sopenharmony_ci unit = fixunit(tbuf, os->evsel, unit); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci if (config->json_output) 64062306a36Sopenharmony_ci return; 64162306a36Sopenharmony_ci else if (config->csv_output) 64262306a36Sopenharmony_ci fprintf(os->fh, "%s%s", unit, config->csv_sep); 64362306a36Sopenharmony_ci else 64462306a36Sopenharmony_ci fprintf(os->fh, "%*s ", config->metric_only_len, unit); 64562306a36Sopenharmony_ci} 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_cistatic void print_counter_value_std(struct perf_stat_config *config, 64862306a36Sopenharmony_ci struct evsel *evsel, double avg, bool ok) 64962306a36Sopenharmony_ci{ 65062306a36Sopenharmony_ci FILE *output = config->output; 65162306a36Sopenharmony_ci double sc = evsel->scale; 65262306a36Sopenharmony_ci const char *fmt; 65362306a36Sopenharmony_ci const char *bad_count = evsel->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (config->big_num) 65662306a36Sopenharmony_ci fmt = floor(sc) != sc ? "%'*.2f " : "%'*.0f "; 65762306a36Sopenharmony_ci else 65862306a36Sopenharmony_ci fmt = floor(sc) != sc ? "%*.2f " : "%*.0f "; 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci if (ok) 66162306a36Sopenharmony_ci fprintf(output, fmt, COUNTS_LEN, avg); 66262306a36Sopenharmony_ci else 66362306a36Sopenharmony_ci fprintf(output, "%*s ", COUNTS_LEN, bad_count); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci if (evsel->unit) 66662306a36Sopenharmony_ci fprintf(output, "%-*s ", config->unit_width, evsel->unit); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci fprintf(output, "%-*s", EVNAME_LEN, evsel__name(evsel)); 66962306a36Sopenharmony_ci} 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistatic void print_counter_value_csv(struct perf_stat_config *config, 67262306a36Sopenharmony_ci struct evsel *evsel, double avg, bool ok) 67362306a36Sopenharmony_ci{ 67462306a36Sopenharmony_ci FILE *output = config->output; 67562306a36Sopenharmony_ci double sc = evsel->scale; 67662306a36Sopenharmony_ci const char *sep = config->csv_sep; 67762306a36Sopenharmony_ci const char *fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; 67862306a36Sopenharmony_ci const char *bad_count = evsel->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED; 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci if (ok) 68162306a36Sopenharmony_ci fprintf(output, fmt, avg, sep); 68262306a36Sopenharmony_ci else 68362306a36Sopenharmony_ci fprintf(output, "%s%s", bad_count, sep); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci if (evsel->unit) 68662306a36Sopenharmony_ci fprintf(output, "%s%s", evsel->unit, sep); 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci fprintf(output, "%s", evsel__name(evsel)); 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_cistatic void print_counter_value_json(struct perf_stat_config *config, 69262306a36Sopenharmony_ci struct evsel *evsel, double avg, bool ok) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci FILE *output = config->output; 69562306a36Sopenharmony_ci const char *bad_count = evsel->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci if (ok) 69862306a36Sopenharmony_ci fprintf(output, "\"counter-value\" : \"%f\", ", avg); 69962306a36Sopenharmony_ci else 70062306a36Sopenharmony_ci fprintf(output, "\"counter-value\" : \"%s\", ", bad_count); 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if (evsel->unit) 70362306a36Sopenharmony_ci fprintf(output, "\"unit\" : \"%s\", ", evsel->unit); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci fprintf(output, "\"event\" : \"%s\", ", evsel__name(evsel)); 70662306a36Sopenharmony_ci} 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_cistatic void print_counter_value(struct perf_stat_config *config, 70962306a36Sopenharmony_ci struct evsel *evsel, double avg, bool ok) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci if (config->json_output) 71262306a36Sopenharmony_ci print_counter_value_json(config, evsel, avg, ok); 71362306a36Sopenharmony_ci else if (config->csv_output) 71462306a36Sopenharmony_ci print_counter_value_csv(config, evsel, avg, ok); 71562306a36Sopenharmony_ci else 71662306a36Sopenharmony_ci print_counter_value_std(config, evsel, avg, ok); 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic void abs_printout(struct perf_stat_config *config, 72062306a36Sopenharmony_ci struct aggr_cpu_id id, int aggr_nr, 72162306a36Sopenharmony_ci struct evsel *evsel, double avg, bool ok) 72262306a36Sopenharmony_ci{ 72362306a36Sopenharmony_ci aggr_printout(config, evsel, id, aggr_nr); 72462306a36Sopenharmony_ci print_counter_value(config, evsel, avg, ok); 72562306a36Sopenharmony_ci print_cgroup(config, evsel->cgrp); 72662306a36Sopenharmony_ci} 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_cistatic bool is_mixed_hw_group(struct evsel *counter) 72962306a36Sopenharmony_ci{ 73062306a36Sopenharmony_ci struct evlist *evlist = counter->evlist; 73162306a36Sopenharmony_ci u32 pmu_type = counter->core.attr.type; 73262306a36Sopenharmony_ci struct evsel *pos; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci if (counter->core.nr_members < 2) 73562306a36Sopenharmony_ci return false; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci evlist__for_each_entry(evlist, pos) { 73862306a36Sopenharmony_ci /* software events can be part of any hardware group */ 73962306a36Sopenharmony_ci if (pos->core.attr.type == PERF_TYPE_SOFTWARE) 74062306a36Sopenharmony_ci continue; 74162306a36Sopenharmony_ci if (pmu_type == PERF_TYPE_SOFTWARE) { 74262306a36Sopenharmony_ci pmu_type = pos->core.attr.type; 74362306a36Sopenharmony_ci continue; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci if (pmu_type != pos->core.attr.type) 74662306a36Sopenharmony_ci return true; 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return false; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic bool evlist__has_hybrid(struct evlist *evlist) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci struct evsel *evsel; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (perf_pmus__num_core_pmus() == 1) 75762306a36Sopenharmony_ci return false; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 76062306a36Sopenharmony_ci if (evsel->core.is_pmu_core) 76162306a36Sopenharmony_ci return true; 76262306a36Sopenharmony_ci } 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci return false; 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_cistatic void printout(struct perf_stat_config *config, struct outstate *os, 76862306a36Sopenharmony_ci double uval, u64 run, u64 ena, double noise, int aggr_idx) 76962306a36Sopenharmony_ci{ 77062306a36Sopenharmony_ci struct perf_stat_output_ctx out; 77162306a36Sopenharmony_ci print_metric_t pm; 77262306a36Sopenharmony_ci new_line_t nl; 77362306a36Sopenharmony_ci print_metricgroup_header_t pmh; 77462306a36Sopenharmony_ci bool ok = true; 77562306a36Sopenharmony_ci struct evsel *counter = os->evsel; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci if (config->csv_output) { 77862306a36Sopenharmony_ci pm = config->metric_only ? print_metric_only_csv : print_metric_csv; 77962306a36Sopenharmony_ci nl = config->metric_only ? new_line_metric : new_line_csv; 78062306a36Sopenharmony_ci pmh = print_metricgroup_header_csv; 78162306a36Sopenharmony_ci os->nfields = 4 + (counter->cgrp ? 1 : 0); 78262306a36Sopenharmony_ci } else if (config->json_output) { 78362306a36Sopenharmony_ci pm = config->metric_only ? print_metric_only_json : print_metric_json; 78462306a36Sopenharmony_ci nl = config->metric_only ? new_line_metric : new_line_json; 78562306a36Sopenharmony_ci pmh = print_metricgroup_header_json; 78662306a36Sopenharmony_ci } else { 78762306a36Sopenharmony_ci pm = config->metric_only ? print_metric_only : print_metric_std; 78862306a36Sopenharmony_ci nl = config->metric_only ? new_line_metric : new_line_std; 78962306a36Sopenharmony_ci pmh = print_metricgroup_header_std; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (run == 0 || ena == 0 || counter->counts->scaled == -1) { 79362306a36Sopenharmony_ci if (config->metric_only) { 79462306a36Sopenharmony_ci pm(config, os, NULL, "", "", 0); 79562306a36Sopenharmony_ci return; 79662306a36Sopenharmony_ci } 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci ok = false; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (counter->supported) { 80162306a36Sopenharmony_ci if (!evlist__has_hybrid(counter->evlist)) { 80262306a36Sopenharmony_ci config->print_free_counters_hint = 1; 80362306a36Sopenharmony_ci if (is_mixed_hw_group(counter)) 80462306a36Sopenharmony_ci config->print_mixed_hw_group_error = 1; 80562306a36Sopenharmony_ci } 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci out.print_metric = pm; 81062306a36Sopenharmony_ci out.new_line = nl; 81162306a36Sopenharmony_ci out.print_metricgroup_header = pmh; 81262306a36Sopenharmony_ci out.ctx = os; 81362306a36Sopenharmony_ci out.force_header = false; 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci if (!config->metric_only && !counter->default_metricgroup) { 81662306a36Sopenharmony_ci abs_printout(config, os->id, os->aggr_nr, counter, uval, ok); 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci print_noise(config, counter, noise, /*before_metric=*/true); 81962306a36Sopenharmony_ci print_running(config, run, ena, /*before_metric=*/true); 82062306a36Sopenharmony_ci } 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci if (ok) { 82362306a36Sopenharmony_ci if (!config->metric_only && counter->default_metricgroup) { 82462306a36Sopenharmony_ci void *from = NULL; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci aggr_printout(config, os->evsel, os->id, os->aggr_nr); 82762306a36Sopenharmony_ci /* Print out all the metricgroup with the same metric event. */ 82862306a36Sopenharmony_ci do { 82962306a36Sopenharmony_ci int num = 0; 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Print out the new line for the next new metricgroup. */ 83262306a36Sopenharmony_ci if (from) { 83362306a36Sopenharmony_ci if (config->json_output) 83462306a36Sopenharmony_ci new_line_json(config, (void *)os); 83562306a36Sopenharmony_ci else 83662306a36Sopenharmony_ci __new_line_std_csv(config, os); 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci print_noise(config, counter, noise, /*before_metric=*/true); 84062306a36Sopenharmony_ci print_running(config, run, ena, /*before_metric=*/true); 84162306a36Sopenharmony_ci from = perf_stat__print_shadow_stats_metricgroup(config, counter, aggr_idx, 84262306a36Sopenharmony_ci &num, from, &out, 84362306a36Sopenharmony_ci &config->metric_events); 84462306a36Sopenharmony_ci } while (from != NULL); 84562306a36Sopenharmony_ci } else 84662306a36Sopenharmony_ci perf_stat__print_shadow_stats(config, counter, uval, aggr_idx, 84762306a36Sopenharmony_ci &out, &config->metric_events); 84862306a36Sopenharmony_ci } else { 84962306a36Sopenharmony_ci pm(config, os, /*color=*/NULL, /*format=*/NULL, /*unit=*/"", /*val=*/0); 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci if (!config->metric_only) { 85362306a36Sopenharmony_ci print_noise(config, counter, noise, /*before_metric=*/false); 85462306a36Sopenharmony_ci print_running(config, run, ena, /*before_metric=*/false); 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci} 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_cistatic void uniquify_event_name(struct evsel *counter) 85962306a36Sopenharmony_ci{ 86062306a36Sopenharmony_ci char *new_name; 86162306a36Sopenharmony_ci char *config; 86262306a36Sopenharmony_ci int ret = 0; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci if (counter->uniquified_name || counter->use_config_name || 86562306a36Sopenharmony_ci !counter->pmu_name || !strncmp(evsel__name(counter), counter->pmu_name, 86662306a36Sopenharmony_ci strlen(counter->pmu_name))) 86762306a36Sopenharmony_ci return; 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci config = strchr(counter->name, '/'); 87062306a36Sopenharmony_ci if (config) { 87162306a36Sopenharmony_ci if (asprintf(&new_name, 87262306a36Sopenharmony_ci "%s%s", counter->pmu_name, config) > 0) { 87362306a36Sopenharmony_ci free(counter->name); 87462306a36Sopenharmony_ci counter->name = new_name; 87562306a36Sopenharmony_ci } 87662306a36Sopenharmony_ci } else { 87762306a36Sopenharmony_ci if (evsel__is_hybrid(counter)) { 87862306a36Sopenharmony_ci ret = asprintf(&new_name, "%s/%s/", 87962306a36Sopenharmony_ci counter->pmu_name, counter->name); 88062306a36Sopenharmony_ci } else { 88162306a36Sopenharmony_ci ret = asprintf(&new_name, "%s [%s]", 88262306a36Sopenharmony_ci counter->name, counter->pmu_name); 88362306a36Sopenharmony_ci } 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci if (ret) { 88662306a36Sopenharmony_ci free(counter->name); 88762306a36Sopenharmony_ci counter->name = new_name; 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci } 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci counter->uniquified_name = true; 89262306a36Sopenharmony_ci} 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cistatic bool hybrid_uniquify(struct evsel *evsel, struct perf_stat_config *config) 89562306a36Sopenharmony_ci{ 89662306a36Sopenharmony_ci return evsel__is_hybrid(evsel) && !config->hybrid_merge; 89762306a36Sopenharmony_ci} 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_cistatic void uniquify_counter(struct perf_stat_config *config, struct evsel *counter) 90062306a36Sopenharmony_ci{ 90162306a36Sopenharmony_ci if (config->no_merge || hybrid_uniquify(counter, config)) 90262306a36Sopenharmony_ci uniquify_event_name(counter); 90362306a36Sopenharmony_ci} 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci/** 90662306a36Sopenharmony_ci * should_skip_zero_count() - Check if the event should print 0 values. 90762306a36Sopenharmony_ci * @config: The perf stat configuration (including aggregation mode). 90862306a36Sopenharmony_ci * @counter: The evsel with its associated cpumap. 90962306a36Sopenharmony_ci * @id: The aggregation id that is being queried. 91062306a36Sopenharmony_ci * 91162306a36Sopenharmony_ci * Due to mismatch between the event cpumap or thread-map and the 91262306a36Sopenharmony_ci * aggregation mode, sometimes it'd iterate the counter with the map 91362306a36Sopenharmony_ci * which does not contain any values. 91462306a36Sopenharmony_ci * 91562306a36Sopenharmony_ci * For example, uncore events have dedicated CPUs to manage them, 91662306a36Sopenharmony_ci * result for other CPUs should be zero and skipped. 91762306a36Sopenharmony_ci * 91862306a36Sopenharmony_ci * Return: %true if the value should NOT be printed, %false if the value 91962306a36Sopenharmony_ci * needs to be printed like "<not counted>" or "<not supported>". 92062306a36Sopenharmony_ci */ 92162306a36Sopenharmony_cistatic bool should_skip_zero_counter(struct perf_stat_config *config, 92262306a36Sopenharmony_ci struct evsel *counter, 92362306a36Sopenharmony_ci const struct aggr_cpu_id *id) 92462306a36Sopenharmony_ci{ 92562306a36Sopenharmony_ci struct perf_cpu cpu; 92662306a36Sopenharmony_ci int idx; 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci /* 92962306a36Sopenharmony_ci * Skip value 0 when enabling --per-thread globally, 93062306a36Sopenharmony_ci * otherwise it will have too many 0 output. 93162306a36Sopenharmony_ci */ 93262306a36Sopenharmony_ci if (config->aggr_mode == AGGR_THREAD && config->system_wide) 93362306a36Sopenharmony_ci return true; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci /* Tool events have the software PMU but are only gathered on 1. */ 93662306a36Sopenharmony_ci if (evsel__is_tool(counter)) 93762306a36Sopenharmony_ci return true; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci /* 94062306a36Sopenharmony_ci * Skip value 0 when it's an uncore event and the given aggr id 94162306a36Sopenharmony_ci * does not belong to the PMU cpumask. 94262306a36Sopenharmony_ci */ 94362306a36Sopenharmony_ci if (!counter->pmu || !counter->pmu->is_uncore) 94462306a36Sopenharmony_ci return false; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci perf_cpu_map__for_each_cpu(cpu, idx, counter->pmu->cpus) { 94762306a36Sopenharmony_ci struct aggr_cpu_id own_id = config->aggr_get_id(config, cpu); 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci if (aggr_cpu_id__equal(id, &own_id)) 95062306a36Sopenharmony_ci return false; 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci return true; 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_cistatic void print_counter_aggrdata(struct perf_stat_config *config, 95662306a36Sopenharmony_ci struct evsel *counter, int aggr_idx, 95762306a36Sopenharmony_ci struct outstate *os) 95862306a36Sopenharmony_ci{ 95962306a36Sopenharmony_ci FILE *output = config->output; 96062306a36Sopenharmony_ci u64 ena, run, val; 96162306a36Sopenharmony_ci double uval; 96262306a36Sopenharmony_ci struct perf_stat_evsel *ps = counter->stats; 96362306a36Sopenharmony_ci struct perf_stat_aggr *aggr = &ps->aggr[aggr_idx]; 96462306a36Sopenharmony_ci struct aggr_cpu_id id = config->aggr_map->map[aggr_idx]; 96562306a36Sopenharmony_ci double avg = aggr->counts.val; 96662306a36Sopenharmony_ci bool metric_only = config->metric_only; 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci os->id = id; 96962306a36Sopenharmony_ci os->aggr_nr = aggr->nr; 97062306a36Sopenharmony_ci os->evsel = counter; 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci /* Skip already merged uncore/hybrid events */ 97362306a36Sopenharmony_ci if (counter->merged_stat) 97462306a36Sopenharmony_ci return; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci uniquify_counter(config, counter); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci val = aggr->counts.val; 97962306a36Sopenharmony_ci ena = aggr->counts.ena; 98062306a36Sopenharmony_ci run = aggr->counts.run; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (perf_stat__skip_metric_event(counter, &config->metric_events, ena, run)) 98362306a36Sopenharmony_ci return; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci if (val == 0 && should_skip_zero_counter(config, counter, &id)) 98662306a36Sopenharmony_ci return; 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci if (!metric_only) { 98962306a36Sopenharmony_ci if (config->json_output) 99062306a36Sopenharmony_ci fputc('{', output); 99162306a36Sopenharmony_ci if (os->prefix) 99262306a36Sopenharmony_ci fprintf(output, "%s", os->prefix); 99362306a36Sopenharmony_ci else if (config->summary && config->csv_output && 99462306a36Sopenharmony_ci !config->no_csv_summary && !config->interval) 99562306a36Sopenharmony_ci fprintf(output, "%s%s", "summary", config->csv_sep); 99662306a36Sopenharmony_ci } 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci uval = val * counter->scale; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci printout(config, os, uval, run, ena, avg, aggr_idx); 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci if (!metric_only) 100362306a36Sopenharmony_ci fputc('\n', output); 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_cistatic void print_metric_begin(struct perf_stat_config *config, 100762306a36Sopenharmony_ci struct evlist *evlist, 100862306a36Sopenharmony_ci struct outstate *os, int aggr_idx) 100962306a36Sopenharmony_ci{ 101062306a36Sopenharmony_ci struct perf_stat_aggr *aggr; 101162306a36Sopenharmony_ci struct aggr_cpu_id id; 101262306a36Sopenharmony_ci struct evsel *evsel; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci os->first = true; 101562306a36Sopenharmony_ci if (!config->metric_only) 101662306a36Sopenharmony_ci return; 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci if (config->json_output) 101962306a36Sopenharmony_ci fputc('{', config->output); 102062306a36Sopenharmony_ci if (os->prefix) 102162306a36Sopenharmony_ci fprintf(config->output, "%s", os->prefix); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci evsel = evlist__first(evlist); 102462306a36Sopenharmony_ci id = config->aggr_map->map[aggr_idx]; 102562306a36Sopenharmony_ci aggr = &evsel->stats->aggr[aggr_idx]; 102662306a36Sopenharmony_ci aggr_printout(config, evsel, id, aggr->nr); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci print_cgroup(config, os->cgrp ? : evsel->cgrp); 102962306a36Sopenharmony_ci} 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_cistatic void print_metric_end(struct perf_stat_config *config, struct outstate *os) 103262306a36Sopenharmony_ci{ 103362306a36Sopenharmony_ci FILE *output = config->output; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci if (!config->metric_only) 103662306a36Sopenharmony_ci return; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci if (config->json_output) { 103962306a36Sopenharmony_ci if (os->first) 104062306a36Sopenharmony_ci fputs("\"metric-value\" : \"none\"", output); 104162306a36Sopenharmony_ci fputc('}', output); 104262306a36Sopenharmony_ci } 104362306a36Sopenharmony_ci fputc('\n', output); 104462306a36Sopenharmony_ci} 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_cistatic void print_aggr(struct perf_stat_config *config, 104762306a36Sopenharmony_ci struct evlist *evlist, 104862306a36Sopenharmony_ci struct outstate *os) 104962306a36Sopenharmony_ci{ 105062306a36Sopenharmony_ci struct evsel *counter; 105162306a36Sopenharmony_ci int aggr_idx; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci if (!config->aggr_map || !config->aggr_get_id) 105462306a36Sopenharmony_ci return; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci /* 105762306a36Sopenharmony_ci * With metric_only everything is on a single line. 105862306a36Sopenharmony_ci * Without each counter has its own line. 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_ci cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) { 106162306a36Sopenharmony_ci print_metric_begin(config, evlist, os, aggr_idx); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 106462306a36Sopenharmony_ci print_counter_aggrdata(config, counter, aggr_idx, os); 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci print_metric_end(config, os); 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_cistatic void print_aggr_cgroup(struct perf_stat_config *config, 107162306a36Sopenharmony_ci struct evlist *evlist, 107262306a36Sopenharmony_ci struct outstate *os) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci struct evsel *counter, *evsel; 107562306a36Sopenharmony_ci int aggr_idx; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci if (!config->aggr_map || !config->aggr_get_id) 107862306a36Sopenharmony_ci return; 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 108162306a36Sopenharmony_ci if (os->cgrp == evsel->cgrp) 108262306a36Sopenharmony_ci continue; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci os->cgrp = evsel->cgrp; 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) { 108762306a36Sopenharmony_ci print_metric_begin(config, evlist, os, aggr_idx); 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 109062306a36Sopenharmony_ci if (counter->cgrp != os->cgrp) 109162306a36Sopenharmony_ci continue; 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci print_counter_aggrdata(config, counter, aggr_idx, os); 109462306a36Sopenharmony_ci } 109562306a36Sopenharmony_ci print_metric_end(config, os); 109662306a36Sopenharmony_ci } 109762306a36Sopenharmony_ci } 109862306a36Sopenharmony_ci} 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_cistatic void print_counter(struct perf_stat_config *config, 110162306a36Sopenharmony_ci struct evsel *counter, struct outstate *os) 110262306a36Sopenharmony_ci{ 110362306a36Sopenharmony_ci int aggr_idx; 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_ci /* AGGR_THREAD doesn't have config->aggr_get_id */ 110662306a36Sopenharmony_ci if (!config->aggr_map) 110762306a36Sopenharmony_ci return; 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) { 111062306a36Sopenharmony_ci print_counter_aggrdata(config, counter, aggr_idx, os); 111162306a36Sopenharmony_ci } 111262306a36Sopenharmony_ci} 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_cistatic void print_no_aggr_metric(struct perf_stat_config *config, 111562306a36Sopenharmony_ci struct evlist *evlist, 111662306a36Sopenharmony_ci struct outstate *os) 111762306a36Sopenharmony_ci{ 111862306a36Sopenharmony_ci int all_idx; 111962306a36Sopenharmony_ci struct perf_cpu cpu; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci perf_cpu_map__for_each_cpu(cpu, all_idx, evlist->core.user_requested_cpus) { 112262306a36Sopenharmony_ci struct evsel *counter; 112362306a36Sopenharmony_ci bool first = true; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 112662306a36Sopenharmony_ci u64 ena, run, val; 112762306a36Sopenharmony_ci double uval; 112862306a36Sopenharmony_ci struct perf_stat_evsel *ps = counter->stats; 112962306a36Sopenharmony_ci int aggr_idx = perf_cpu_map__idx(evsel__cpus(counter), cpu); 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci if (aggr_idx < 0) 113262306a36Sopenharmony_ci continue; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci os->evsel = counter; 113562306a36Sopenharmony_ci os->id = aggr_cpu_id__cpu(cpu, /*data=*/NULL); 113662306a36Sopenharmony_ci if (first) { 113762306a36Sopenharmony_ci print_metric_begin(config, evlist, os, aggr_idx); 113862306a36Sopenharmony_ci first = false; 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci val = ps->aggr[aggr_idx].counts.val; 114162306a36Sopenharmony_ci ena = ps->aggr[aggr_idx].counts.ena; 114262306a36Sopenharmony_ci run = ps->aggr[aggr_idx].counts.run; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci uval = val * counter->scale; 114562306a36Sopenharmony_ci printout(config, os, uval, run, ena, 1.0, aggr_idx); 114662306a36Sopenharmony_ci } 114762306a36Sopenharmony_ci if (!first) 114862306a36Sopenharmony_ci print_metric_end(config, os); 114962306a36Sopenharmony_ci } 115062306a36Sopenharmony_ci} 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_cistatic void print_metric_headers_std(struct perf_stat_config *config, 115362306a36Sopenharmony_ci bool no_indent) 115462306a36Sopenharmony_ci{ 115562306a36Sopenharmony_ci fputc(' ', config->output); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if (!no_indent) { 115862306a36Sopenharmony_ci int len = aggr_header_lens[config->aggr_mode]; 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_ci if (nr_cgroups || config->cgroup_list) 116162306a36Sopenharmony_ci len += CGROUP_LEN + 1; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci fprintf(config->output, "%*s", len, ""); 116462306a36Sopenharmony_ci } 116562306a36Sopenharmony_ci} 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_cistatic void print_metric_headers_csv(struct perf_stat_config *config, 116862306a36Sopenharmony_ci bool no_indent __maybe_unused) 116962306a36Sopenharmony_ci{ 117062306a36Sopenharmony_ci if (config->interval) 117162306a36Sopenharmony_ci fputs("time,", config->output); 117262306a36Sopenharmony_ci if (!config->iostat_run) 117362306a36Sopenharmony_ci fputs(aggr_header_csv[config->aggr_mode], config->output); 117462306a36Sopenharmony_ci} 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_cistatic void print_metric_headers_json(struct perf_stat_config *config __maybe_unused, 117762306a36Sopenharmony_ci bool no_indent __maybe_unused) 117862306a36Sopenharmony_ci{ 117962306a36Sopenharmony_ci} 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_cistatic void print_metric_headers(struct perf_stat_config *config, 118262306a36Sopenharmony_ci struct evlist *evlist, bool no_indent) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci struct evsel *counter; 118562306a36Sopenharmony_ci struct outstate os = { 118662306a36Sopenharmony_ci .fh = config->output 118762306a36Sopenharmony_ci }; 118862306a36Sopenharmony_ci struct perf_stat_output_ctx out = { 118962306a36Sopenharmony_ci .ctx = &os, 119062306a36Sopenharmony_ci .print_metric = print_metric_header, 119162306a36Sopenharmony_ci .new_line = new_line_metric, 119262306a36Sopenharmony_ci .force_header = true, 119362306a36Sopenharmony_ci }; 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci if (config->json_output) 119662306a36Sopenharmony_ci print_metric_headers_json(config, no_indent); 119762306a36Sopenharmony_ci else if (config->csv_output) 119862306a36Sopenharmony_ci print_metric_headers_csv(config, no_indent); 119962306a36Sopenharmony_ci else 120062306a36Sopenharmony_ci print_metric_headers_std(config, no_indent); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci if (config->iostat_run) 120362306a36Sopenharmony_ci iostat_print_header_prefix(config); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci if (config->cgroup_list) 120662306a36Sopenharmony_ci os.cgrp = evlist__first(evlist)->cgrp; 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_ci /* Print metrics headers only */ 120962306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 121062306a36Sopenharmony_ci os.evsel = counter; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci perf_stat__print_shadow_stats(config, counter, 0, 121362306a36Sopenharmony_ci 0, 121462306a36Sopenharmony_ci &out, 121562306a36Sopenharmony_ci &config->metric_events); 121662306a36Sopenharmony_ci } 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci if (!config->json_output) 121962306a36Sopenharmony_ci fputc('\n', config->output); 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic void prepare_interval(struct perf_stat_config *config, 122362306a36Sopenharmony_ci char *prefix, size_t len, struct timespec *ts) 122462306a36Sopenharmony_ci{ 122562306a36Sopenharmony_ci if (config->iostat_run) 122662306a36Sopenharmony_ci return; 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci if (config->json_output) 122962306a36Sopenharmony_ci scnprintf(prefix, len, "\"interval\" : %lu.%09lu, ", 123062306a36Sopenharmony_ci (unsigned long) ts->tv_sec, ts->tv_nsec); 123162306a36Sopenharmony_ci else if (config->csv_output) 123262306a36Sopenharmony_ci scnprintf(prefix, len, "%lu.%09lu%s", 123362306a36Sopenharmony_ci (unsigned long) ts->tv_sec, ts->tv_nsec, config->csv_sep); 123462306a36Sopenharmony_ci else 123562306a36Sopenharmony_ci scnprintf(prefix, len, "%6lu.%09lu ", 123662306a36Sopenharmony_ci (unsigned long) ts->tv_sec, ts->tv_nsec); 123762306a36Sopenharmony_ci} 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_cistatic void print_header_interval_std(struct perf_stat_config *config, 124062306a36Sopenharmony_ci struct target *_target __maybe_unused, 124162306a36Sopenharmony_ci struct evlist *evlist, 124262306a36Sopenharmony_ci int argc __maybe_unused, 124362306a36Sopenharmony_ci const char **argv __maybe_unused) 124462306a36Sopenharmony_ci{ 124562306a36Sopenharmony_ci FILE *output = config->output; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci switch (config->aggr_mode) { 124862306a36Sopenharmony_ci case AGGR_NODE: 124962306a36Sopenharmony_ci case AGGR_SOCKET: 125062306a36Sopenharmony_ci case AGGR_DIE: 125162306a36Sopenharmony_ci case AGGR_CACHE: 125262306a36Sopenharmony_ci case AGGR_CORE: 125362306a36Sopenharmony_ci fprintf(output, "#%*s %-*s cpus", 125462306a36Sopenharmony_ci INTERVAL_LEN - 1, "time", 125562306a36Sopenharmony_ci aggr_header_lens[config->aggr_mode], 125662306a36Sopenharmony_ci aggr_header_std[config->aggr_mode]); 125762306a36Sopenharmony_ci break; 125862306a36Sopenharmony_ci case AGGR_NONE: 125962306a36Sopenharmony_ci fprintf(output, "#%*s %-*s", 126062306a36Sopenharmony_ci INTERVAL_LEN - 1, "time", 126162306a36Sopenharmony_ci aggr_header_lens[config->aggr_mode], 126262306a36Sopenharmony_ci aggr_header_std[config->aggr_mode]); 126362306a36Sopenharmony_ci break; 126462306a36Sopenharmony_ci case AGGR_THREAD: 126562306a36Sopenharmony_ci fprintf(output, "#%*s %*s-%-*s", 126662306a36Sopenharmony_ci INTERVAL_LEN - 1, "time", 126762306a36Sopenharmony_ci COMM_LEN, "comm", PID_LEN, "pid"); 126862306a36Sopenharmony_ci break; 126962306a36Sopenharmony_ci case AGGR_GLOBAL: 127062306a36Sopenharmony_ci default: 127162306a36Sopenharmony_ci if (!config->iostat_run) 127262306a36Sopenharmony_ci fprintf(output, "#%*s", 127362306a36Sopenharmony_ci INTERVAL_LEN - 1, "time"); 127462306a36Sopenharmony_ci case AGGR_UNSET: 127562306a36Sopenharmony_ci case AGGR_MAX: 127662306a36Sopenharmony_ci break; 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci if (config->metric_only) 128062306a36Sopenharmony_ci print_metric_headers(config, evlist, true); 128162306a36Sopenharmony_ci else 128262306a36Sopenharmony_ci fprintf(output, " %*s %*s events\n", 128362306a36Sopenharmony_ci COUNTS_LEN, "counts", config->unit_width, "unit"); 128462306a36Sopenharmony_ci} 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cistatic void print_header_std(struct perf_stat_config *config, 128762306a36Sopenharmony_ci struct target *_target, struct evlist *evlist, 128862306a36Sopenharmony_ci int argc, const char **argv) 128962306a36Sopenharmony_ci{ 129062306a36Sopenharmony_ci FILE *output = config->output; 129162306a36Sopenharmony_ci int i; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci fprintf(output, "\n"); 129462306a36Sopenharmony_ci fprintf(output, " Performance counter stats for "); 129562306a36Sopenharmony_ci if (_target->bpf_str) 129662306a36Sopenharmony_ci fprintf(output, "\'BPF program(s) %s", _target->bpf_str); 129762306a36Sopenharmony_ci else if (_target->system_wide) 129862306a36Sopenharmony_ci fprintf(output, "\'system wide"); 129962306a36Sopenharmony_ci else if (_target->cpu_list) 130062306a36Sopenharmony_ci fprintf(output, "\'CPU(s) %s", _target->cpu_list); 130162306a36Sopenharmony_ci else if (!target__has_task(_target)) { 130262306a36Sopenharmony_ci fprintf(output, "\'%s", argv ? argv[0] : "pipe"); 130362306a36Sopenharmony_ci for (i = 1; argv && (i < argc); i++) 130462306a36Sopenharmony_ci fprintf(output, " %s", argv[i]); 130562306a36Sopenharmony_ci } else if (_target->pid) 130662306a36Sopenharmony_ci fprintf(output, "process id \'%s", _target->pid); 130762306a36Sopenharmony_ci else 130862306a36Sopenharmony_ci fprintf(output, "thread id \'%s", _target->tid); 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci fprintf(output, "\'"); 131162306a36Sopenharmony_ci if (config->run_count > 1) 131262306a36Sopenharmony_ci fprintf(output, " (%d runs)", config->run_count); 131362306a36Sopenharmony_ci fprintf(output, ":\n\n"); 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci if (config->metric_only) 131662306a36Sopenharmony_ci print_metric_headers(config, evlist, false); 131762306a36Sopenharmony_ci} 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_cistatic void print_header_csv(struct perf_stat_config *config, 132062306a36Sopenharmony_ci struct target *_target __maybe_unused, 132162306a36Sopenharmony_ci struct evlist *evlist, 132262306a36Sopenharmony_ci int argc __maybe_unused, 132362306a36Sopenharmony_ci const char **argv __maybe_unused) 132462306a36Sopenharmony_ci{ 132562306a36Sopenharmony_ci if (config->metric_only) 132662306a36Sopenharmony_ci print_metric_headers(config, evlist, true); 132762306a36Sopenharmony_ci} 132862306a36Sopenharmony_cistatic void print_header_json(struct perf_stat_config *config, 132962306a36Sopenharmony_ci struct target *_target __maybe_unused, 133062306a36Sopenharmony_ci struct evlist *evlist, 133162306a36Sopenharmony_ci int argc __maybe_unused, 133262306a36Sopenharmony_ci const char **argv __maybe_unused) 133362306a36Sopenharmony_ci{ 133462306a36Sopenharmony_ci if (config->metric_only) 133562306a36Sopenharmony_ci print_metric_headers(config, evlist, true); 133662306a36Sopenharmony_ci} 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_cistatic void print_header(struct perf_stat_config *config, 133962306a36Sopenharmony_ci struct target *_target, 134062306a36Sopenharmony_ci struct evlist *evlist, 134162306a36Sopenharmony_ci int argc, const char **argv) 134262306a36Sopenharmony_ci{ 134362306a36Sopenharmony_ci static int num_print_iv; 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci fflush(stdout); 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci if (config->interval_clear) 134862306a36Sopenharmony_ci puts(CONSOLE_CLEAR); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci if (num_print_iv == 0 || config->interval_clear) { 135162306a36Sopenharmony_ci if (config->json_output) 135262306a36Sopenharmony_ci print_header_json(config, _target, evlist, argc, argv); 135362306a36Sopenharmony_ci else if (config->csv_output) 135462306a36Sopenharmony_ci print_header_csv(config, _target, evlist, argc, argv); 135562306a36Sopenharmony_ci else if (config->interval) 135662306a36Sopenharmony_ci print_header_interval_std(config, _target, evlist, argc, argv); 135762306a36Sopenharmony_ci else 135862306a36Sopenharmony_ci print_header_std(config, _target, evlist, argc, argv); 135962306a36Sopenharmony_ci } 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci if (num_print_iv++ == 25) 136262306a36Sopenharmony_ci num_print_iv = 0; 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_cistatic int get_precision(double num) 136662306a36Sopenharmony_ci{ 136762306a36Sopenharmony_ci if (num > 1) 136862306a36Sopenharmony_ci return 0; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci return lround(ceil(-log10(num))); 137162306a36Sopenharmony_ci} 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_cistatic void print_table(struct perf_stat_config *config, 137462306a36Sopenharmony_ci FILE *output, int precision, double avg) 137562306a36Sopenharmony_ci{ 137662306a36Sopenharmony_ci char tmp[64]; 137762306a36Sopenharmony_ci int idx, indent = 0; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci scnprintf(tmp, 64, " %17.*f", precision, avg); 138062306a36Sopenharmony_ci while (tmp[indent] == ' ') 138162306a36Sopenharmony_ci indent++; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci fprintf(output, "%*s# Table of individual measurements:\n", indent, ""); 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci for (idx = 0; idx < config->run_count; idx++) { 138662306a36Sopenharmony_ci double run = (double) config->walltime_run[idx] / NSEC_PER_SEC; 138762306a36Sopenharmony_ci int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5); 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci fprintf(output, " %17.*f (%+.*f) ", 139062306a36Sopenharmony_ci precision, run, precision, run - avg); 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci for (h = 0; h < n; h++) 139362306a36Sopenharmony_ci fprintf(output, "#"); 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci fprintf(output, "\n"); 139662306a36Sopenharmony_ci } 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci fprintf(output, "\n%*s# Final result:\n", indent, ""); 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic double timeval2double(struct timeval *t) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC; 140462306a36Sopenharmony_ci} 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_cistatic void print_footer(struct perf_stat_config *config) 140762306a36Sopenharmony_ci{ 140862306a36Sopenharmony_ci double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; 140962306a36Sopenharmony_ci FILE *output = config->output; 141062306a36Sopenharmony_ci 141162306a36Sopenharmony_ci if (config->interval || config->csv_output || config->json_output) 141262306a36Sopenharmony_ci return; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci if (!config->null_run) 141562306a36Sopenharmony_ci fprintf(output, "\n"); 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci if (config->run_count == 1) { 141862306a36Sopenharmony_ci fprintf(output, " %17.9f seconds time elapsed", avg); 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci if (config->ru_display) { 142162306a36Sopenharmony_ci double ru_utime = timeval2double(&config->ru_data.ru_utime); 142262306a36Sopenharmony_ci double ru_stime = timeval2double(&config->ru_data.ru_stime); 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci fprintf(output, "\n\n"); 142562306a36Sopenharmony_ci fprintf(output, " %17.9f seconds user\n", ru_utime); 142662306a36Sopenharmony_ci fprintf(output, " %17.9f seconds sys\n", ru_stime); 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci } else { 142962306a36Sopenharmony_ci double sd = stddev_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC; 143062306a36Sopenharmony_ci /* 143162306a36Sopenharmony_ci * Display at most 2 more significant 143262306a36Sopenharmony_ci * digits than the stddev inaccuracy. 143362306a36Sopenharmony_ci */ 143462306a36Sopenharmony_ci int precision = get_precision(sd) + 2; 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_ci if (config->walltime_run_table) 143762306a36Sopenharmony_ci print_table(config, output, precision, avg); 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci fprintf(output, " %17.*f +- %.*f seconds time elapsed", 144062306a36Sopenharmony_ci precision, avg, precision, sd); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci print_noise_pct(config, sd, avg, /*before_metric=*/false); 144362306a36Sopenharmony_ci } 144462306a36Sopenharmony_ci fprintf(output, "\n\n"); 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci if (config->print_free_counters_hint && sysctl__nmi_watchdog_enabled()) 144762306a36Sopenharmony_ci fprintf(output, 144862306a36Sopenharmony_ci"Some events weren't counted. Try disabling the NMI watchdog:\n" 144962306a36Sopenharmony_ci" echo 0 > /proc/sys/kernel/nmi_watchdog\n" 145062306a36Sopenharmony_ci" perf stat ...\n" 145162306a36Sopenharmony_ci" echo 1 > /proc/sys/kernel/nmi_watchdog\n"); 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci if (config->print_mixed_hw_group_error) 145462306a36Sopenharmony_ci fprintf(output, 145562306a36Sopenharmony_ci "The events in group usually have to be from " 145662306a36Sopenharmony_ci "the same PMU. Try reorganizing the group.\n"); 145762306a36Sopenharmony_ci} 145862306a36Sopenharmony_ci 145962306a36Sopenharmony_cistatic void print_percore(struct perf_stat_config *config, 146062306a36Sopenharmony_ci struct evsel *counter, struct outstate *os) 146162306a36Sopenharmony_ci{ 146262306a36Sopenharmony_ci bool metric_only = config->metric_only; 146362306a36Sopenharmony_ci FILE *output = config->output; 146462306a36Sopenharmony_ci struct cpu_aggr_map *core_map; 146562306a36Sopenharmony_ci int aggr_idx, core_map_len = 0; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci if (!config->aggr_map || !config->aggr_get_id) 146862306a36Sopenharmony_ci return; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci if (config->percore_show_thread) 147162306a36Sopenharmony_ci return print_counter(config, counter, os); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci /* 147462306a36Sopenharmony_ci * core_map will hold the aggr_cpu_id for the cores that have been 147562306a36Sopenharmony_ci * printed so that each core is printed just once. 147662306a36Sopenharmony_ci */ 147762306a36Sopenharmony_ci core_map = cpu_aggr_map__empty_new(config->aggr_map->nr); 147862306a36Sopenharmony_ci if (core_map == NULL) { 147962306a36Sopenharmony_ci fprintf(output, "Cannot allocate per-core aggr map for display\n"); 148062306a36Sopenharmony_ci return; 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci cpu_aggr_map__for_each_idx(aggr_idx, config->aggr_map) { 148462306a36Sopenharmony_ci struct perf_cpu curr_cpu = config->aggr_map->map[aggr_idx].cpu; 148562306a36Sopenharmony_ci struct aggr_cpu_id core_id = aggr_cpu_id__core(curr_cpu, NULL); 148662306a36Sopenharmony_ci bool found = false; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci for (int i = 0; i < core_map_len; i++) { 148962306a36Sopenharmony_ci if (aggr_cpu_id__equal(&core_map->map[i], &core_id)) { 149062306a36Sopenharmony_ci found = true; 149162306a36Sopenharmony_ci break; 149262306a36Sopenharmony_ci } 149362306a36Sopenharmony_ci } 149462306a36Sopenharmony_ci if (found) 149562306a36Sopenharmony_ci continue; 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci print_counter_aggrdata(config, counter, aggr_idx, os); 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci core_map->map[core_map_len++] = core_id; 150062306a36Sopenharmony_ci } 150162306a36Sopenharmony_ci free(core_map); 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci if (metric_only) 150462306a36Sopenharmony_ci fputc('\n', output); 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_cistatic void print_cgroup_counter(struct perf_stat_config *config, struct evlist *evlist, 150862306a36Sopenharmony_ci struct outstate *os) 150962306a36Sopenharmony_ci{ 151062306a36Sopenharmony_ci struct evsel *counter; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 151362306a36Sopenharmony_ci if (os->cgrp != counter->cgrp) { 151462306a36Sopenharmony_ci if (os->cgrp != NULL) 151562306a36Sopenharmony_ci print_metric_end(config, os); 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci os->cgrp = counter->cgrp; 151862306a36Sopenharmony_ci print_metric_begin(config, evlist, os, /*aggr_idx=*/0); 151962306a36Sopenharmony_ci } 152062306a36Sopenharmony_ci 152162306a36Sopenharmony_ci print_counter(config, counter, os); 152262306a36Sopenharmony_ci } 152362306a36Sopenharmony_ci if (os->cgrp) 152462306a36Sopenharmony_ci print_metric_end(config, os); 152562306a36Sopenharmony_ci} 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_civoid evlist__print_counters(struct evlist *evlist, struct perf_stat_config *config, 152862306a36Sopenharmony_ci struct target *_target, struct timespec *ts, 152962306a36Sopenharmony_ci int argc, const char **argv) 153062306a36Sopenharmony_ci{ 153162306a36Sopenharmony_ci bool metric_only = config->metric_only; 153262306a36Sopenharmony_ci int interval = config->interval; 153362306a36Sopenharmony_ci struct evsel *counter; 153462306a36Sopenharmony_ci char buf[64]; 153562306a36Sopenharmony_ci struct outstate os = { 153662306a36Sopenharmony_ci .fh = config->output, 153762306a36Sopenharmony_ci .first = true, 153862306a36Sopenharmony_ci }; 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci if (config->iostat_run) 154162306a36Sopenharmony_ci evlist->selected = evlist__first(evlist); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci if (interval) { 154462306a36Sopenharmony_ci os.prefix = buf; 154562306a36Sopenharmony_ci prepare_interval(config, buf, sizeof(buf), ts); 154662306a36Sopenharmony_ci } 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci print_header(config, _target, evlist, argc, argv); 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci switch (config->aggr_mode) { 155162306a36Sopenharmony_ci case AGGR_CORE: 155262306a36Sopenharmony_ci case AGGR_CACHE: 155362306a36Sopenharmony_ci case AGGR_DIE: 155462306a36Sopenharmony_ci case AGGR_SOCKET: 155562306a36Sopenharmony_ci case AGGR_NODE: 155662306a36Sopenharmony_ci if (config->cgroup_list) 155762306a36Sopenharmony_ci print_aggr_cgroup(config, evlist, &os); 155862306a36Sopenharmony_ci else 155962306a36Sopenharmony_ci print_aggr(config, evlist, &os); 156062306a36Sopenharmony_ci break; 156162306a36Sopenharmony_ci case AGGR_THREAD: 156262306a36Sopenharmony_ci case AGGR_GLOBAL: 156362306a36Sopenharmony_ci if (config->iostat_run) { 156462306a36Sopenharmony_ci iostat_print_counters(evlist, config, ts, buf, 156562306a36Sopenharmony_ci (iostat_print_counter_t)print_counter, &os); 156662306a36Sopenharmony_ci } else if (config->cgroup_list) { 156762306a36Sopenharmony_ci print_cgroup_counter(config, evlist, &os); 156862306a36Sopenharmony_ci } else { 156962306a36Sopenharmony_ci print_metric_begin(config, evlist, &os, /*aggr_idx=*/0); 157062306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 157162306a36Sopenharmony_ci print_counter(config, counter, &os); 157262306a36Sopenharmony_ci } 157362306a36Sopenharmony_ci print_metric_end(config, &os); 157462306a36Sopenharmony_ci } 157562306a36Sopenharmony_ci break; 157662306a36Sopenharmony_ci case AGGR_NONE: 157762306a36Sopenharmony_ci if (metric_only) 157862306a36Sopenharmony_ci print_no_aggr_metric(config, evlist, &os); 157962306a36Sopenharmony_ci else { 158062306a36Sopenharmony_ci evlist__for_each_entry(evlist, counter) { 158162306a36Sopenharmony_ci if (counter->percore) 158262306a36Sopenharmony_ci print_percore(config, counter, &os); 158362306a36Sopenharmony_ci else 158462306a36Sopenharmony_ci print_counter(config, counter, &os); 158562306a36Sopenharmony_ci } 158662306a36Sopenharmony_ci } 158762306a36Sopenharmony_ci break; 158862306a36Sopenharmony_ci case AGGR_MAX: 158962306a36Sopenharmony_ci case AGGR_UNSET: 159062306a36Sopenharmony_ci default: 159162306a36Sopenharmony_ci break; 159262306a36Sopenharmony_ci } 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci print_footer(config); 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci fflush(config->output); 159762306a36Sopenharmony_ci} 1598