186470930SIngo Molnar /* 286470930SIngo Molnar * builtin-stat.c 386470930SIngo Molnar * 486470930SIngo Molnar * Builtin stat command: Give a precise performance counters summary 586470930SIngo Molnar * overview about any workload, CPU or specific PID. 686470930SIngo Molnar * 786470930SIngo Molnar * Sample output: 886470930SIngo Molnar 92cba3ffbSIngo Molnar $ perf stat ./hackbench 10 1086470930SIngo Molnar 112cba3ffbSIngo Molnar Time: 0.118 1286470930SIngo Molnar 132cba3ffbSIngo Molnar Performance counter stats for './hackbench 10': 1486470930SIngo Molnar 152cba3ffbSIngo Molnar 1708.761321 task-clock # 11.037 CPUs utilized 162cba3ffbSIngo Molnar 41,190 context-switches # 0.024 M/sec 172cba3ffbSIngo Molnar 6,735 CPU-migrations # 0.004 M/sec 182cba3ffbSIngo Molnar 17,318 page-faults # 0.010 M/sec 192cba3ffbSIngo Molnar 5,205,202,243 cycles # 3.046 GHz 202cba3ffbSIngo Molnar 3,856,436,920 stalled-cycles-frontend # 74.09% frontend cycles idle 212cba3ffbSIngo Molnar 1,600,790,871 stalled-cycles-backend # 30.75% backend cycles idle 222cba3ffbSIngo Molnar 2,603,501,247 instructions # 0.50 insns per cycle 232cba3ffbSIngo Molnar # 1.48 stalled cycles per insn 242cba3ffbSIngo Molnar 484,357,498 branches # 283.455 M/sec 252cba3ffbSIngo Molnar 6,388,934 branch-misses # 1.32% of all branches 262cba3ffbSIngo Molnar 272cba3ffbSIngo Molnar 0.154822978 seconds time elapsed 2886470930SIngo Molnar 2986470930SIngo Molnar * 302cba3ffbSIngo Molnar * Copyright (C) 2008-2011, Red Hat Inc, Ingo Molnar <mingo@redhat.com> 3186470930SIngo Molnar * 3286470930SIngo Molnar * Improvements and fixes by: 3386470930SIngo Molnar * 3486470930SIngo Molnar * Arjan van de Ven <arjan@linux.intel.com> 3586470930SIngo Molnar * Yanmin Zhang <yanmin.zhang@intel.com> 3686470930SIngo Molnar * Wu Fengguang <fengguang.wu@intel.com> 3786470930SIngo Molnar * Mike Galbraith <efault@gmx.de> 3886470930SIngo Molnar * Paul Mackerras <paulus@samba.org> 396e750a8fSJaswinder Singh Rajput * Jaswinder Singh Rajput <jaswinder@kernel.org> 4086470930SIngo Molnar * 4186470930SIngo Molnar * Released under the GPL v2. (and only v2, not any later version) 4286470930SIngo Molnar */ 4386470930SIngo Molnar 4486470930SIngo Molnar #include "perf.h" 4586470930SIngo Molnar #include "builtin.h" 46f14d5707SArnaldo Carvalho de Melo #include "util/cgroup.h" 4786470930SIngo Molnar #include "util/util.h" 484b6ab94eSJosh Poimboeuf #include <subcmd/parse-options.h> 4986470930SIngo Molnar #include "util/parse-events.h" 504cabc3d1SAndi Kleen #include "util/pmu.h" 518f28827aSFrederic Weisbecker #include "util/event.h" 52361c99a6SArnaldo Carvalho de Melo #include "util/evlist.h" 5369aad6f1SArnaldo Carvalho de Melo #include "util/evsel.h" 548f28827aSFrederic Weisbecker #include "util/debug.h" 555d8bb1ecSMathieu Poirier #include "util/drv_configs.h" 56a5d243d0SIngo Molnar #include "util/color.h" 570007eceaSXiao Guangrong #include "util/stat.h" 5860666c63SLiming Wang #include "util/header.h" 59a12b51c4SPaul Mackerras #include "util/cpumap.h" 60d6d901c2SZhang, Yanmin #include "util/thread.h" 61fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 62d809560bSJiri Olsa #include "util/counts.h" 6344b1e60aSAndi Kleen #include "util/group.h" 644979d0c7SJiri Olsa #include "util/session.h" 65ba6039b6SJiri Olsa #include "util/tool.h" 66a067558eSArnaldo Carvalho de Melo #include "util/string2.h" 67b18f3e36SAndi Kleen #include "util/metricgroup.h" 689660e08eSJiri Olsa #include "util/top.h" 69ba6039b6SJiri Olsa #include "asm/bug.h" 7086470930SIngo Molnar 71bd48c63eSArnaldo Carvalho de Melo #include <linux/time64.h> 7244b1e60aSAndi Kleen #include <api/fs/fs.h> 73a43783aeSArnaldo Carvalho de Melo #include <errno.h> 749607ad3aSArnaldo Carvalho de Melo #include <signal.h> 751f16c575SPeter Zijlstra #include <stdlib.h> 7686470930SIngo Molnar #include <sys/prctl.h> 77fd20e811SArnaldo Carvalho de Melo #include <inttypes.h> 785af52b51SStephane Eranian #include <locale.h> 79e3b03b6cSAndi Kleen #include <math.h> 807a8ef4c4SArnaldo Carvalho de Melo #include <sys/types.h> 817a8ef4c4SArnaldo Carvalho de Melo #include <sys/stat.h> 824208735dSArnaldo Carvalho de Melo #include <sys/wait.h> 837a8ef4c4SArnaldo Carvalho de Melo #include <unistd.h> 840ce2da14SJiri Olsa #include <sys/time.h> 850ce2da14SJiri Olsa #include <sys/resource.h> 860ce2da14SJiri Olsa #include <sys/wait.h> 8786470930SIngo Molnar 883d689ed6SArnaldo Carvalho de Melo #include "sane_ctype.h" 893d689ed6SArnaldo Carvalho de Melo 90d7470b6aSStephane Eranian #define DEFAULT_SEPARATOR " " 912cee77c4SDavid Ahern #define CNTR_NOT_SUPPORTED "<not supported>" 922cee77c4SDavid Ahern #define CNTR_NOT_COUNTED "<not counted>" 93daefd0bcSKan Liang #define FREEZE_ON_SMI_PATH "devices/cpu/freeze_on_smi" 94d7470b6aSStephane Eranian 95d4f63a47SJiri Olsa static void print_counters(struct timespec *ts, int argc, const char **argv); 9613370a9bSStephane Eranian 974cabc3d1SAndi Kleen /* Default events used for perf stat -T */ 98a454742cSJiri Olsa static const char *transaction_attrs = { 99a454742cSJiri Olsa "task-clock," 1004cabc3d1SAndi Kleen "{" 1014cabc3d1SAndi Kleen "instructions," 1024cabc3d1SAndi Kleen "cycles," 1034cabc3d1SAndi Kleen "cpu/cycles-t/," 1044cabc3d1SAndi Kleen "cpu/tx-start/," 1054cabc3d1SAndi Kleen "cpu/el-start/," 1064cabc3d1SAndi Kleen "cpu/cycles-ct/" 1074cabc3d1SAndi Kleen "}" 1084cabc3d1SAndi Kleen }; 1094cabc3d1SAndi Kleen 1104cabc3d1SAndi Kleen /* More limited version when the CPU does not have all events. */ 111a454742cSJiri Olsa static const char * transaction_limited_attrs = { 112a454742cSJiri Olsa "task-clock," 1134cabc3d1SAndi Kleen "{" 1144cabc3d1SAndi Kleen "instructions," 1154cabc3d1SAndi Kleen "cycles," 1164cabc3d1SAndi Kleen "cpu/cycles-t/," 1174cabc3d1SAndi Kleen "cpu/tx-start/" 1184cabc3d1SAndi Kleen "}" 1194cabc3d1SAndi Kleen }; 1204cabc3d1SAndi Kleen 12144b1e60aSAndi Kleen static const char * topdown_attrs[] = { 12244b1e60aSAndi Kleen "topdown-total-slots", 12344b1e60aSAndi Kleen "topdown-slots-retired", 12444b1e60aSAndi Kleen "topdown-recovery-bubbles", 12544b1e60aSAndi Kleen "topdown-fetch-bubbles", 12644b1e60aSAndi Kleen "topdown-slots-issued", 12744b1e60aSAndi Kleen NULL, 12844b1e60aSAndi Kleen }; 12944b1e60aSAndi Kleen 130daefd0bcSKan Liang static const char *smi_cost_attrs = { 131daefd0bcSKan Liang "{" 132daefd0bcSKan Liang "msr/aperf/," 133daefd0bcSKan Liang "msr/smi/," 134daefd0bcSKan Liang "cycles" 135daefd0bcSKan Liang "}" 136daefd0bcSKan Liang }; 137daefd0bcSKan Liang 138666e6d48SRobert Richter static struct perf_evlist *evsel_list; 139361c99a6SArnaldo Carvalho de Melo 140b18f3e36SAndi Kleen static struct rblist metric_events; 141b18f3e36SAndi Kleen 142602ad878SArnaldo Carvalho de Melo static struct target target = { 14377a6f014SNamhyung Kim .uid = UINT_MAX, 14477a6f014SNamhyung Kim }; 14542202dd5SIngo Molnar 1461e5a2931SJiri Olsa typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); 1471e5a2931SJiri Olsa 148c1a1f5d9SJiri Olsa #define METRIC_ONLY_LEN 20 149c1a1f5d9SJiri Olsa 1503d632595SJaswinder Singh Rajput static int run_count = 1; 151d07f0b12SStephane Eranian static volatile pid_t child_pid = -1; 152c0555642SIan Munsie static bool null_run = false; 1532cba3ffbSIngo Molnar static int detailed_run = 0; 1544cabc3d1SAndi Kleen static bool transaction_run; 15544b1e60aSAndi Kleen static bool topdown_run = false; 156daefd0bcSKan Liang static bool smi_cost = false; 157daefd0bcSKan Liang static bool smi_reset = false; 158201e0b06SArnaldo Carvalho de Melo static bool big_num = true; 159d7470b6aSStephane Eranian static int big_num_opt = -1; 160d7470b6aSStephane Eranian static const char *csv_sep = NULL; 161d7470b6aSStephane Eranian static bool csv_output = false; 16243bece79SLin Ming static bool group = false; 1631f16c575SPeter Zijlstra static const char *pre_cmd = NULL; 1641f16c575SPeter Zijlstra static const char *post_cmd = NULL; 1651f16c575SPeter Zijlstra static bool sync_run = false; 166410136f5SStephane Eranian static unsigned int unit_width = 4; /* strlen("unit") */ 167a7e191c3SFrederik Deweerdt static bool forever = false; 16854b50916SAndi Kleen static bool metric_only = false; 16944b1e60aSAndi Kleen static bool force_metric_only = false; 170430daf2dSAndi Kleen static bool no_merge = false; 171e55c14afSJiri Olsa static bool walltime_run_table = false; 17213370a9bSStephane Eranian static struct timespec ref_time; 17386ee6e18SStephane Eranian static struct cpu_map *aggr_map; 1741e5a2931SJiri Olsa static aggr_get_id_t aggr_get_id; 175e0547311SJiri Olsa static bool append_file; 176db06a269Syuzhoujian static bool interval_count; 1779660e08eSJiri Olsa static bool interval_clear; 178e0547311SJiri Olsa static const char *output_name; 179e0547311SJiri Olsa static int output_fd; 18002d492e5SBorislav Petkov static int print_free_counters_hint; 18130060eaeSKan Liang static int print_mixed_hw_group_error; 182e55c14afSJiri Olsa static u64 *walltime_run; 1830ce2da14SJiri Olsa static bool ru_display = false; 1840ce2da14SJiri Olsa static struct rusage ru_data; 185c1a1f5d9SJiri Olsa static unsigned int metric_only_len = METRIC_ONLY_LEN; 1865af52b51SStephane Eranian 1874979d0c7SJiri Olsa struct perf_stat { 1884979d0c7SJiri Olsa bool record; 1898ceb41d7SJiri Olsa struct perf_data data; 1904979d0c7SJiri Olsa struct perf_session *session; 1914979d0c7SJiri Olsa u64 bytes_written; 192ba6039b6SJiri Olsa struct perf_tool tool; 1931975d36eSJiri Olsa bool maps_allocated; 1941975d36eSJiri Olsa struct cpu_map *cpus; 1951975d36eSJiri Olsa struct thread_map *threads; 19689af4e05SJiri Olsa enum aggr_mode aggr_mode; 1974979d0c7SJiri Olsa }; 1984979d0c7SJiri Olsa 1994979d0c7SJiri Olsa static struct perf_stat perf_stat; 2004979d0c7SJiri Olsa #define STAT_RECORD perf_stat.record 2014979d0c7SJiri Olsa 20260666c63SLiming Wang static volatile int done = 0; 20360666c63SLiming Wang 204421a50f3SJiri Olsa static struct perf_stat_config stat_config = { 205421a50f3SJiri Olsa .aggr_mode = AGGR_GLOBAL, 206711a572eSJiri Olsa .scale = true, 207421a50f3SJiri Olsa }; 208421a50f3SJiri Olsa 209e864c5caSAndi Kleen static bool is_duration_time(struct perf_evsel *evsel) 210e864c5caSAndi Kleen { 211e864c5caSAndi Kleen return !strcmp(evsel->name, "duration_time"); 212e864c5caSAndi Kleen } 213e864c5caSAndi Kleen 21413370a9bSStephane Eranian static inline void diff_timespec(struct timespec *r, struct timespec *a, 21513370a9bSStephane Eranian struct timespec *b) 21613370a9bSStephane Eranian { 21713370a9bSStephane Eranian r->tv_sec = a->tv_sec - b->tv_sec; 21813370a9bSStephane Eranian if (a->tv_nsec < b->tv_nsec) { 219310ebb93SArnaldo Carvalho de Melo r->tv_nsec = a->tv_nsec + NSEC_PER_SEC - b->tv_nsec; 22013370a9bSStephane Eranian r->tv_sec--; 22113370a9bSStephane Eranian } else { 22213370a9bSStephane Eranian r->tv_nsec = a->tv_nsec - b->tv_nsec ; 22313370a9bSStephane Eranian } 22413370a9bSStephane Eranian } 22513370a9bSStephane Eranian 226254ecbc7SJiri Olsa static void perf_stat__reset_stats(void) 227254ecbc7SJiri Olsa { 22856739444SJin Yao int i; 22956739444SJin Yao 230254ecbc7SJiri Olsa perf_evlist__reset_stats(evsel_list); 231f87027b9SJiri Olsa perf_stat__reset_shadow_stats(); 23256739444SJin Yao 23356739444SJin Yao for (i = 0; i < stat_config.stats_num; i++) 23456739444SJin Yao perf_stat__reset_shadow_per_stat(&stat_config.stats[i]); 2351eda3b21SJiri Olsa } 2361eda3b21SJiri Olsa 2378b99b1a4SJiri Olsa static int process_synthesized_event(struct perf_tool *tool __maybe_unused, 2384979d0c7SJiri Olsa union perf_event *event, 2394979d0c7SJiri Olsa struct perf_sample *sample __maybe_unused, 2404979d0c7SJiri Olsa struct machine *machine __maybe_unused) 2414979d0c7SJiri Olsa { 2428ceb41d7SJiri Olsa if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) { 2438b99b1a4SJiri Olsa pr_err("failed to write perf data, error: %m\n"); 2448b99b1a4SJiri Olsa return -1; 2458b99b1a4SJiri Olsa } 2468b99b1a4SJiri Olsa 2478b99b1a4SJiri Olsa perf_stat.bytes_written += event->header.size; 2488b99b1a4SJiri Olsa return 0; 2494979d0c7SJiri Olsa } 2504979d0c7SJiri Olsa 2511975d36eSJiri Olsa static int write_stat_round_event(u64 tm, u64 type) 2527aad0c32SJiri Olsa { 2531975d36eSJiri Olsa return perf_event__synthesize_stat_round(NULL, tm, type, 2547aad0c32SJiri Olsa process_synthesized_event, 2557aad0c32SJiri Olsa NULL); 2567aad0c32SJiri Olsa } 2577aad0c32SJiri Olsa 2587aad0c32SJiri Olsa #define WRITE_STAT_ROUND_EVENT(time, interval) \ 2597aad0c32SJiri Olsa write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval) 2607aad0c32SJiri Olsa 2615a6ea81bSJiri Olsa #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 2625a6ea81bSJiri Olsa 2635a6ea81bSJiri Olsa static int 2645a6ea81bSJiri Olsa perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread, 2655a6ea81bSJiri Olsa struct perf_counts_values *count) 2665a6ea81bSJiri Olsa { 2675a6ea81bSJiri Olsa struct perf_sample_id *sid = SID(counter, cpu, thread); 2685a6ea81bSJiri Olsa 2695a6ea81bSJiri Olsa return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count, 2705a6ea81bSJiri Olsa process_synthesized_event, NULL); 2715a6ea81bSJiri Olsa } 2725a6ea81bSJiri Olsa 273f5b4a9c3SStephane Eranian /* 274f5b4a9c3SStephane Eranian * Read out the results of a single counter: 275f5b4a9c3SStephane Eranian * do not aggregate counts across CPUs in system-wide mode 276f5b4a9c3SStephane Eranian */ 277c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter) 278f5b4a9c3SStephane Eranian { 2799bf1a529SJiri Olsa int nthreads = thread_map__nr(evsel_list->threads); 28000e727bbSMark Rutland int ncpus, cpu, thread; 28100e727bbSMark Rutland 2821d9f8d1bSJin Yao if (target__has_cpu(&target) && !target__has_per_thread(&target)) 28300e727bbSMark Rutland ncpus = perf_evsel__nr_cpus(counter); 28400e727bbSMark Rutland else 28500e727bbSMark Rutland ncpus = 1; 286f5b4a9c3SStephane Eranian 2873b4331d9SSuzuki K. Poulose if (!counter->supported) 2883b4331d9SSuzuki K. Poulose return -ENOENT; 2893b4331d9SSuzuki K. Poulose 2909bf1a529SJiri Olsa if (counter->system_wide) 2919bf1a529SJiri Olsa nthreads = 1; 2929bf1a529SJiri Olsa 2939bf1a529SJiri Olsa for (thread = 0; thread < nthreads; thread++) { 2949bf1a529SJiri Olsa for (cpu = 0; cpu < ncpus; cpu++) { 2953b3eb044SJiri Olsa struct perf_counts_values *count; 2963b3eb044SJiri Olsa 2973b3eb044SJiri Olsa count = perf_counts(counter->counts, cpu, thread); 29882bf311eSJiri Olsa 29982bf311eSJiri Olsa /* 30082bf311eSJiri Olsa * The leader's group read loads data into its group members 30182bf311eSJiri Olsa * (via perf_evsel__read_counter) and sets threir count->loaded. 30282bf311eSJiri Olsa */ 30382bf311eSJiri Olsa if (!count->loaded && 30482bf311eSJiri Olsa perf_evsel__read_counter(counter, cpu, thread)) { 305db49a717SStephane Eranian counter->counts->scaled = -1; 306db49a717SStephane Eranian perf_counts(counter->counts, cpu, thread)->ena = 0; 307db49a717SStephane Eranian perf_counts(counter->counts, cpu, thread)->run = 0; 308c52b12edSArnaldo Carvalho de Melo return -1; 309db49a717SStephane Eranian } 3105a6ea81bSJiri Olsa 31182bf311eSJiri Olsa count->loaded = false; 31282bf311eSJiri Olsa 3135a6ea81bSJiri Olsa if (STAT_RECORD) { 3145a6ea81bSJiri Olsa if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { 3155a6ea81bSJiri Olsa pr_err("failed to write stat event\n"); 3165a6ea81bSJiri Olsa return -1; 3175a6ea81bSJiri Olsa } 3185a6ea81bSJiri Olsa } 3190b1abbf4SAndi Kleen 3200b1abbf4SAndi Kleen if (verbose > 1) { 3210b1abbf4SAndi Kleen fprintf(stat_config.output, 3220b1abbf4SAndi Kleen "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 3230b1abbf4SAndi Kleen perf_evsel__name(counter), 3240b1abbf4SAndi Kleen cpu, 3250b1abbf4SAndi Kleen count->val, count->ena, count->run); 3260b1abbf4SAndi Kleen } 327f5b4a9c3SStephane Eranian } 3289bf1a529SJiri Olsa } 329c52b12edSArnaldo Carvalho de Melo 330c52b12edSArnaldo Carvalho de Melo return 0; 33186470930SIngo Molnar } 33286470930SIngo Molnar 3333df33effSMark Rutland static void read_counters(void) 334106a94a0SJiri Olsa { 335106a94a0SJiri Olsa struct perf_evsel *counter; 336db49a717SStephane Eranian int ret; 337106a94a0SJiri Olsa 338e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 339db49a717SStephane Eranian ret = read_counter(counter); 340db49a717SStephane Eranian if (ret) 341245bad8eSAndi Kleen pr_debug("failed to read counter %s\n", counter->name); 3423b3eb044SJiri Olsa 343db49a717SStephane Eranian if (ret == 0 && perf_stat_process_counter(&stat_config, counter)) 3443b3eb044SJiri Olsa pr_warning("failed to process counter %s\n", counter->name); 345106a94a0SJiri Olsa } 346106a94a0SJiri Olsa } 347106a94a0SJiri Olsa 348ba411a95SJiri Olsa static void process_interval(void) 34913370a9bSStephane Eranian { 35013370a9bSStephane Eranian struct timespec ts, rs; 35113370a9bSStephane Eranian 3523df33effSMark Rutland read_counters(); 35386ee6e18SStephane Eranian 35413370a9bSStephane Eranian clock_gettime(CLOCK_MONOTONIC, &ts); 35513370a9bSStephane Eranian diff_timespec(&rs, &ts, &ref_time); 35613370a9bSStephane Eranian 3577aad0c32SJiri Olsa if (STAT_RECORD) { 358bd48c63eSArnaldo Carvalho de Melo if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL)) 3597aad0c32SJiri Olsa pr_err("failed to write stat round event\n"); 3607aad0c32SJiri Olsa } 3617aad0c32SJiri Olsa 362b90f1333SAndi Kleen init_stats(&walltime_nsecs_stats); 363b90f1333SAndi Kleen update_stats(&walltime_nsecs_stats, stat_config.interval * 1000000); 364d4f63a47SJiri Olsa print_counters(&rs, 0, NULL); 36513370a9bSStephane Eranian } 36613370a9bSStephane Eranian 36767ccdecdSJiri Olsa static void enable_counters(void) 36841191688SAndi Kleen { 369728c0ee0SJiri Olsa if (stat_config.initial_delay) 370728c0ee0SJiri Olsa usleep(stat_config.initial_delay * USEC_PER_MSEC); 37167ccdecdSJiri Olsa 37267ccdecdSJiri Olsa /* 37367ccdecdSJiri Olsa * We need to enable counters only if: 37467ccdecdSJiri Olsa * - we don't have tracee (attaching to task or cpu) 37567ccdecdSJiri Olsa * - we have initial delay configured 37667ccdecdSJiri Olsa */ 377728c0ee0SJiri Olsa if (!target__none(&target) || stat_config.initial_delay) 378ab46db0aSJiri Olsa perf_evlist__enable(evsel_list); 37941191688SAndi Kleen } 38041191688SAndi Kleen 3813df33effSMark Rutland static void disable_counters(void) 3823df33effSMark Rutland { 3833df33effSMark Rutland /* 3843df33effSMark Rutland * If we don't have tracee (attaching to task or cpu), counters may 3853df33effSMark Rutland * still be running. To get accurate group ratios, we must stop groups 3863df33effSMark Rutland * from counting before reading their constituent counters. 3873df33effSMark Rutland */ 3883df33effSMark Rutland if (!target__none(&target)) 3893df33effSMark Rutland perf_evlist__disable(evsel_list); 3903df33effSMark Rutland } 3913df33effSMark Rutland 392f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 3936af206fdSArnaldo Carvalho de Melo 3946af206fdSArnaldo Carvalho de Melo /* 3956af206fdSArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 3966af206fdSArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 3976af206fdSArnaldo Carvalho de Melo * want_signal to true. 3986af206fdSArnaldo Carvalho de Melo */ 399f33cbe72SArnaldo Carvalho de Melo static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, 400f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 4016af206fdSArnaldo Carvalho de Melo { 402f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 4036af206fdSArnaldo Carvalho de Melo } 4046af206fdSArnaldo Carvalho de Melo 40582bf311eSJiri Olsa static bool perf_evsel__should_store_id(struct perf_evsel *counter) 40682bf311eSJiri Olsa { 40782bf311eSJiri Olsa return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID; 40882bf311eSJiri Olsa } 40982bf311eSJiri Olsa 4105a5dfe4bSAndi Kleen static struct perf_evsel *perf_evsel__reset_weak_group(struct perf_evsel *evsel) 4115a5dfe4bSAndi Kleen { 4125a5dfe4bSAndi Kleen struct perf_evsel *c2, *leader; 4135a5dfe4bSAndi Kleen bool is_open = true; 4145a5dfe4bSAndi Kleen 4155a5dfe4bSAndi Kleen leader = evsel->leader; 4165a5dfe4bSAndi Kleen pr_debug("Weak group for %s/%d failed\n", 4175a5dfe4bSAndi Kleen leader->name, leader->nr_members); 4185a5dfe4bSAndi Kleen 4195a5dfe4bSAndi Kleen /* 4205a5dfe4bSAndi Kleen * for_each_group_member doesn't work here because it doesn't 4215a5dfe4bSAndi Kleen * include the first entry. 4225a5dfe4bSAndi Kleen */ 4235a5dfe4bSAndi Kleen evlist__for_each_entry(evsel_list, c2) { 4245a5dfe4bSAndi Kleen if (c2 == evsel) 4255a5dfe4bSAndi Kleen is_open = false; 4265a5dfe4bSAndi Kleen if (c2->leader == leader) { 4275a5dfe4bSAndi Kleen if (is_open) 4285a5dfe4bSAndi Kleen perf_evsel__close(c2); 4295a5dfe4bSAndi Kleen c2->leader = c2; 4305a5dfe4bSAndi Kleen c2->nr_members = 0; 4315a5dfe4bSAndi Kleen } 4325a5dfe4bSAndi Kleen } 4335a5dfe4bSAndi Kleen return leader; 4345a5dfe4bSAndi Kleen } 4355a5dfe4bSAndi Kleen 436e55c14afSJiri Olsa static int __run_perf_stat(int argc, const char **argv, int run_idx) 43786470930SIngo Molnar { 438ec0d3d1fSJiri Olsa int interval = stat_config.interval; 439db06a269Syuzhoujian int times = stat_config.times; 440f1f8ad52Syuzhoujian int timeout = stat_config.timeout; 441d6195a6aSArnaldo Carvalho de Melo char msg[BUFSIZ]; 44286470930SIngo Molnar unsigned long long t0, t1; 443cac21425SJiri Olsa struct perf_evsel *counter; 44413370a9bSStephane Eranian struct timespec ts; 445410136f5SStephane Eranian size_t l; 44642202dd5SIngo Molnar int status = 0; 4476be2850eSZhang, Yanmin const bool forks = (argc > 0); 4488ceb41d7SJiri Olsa bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false; 4495d8bb1ecSMathieu Poirier struct perf_evsel_config_term *err_term; 45086470930SIngo Molnar 45113370a9bSStephane Eranian if (interval) { 452310ebb93SArnaldo Carvalho de Melo ts.tv_sec = interval / USEC_PER_MSEC; 453310ebb93SArnaldo Carvalho de Melo ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC; 454f1f8ad52Syuzhoujian } else if (timeout) { 455f1f8ad52Syuzhoujian ts.tv_sec = timeout / USEC_PER_MSEC; 456f1f8ad52Syuzhoujian ts.tv_nsec = (timeout % USEC_PER_MSEC) * NSEC_PER_MSEC; 45713370a9bSStephane Eranian } else { 45813370a9bSStephane Eranian ts.tv_sec = 1; 45913370a9bSStephane Eranian ts.tv_nsec = 0; 46013370a9bSStephane Eranian } 46113370a9bSStephane Eranian 462acf28922SNamhyung Kim if (forks) { 463664c98d4SJiri Olsa if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe, 464735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal) < 0) { 465acf28922SNamhyung Kim perror("failed to prepare workload"); 466fceda7feSDavid Ahern return -1; 467051ae7f7SPaul Mackerras } 468d20a47e7SNamhyung Kim child_pid = evsel_list->workload.pid; 46960666c63SLiming Wang } 470051ae7f7SPaul Mackerras 4716a4bb04cSJiri Olsa if (group) 47263dab225SArnaldo Carvalho de Melo perf_evlist__set_leader(evsel_list); 4736a4bb04cSJiri Olsa 474e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 47542ef8a78SArnaldo Carvalho de Melo try_again: 476d09cefd2SJiri Olsa if (create_perf_stat_counter(counter, &stat_config, &target) < 0) { 4775a5dfe4bSAndi Kleen 4785a5dfe4bSAndi Kleen /* Weak group failed. Reset the group. */ 47935c1980eSAndi Kleen if ((errno == EINVAL || errno == EBADF) && 4805a5dfe4bSAndi Kleen counter->leader != counter && 4815a5dfe4bSAndi Kleen counter->weak_group) { 4825a5dfe4bSAndi Kleen counter = perf_evsel__reset_weak_group(counter); 4835a5dfe4bSAndi Kleen goto try_again; 4845a5dfe4bSAndi Kleen } 4855a5dfe4bSAndi Kleen 486979987a5SDavid Ahern /* 487979987a5SDavid Ahern * PPC returns ENXIO for HW counters until 2.6.37 488979987a5SDavid Ahern * (behavior changed with commit b0a873e). 489979987a5SDavid Ahern */ 49038f6ae1eSAnton Blanchard if (errno == EINVAL || errno == ENOSYS || 491979987a5SDavid Ahern errno == ENOENT || errno == EOPNOTSUPP || 492979987a5SDavid Ahern errno == ENXIO) { 493bb963e16SNamhyung Kim if (verbose > 0) 494c63ca0c0SDavid Ahern ui__warning("%s event is not supported by the kernel.\n", 4957289f83cSArnaldo Carvalho de Melo perf_evsel__name(counter)); 4962cee77c4SDavid Ahern counter->supported = false; 497cb5ef600SKan Liang 498cb5ef600SKan Liang if ((counter->leader != counter) || 499cb5ef600SKan Liang !(counter->leader->nr_members > 1)) 500ede70290SIngo Molnar continue; 50142ef8a78SArnaldo Carvalho de Melo } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { 502bb963e16SNamhyung Kim if (verbose > 0) 50342ef8a78SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 50442ef8a78SArnaldo Carvalho de Melo goto try_again; 505ab6c79b8SJin Yao } else if (target__has_per_thread(&target) && 506ab6c79b8SJin Yao evsel_list->threads && 507ab6c79b8SJin Yao evsel_list->threads->err_thread != -1) { 508ab6c79b8SJin Yao /* 509ab6c79b8SJin Yao * For global --per-thread case, skip current 510ab6c79b8SJin Yao * error thread. 511ab6c79b8SJin Yao */ 512ab6c79b8SJin Yao if (!thread_map__remove(evsel_list->threads, 513ab6c79b8SJin Yao evsel_list->threads->err_thread)) { 514ab6c79b8SJin Yao evsel_list->threads->err_thread = -1; 515ab6c79b8SJin Yao goto try_again; 516ab6c79b8SJin Yao } 517c63ca0c0SDavid Ahern } 518ede70290SIngo Molnar 51956e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(counter, &target, 52056e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 52156e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 52256e52e85SArnaldo Carvalho de Melo 523084ab9f8SArnaldo Carvalho de Melo if (child_pid != -1) 524084ab9f8SArnaldo Carvalho de Melo kill(child_pid, SIGTERM); 525fceda7feSDavid Ahern 526084ab9f8SArnaldo Carvalho de Melo return -1; 527084ab9f8SArnaldo Carvalho de Melo } 5282cee77c4SDavid Ahern counter->supported = true; 529410136f5SStephane Eranian 530410136f5SStephane Eranian l = strlen(counter->unit); 531410136f5SStephane Eranian if (l > unit_width) 532410136f5SStephane Eranian unit_width = l; 5332af4646dSJiri Olsa 53482bf311eSJiri Olsa if (perf_evsel__should_store_id(counter) && 535650d6220SJiri Olsa perf_evsel__store_ids(counter, evsel_list)) 5362af4646dSJiri Olsa return -1; 53748290609SArnaldo Carvalho de Melo } 53886470930SIngo Molnar 53923d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evsel_list, &counter)) { 54062d94b00SArnaldo Carvalho de Melo pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n", 54123d4aad4SArnaldo Carvalho de Melo counter->filter, perf_evsel__name(counter), errno, 542c8b5f2c9SArnaldo Carvalho de Melo str_error_r(errno, msg, sizeof(msg))); 543cfd748aeSFrederic Weisbecker return -1; 544cfd748aeSFrederic Weisbecker } 545cfd748aeSFrederic Weisbecker 5465d8bb1ecSMathieu Poirier if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) { 54762d94b00SArnaldo Carvalho de Melo pr_err("failed to set config \"%s\" on event %s with %d (%s)\n", 5485d8bb1ecSMathieu Poirier err_term->val.drv_cfg, perf_evsel__name(counter), errno, 5495d8bb1ecSMathieu Poirier str_error_r(errno, msg, sizeof(msg))); 5505d8bb1ecSMathieu Poirier return -1; 5515d8bb1ecSMathieu Poirier } 5525d8bb1ecSMathieu Poirier 5534979d0c7SJiri Olsa if (STAT_RECORD) { 5548ceb41d7SJiri Olsa int err, fd = perf_data__fd(&perf_stat.data); 5554979d0c7SJiri Olsa 556664c98d4SJiri Olsa if (is_pipe) { 5578ceb41d7SJiri Olsa err = perf_header__write_pipe(perf_data__fd(&perf_stat.data)); 558664c98d4SJiri Olsa } else { 5594979d0c7SJiri Olsa err = perf_session__write_header(perf_stat.session, evsel_list, 5604979d0c7SJiri Olsa fd, false); 561664c98d4SJiri Olsa } 562664c98d4SJiri Olsa 5634979d0c7SJiri Olsa if (err < 0) 5644979d0c7SJiri Olsa return err; 5658b99b1a4SJiri Olsa 5661c21e989SJiri Olsa err = perf_stat_synthesize_config(&stat_config, NULL, evsel_list, 567c2c247f2SJiri Olsa process_synthesized_event, is_pipe); 5688b99b1a4SJiri Olsa if (err < 0) 5698b99b1a4SJiri Olsa return err; 5704979d0c7SJiri Olsa } 5714979d0c7SJiri Olsa 57286470930SIngo Molnar /* 57386470930SIngo Molnar * Enable counters and exec the command: 57486470930SIngo Molnar */ 57586470930SIngo Molnar t0 = rdclock(); 57613370a9bSStephane Eranian clock_gettime(CLOCK_MONOTONIC, &ref_time); 57786470930SIngo Molnar 57860666c63SLiming Wang if (forks) { 579acf28922SNamhyung Kim perf_evlist__start_workload(evsel_list); 58067ccdecdSJiri Olsa enable_counters(); 581acf28922SNamhyung Kim 582f1f8ad52Syuzhoujian if (interval || timeout) { 58313370a9bSStephane Eranian while (!waitpid(child_pid, &status, WNOHANG)) { 58413370a9bSStephane Eranian nanosleep(&ts, NULL); 585f1f8ad52Syuzhoujian if (timeout) 586f1f8ad52Syuzhoujian break; 587ba411a95SJiri Olsa process_interval(); 588db06a269Syuzhoujian if (interval_count && !(--times)) 589db06a269Syuzhoujian break; 59013370a9bSStephane Eranian } 59113370a9bSStephane Eranian } 5920ce2da14SJiri Olsa wait4(child_pid, &status, 0, &ru_data); 5936af206fdSArnaldo Carvalho de Melo 594f33cbe72SArnaldo Carvalho de Melo if (workload_exec_errno) { 595c8b5f2c9SArnaldo Carvalho de Melo const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg)); 596f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 5976af206fdSArnaldo Carvalho de Melo return -1; 598f33cbe72SArnaldo Carvalho de Melo } 5996af206fdSArnaldo Carvalho de Melo 60033e49ea7SAndi Kleen if (WIFSIGNALED(status)) 60133e49ea7SAndi Kleen psignal(WTERMSIG(status), argv[0]); 60260666c63SLiming Wang } else { 60367ccdecdSJiri Olsa enable_counters(); 60413370a9bSStephane Eranian while (!done) { 60513370a9bSStephane Eranian nanosleep(&ts, NULL); 606f1f8ad52Syuzhoujian if (timeout) 607f1f8ad52Syuzhoujian break; 608db06a269Syuzhoujian if (interval) { 609ba411a95SJiri Olsa process_interval(); 610db06a269Syuzhoujian if (interval_count && !(--times)) 611db06a269Syuzhoujian break; 612db06a269Syuzhoujian } 61313370a9bSStephane Eranian } 61460666c63SLiming Wang } 61586470930SIngo Molnar 6163df33effSMark Rutland disable_counters(); 6173df33effSMark Rutland 61886470930SIngo Molnar t1 = rdclock(); 61986470930SIngo Molnar 620e55c14afSJiri Olsa if (walltime_run_table) 621e55c14afSJiri Olsa walltime_run[run_idx] = t1 - t0; 622e55c14afSJiri Olsa 6239e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 62442202dd5SIngo Molnar 6253df33effSMark Rutland /* 6263df33effSMark Rutland * Closing a group leader splits the group, and as we only disable 6273df33effSMark Rutland * group leaders, results in remaining events becoming enabled. To 6283df33effSMark Rutland * avoid arbitrary skew, we must read all counters before closing any 6293df33effSMark Rutland * group leaders. 6303df33effSMark Rutland */ 6313df33effSMark Rutland read_counters(); 6323df33effSMark Rutland perf_evlist__close(evsel_list); 633c52b12edSArnaldo Carvalho de Melo 63442202dd5SIngo Molnar return WEXITSTATUS(status); 63542202dd5SIngo Molnar } 63642202dd5SIngo Molnar 637e55c14afSJiri Olsa static int run_perf_stat(int argc, const char **argv, int run_idx) 6381f16c575SPeter Zijlstra { 6391f16c575SPeter Zijlstra int ret; 6401f16c575SPeter Zijlstra 6411f16c575SPeter Zijlstra if (pre_cmd) { 6421f16c575SPeter Zijlstra ret = system(pre_cmd); 6431f16c575SPeter Zijlstra if (ret) 6441f16c575SPeter Zijlstra return ret; 6451f16c575SPeter Zijlstra } 6461f16c575SPeter Zijlstra 6471f16c575SPeter Zijlstra if (sync_run) 6481f16c575SPeter Zijlstra sync(); 6491f16c575SPeter Zijlstra 650e55c14afSJiri Olsa ret = __run_perf_stat(argc, argv, run_idx); 6511f16c575SPeter Zijlstra if (ret) 6521f16c575SPeter Zijlstra return ret; 6531f16c575SPeter Zijlstra 6541f16c575SPeter Zijlstra if (post_cmd) { 6551f16c575SPeter Zijlstra ret = system(post_cmd); 6561f16c575SPeter Zijlstra if (ret) 6571f16c575SPeter Zijlstra return ret; 6581f16c575SPeter Zijlstra } 6591f16c575SPeter Zijlstra 6601f16c575SPeter Zijlstra return ret; 6611f16c575SPeter Zijlstra } 6621f16c575SPeter Zijlstra 663d73515c0SAndi Kleen static void print_running(u64 run, u64 ena) 664d73515c0SAndi Kleen { 665d73515c0SAndi Kleen if (csv_output) { 6665821522eSJiri Olsa fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f", 667d73515c0SAndi Kleen csv_sep, 668d73515c0SAndi Kleen run, 669d73515c0SAndi Kleen csv_sep, 670d73515c0SAndi Kleen ena ? 100.0 * run / ena : 100.0); 671d73515c0SAndi Kleen } else if (run != ena) { 6725821522eSJiri Olsa fprintf(stat_config.output, " (%.2f%%)", 100.0 * run / ena); 673d73515c0SAndi Kleen } 674d73515c0SAndi Kleen } 675d73515c0SAndi Kleen 676f99844cbSIngo Molnar static void print_noise_pct(double total, double avg) 677f99844cbSIngo Molnar { 6780007eceaSXiao Guangrong double pct = rel_stddev_stats(total, avg); 679f99844cbSIngo Molnar 6803ae9a34dSZhengyu He if (csv_output) 6815821522eSJiri Olsa fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct); 682a1bca6ccSJim Cromie else if (pct) 6835821522eSJiri Olsa fprintf(stat_config.output, " ( +-%6.2f%% )", pct); 684f99844cbSIngo Molnar } 685f99844cbSIngo Molnar 68669aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg) 68742202dd5SIngo Molnar { 688581cc8a2SJiri Olsa struct perf_stat_evsel *ps; 68969aad6f1SArnaldo Carvalho de Melo 690849abde9SPeter Zijlstra if (run_count == 1) 691849abde9SPeter Zijlstra return; 692849abde9SPeter Zijlstra 693e669e833SArnaldo Carvalho de Melo ps = evsel->stats; 694f99844cbSIngo Molnar print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 69542202dd5SIngo Molnar } 69642202dd5SIngo Molnar 69712c08a9fSStephane Eranian static void aggr_printout(struct perf_evsel *evsel, int id, int nr) 69842202dd5SIngo Molnar { 699421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 70012c08a9fSStephane Eranian case AGGR_CORE: 7015821522eSJiri Olsa fprintf(stat_config.output, "S%d-C%*d%s%*d%s", 70212c08a9fSStephane Eranian cpu_map__id_to_socket(id), 70312c08a9fSStephane Eranian csv_output ? 0 : -8, 70412c08a9fSStephane Eranian cpu_map__id_to_cpu(id), 70512c08a9fSStephane Eranian csv_sep, 70612c08a9fSStephane Eranian csv_output ? 0 : 4, 70712c08a9fSStephane Eranian nr, 70812c08a9fSStephane Eranian csv_sep); 70912c08a9fSStephane Eranian break; 71086ee6e18SStephane Eranian case AGGR_SOCKET: 7115821522eSJiri Olsa fprintf(stat_config.output, "S%*d%s%*d%s", 712d7e7a451SStephane Eranian csv_output ? 0 : -5, 71312c08a9fSStephane Eranian id, 714d7e7a451SStephane Eranian csv_sep, 715d7e7a451SStephane Eranian csv_output ? 0 : 4, 716d7e7a451SStephane Eranian nr, 717d7e7a451SStephane Eranian csv_sep); 71886ee6e18SStephane Eranian break; 71986ee6e18SStephane Eranian case AGGR_NONE: 7205821522eSJiri Olsa fprintf(stat_config.output, "CPU%*d%s", 721d7470b6aSStephane Eranian csv_output ? 0 : -4, 72212c08a9fSStephane Eranian perf_evsel__cpus(evsel)->map[id], csv_sep); 72386ee6e18SStephane Eranian break; 72432b8af82SJiri Olsa case AGGR_THREAD: 7255821522eSJiri Olsa fprintf(stat_config.output, "%*s-%*d%s", 72632b8af82SJiri Olsa csv_output ? 0 : 16, 72732b8af82SJiri Olsa thread_map__comm(evsel->threads, id), 72832b8af82SJiri Olsa csv_output ? 0 : -8, 72932b8af82SJiri Olsa thread_map__pid(evsel->threads, id), 73032b8af82SJiri Olsa csv_sep); 73132b8af82SJiri Olsa break; 73286ee6e18SStephane Eranian case AGGR_GLOBAL: 733208df99eSJiri Olsa case AGGR_UNSET: 73486ee6e18SStephane Eranian default: 73586ee6e18SStephane Eranian break; 73686ee6e18SStephane Eranian } 73786ee6e18SStephane Eranian } 738d7470b6aSStephane Eranian 739140aeadcSAndi Kleen struct outstate { 740140aeadcSAndi Kleen FILE *fh; 741140aeadcSAndi Kleen bool newline; 742f9483392SAndi Kleen const char *prefix; 74392a61f64SAndi Kleen int nfields; 74444d49a60SAndi Kleen int id, nr; 74544d49a60SAndi Kleen struct perf_evsel *evsel; 746140aeadcSAndi Kleen }; 747140aeadcSAndi Kleen 748140aeadcSAndi Kleen #define METRIC_LEN 35 749140aeadcSAndi Kleen 750140aeadcSAndi Kleen static void new_line_std(void *ctx) 751140aeadcSAndi Kleen { 752140aeadcSAndi Kleen struct outstate *os = ctx; 753140aeadcSAndi Kleen 754140aeadcSAndi Kleen os->newline = true; 755140aeadcSAndi Kleen } 756140aeadcSAndi Kleen 757140aeadcSAndi Kleen static void do_new_line_std(struct outstate *os) 758140aeadcSAndi Kleen { 759140aeadcSAndi Kleen fputc('\n', os->fh); 760f9483392SAndi Kleen fputs(os->prefix, os->fh); 76144d49a60SAndi Kleen aggr_printout(os->evsel, os->id, os->nr); 762140aeadcSAndi Kleen if (stat_config.aggr_mode == AGGR_NONE) 763140aeadcSAndi Kleen fprintf(os->fh, " "); 764140aeadcSAndi Kleen fprintf(os->fh, " "); 765140aeadcSAndi Kleen } 766140aeadcSAndi Kleen 767140aeadcSAndi Kleen static void print_metric_std(void *ctx, const char *color, const char *fmt, 768140aeadcSAndi Kleen const char *unit, double val) 769140aeadcSAndi Kleen { 770140aeadcSAndi Kleen struct outstate *os = ctx; 771140aeadcSAndi Kleen FILE *out = os->fh; 772140aeadcSAndi Kleen int n; 773140aeadcSAndi Kleen bool newline = os->newline; 774140aeadcSAndi Kleen 775140aeadcSAndi Kleen os->newline = false; 776140aeadcSAndi Kleen 777140aeadcSAndi Kleen if (unit == NULL || fmt == NULL) { 778140aeadcSAndi Kleen fprintf(out, "%-*s", METRIC_LEN, ""); 779140aeadcSAndi Kleen return; 780140aeadcSAndi Kleen } 781140aeadcSAndi Kleen 782140aeadcSAndi Kleen if (newline) 783140aeadcSAndi Kleen do_new_line_std(os); 784140aeadcSAndi Kleen 785140aeadcSAndi Kleen n = fprintf(out, " # "); 786140aeadcSAndi Kleen if (color) 787140aeadcSAndi Kleen n += color_fprintf(out, color, fmt, val); 788140aeadcSAndi Kleen else 789140aeadcSAndi Kleen n += fprintf(out, fmt, val); 790140aeadcSAndi Kleen fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); 791140aeadcSAndi Kleen } 792140aeadcSAndi Kleen 79392a61f64SAndi Kleen static void new_line_csv(void *ctx) 79492a61f64SAndi Kleen { 79592a61f64SAndi Kleen struct outstate *os = ctx; 79692a61f64SAndi Kleen int i; 79792a61f64SAndi Kleen 79892a61f64SAndi Kleen fputc('\n', os->fh); 79992a61f64SAndi Kleen if (os->prefix) 80092a61f64SAndi Kleen fprintf(os->fh, "%s%s", os->prefix, csv_sep); 80144d49a60SAndi Kleen aggr_printout(os->evsel, os->id, os->nr); 80292a61f64SAndi Kleen for (i = 0; i < os->nfields; i++) 80392a61f64SAndi Kleen fputs(csv_sep, os->fh); 80492a61f64SAndi Kleen } 80592a61f64SAndi Kleen 80692a61f64SAndi Kleen static void print_metric_csv(void *ctx, 80792a61f64SAndi Kleen const char *color __maybe_unused, 80892a61f64SAndi Kleen const char *fmt, const char *unit, double val) 80992a61f64SAndi Kleen { 81092a61f64SAndi Kleen struct outstate *os = ctx; 81192a61f64SAndi Kleen FILE *out = os->fh; 81292a61f64SAndi Kleen char buf[64], *vals, *ends; 81392a61f64SAndi Kleen 81492a61f64SAndi Kleen if (unit == NULL || fmt == NULL) { 81540c21898SIlya Pronin fprintf(out, "%s%s", csv_sep, csv_sep); 81692a61f64SAndi Kleen return; 81792a61f64SAndi Kleen } 81892a61f64SAndi Kleen snprintf(buf, sizeof(buf), fmt, val); 819b07c40dfSTaeung Song ends = vals = ltrim(buf); 82092a61f64SAndi Kleen while (isdigit(*ends) || *ends == '.') 82192a61f64SAndi Kleen ends++; 82292a61f64SAndi Kleen *ends = 0; 82392a61f64SAndi Kleen while (isspace(*unit)) 82492a61f64SAndi Kleen unit++; 82592a61f64SAndi Kleen fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit); 82692a61f64SAndi Kleen } 82792a61f64SAndi Kleen 82854b50916SAndi Kleen /* Filter out some columns that don't work well in metrics only mode */ 82954b50916SAndi Kleen 83054b50916SAndi Kleen static bool valid_only_metric(const char *unit) 83154b50916SAndi Kleen { 83254b50916SAndi Kleen if (!unit) 83354b50916SAndi Kleen return false; 83454b50916SAndi Kleen if (strstr(unit, "/sec") || 83554b50916SAndi Kleen strstr(unit, "hz") || 83654b50916SAndi Kleen strstr(unit, "Hz") || 83754b50916SAndi Kleen strstr(unit, "CPUs utilized")) 83854b50916SAndi Kleen return false; 83954b50916SAndi Kleen return true; 84054b50916SAndi Kleen } 84154b50916SAndi Kleen 84254b50916SAndi Kleen static const char *fixunit(char *buf, struct perf_evsel *evsel, 84354b50916SAndi Kleen const char *unit) 84454b50916SAndi Kleen { 84554b50916SAndi Kleen if (!strncmp(unit, "of all", 6)) { 84654b50916SAndi Kleen snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel), 84754b50916SAndi Kleen unit); 84854b50916SAndi Kleen return buf; 84954b50916SAndi Kleen } 85054b50916SAndi Kleen return unit; 85154b50916SAndi Kleen } 85254b50916SAndi Kleen 85354b50916SAndi Kleen static void print_metric_only(void *ctx, const char *color, const char *fmt, 85454b50916SAndi Kleen const char *unit, double val) 85554b50916SAndi Kleen { 85654b50916SAndi Kleen struct outstate *os = ctx; 85754b50916SAndi Kleen FILE *out = os->fh; 858f5155727SJiri Olsa char buf[1024], str[1024]; 859c1a1f5d9SJiri Olsa unsigned mlen = metric_only_len; 86054b50916SAndi Kleen 86154b50916SAndi Kleen if (!valid_only_metric(unit)) 86254b50916SAndi Kleen return; 86354b50916SAndi Kleen unit = fixunit(buf, os->evsel, unit); 86454b50916SAndi Kleen if (mlen < strlen(unit)) 86554b50916SAndi Kleen mlen = strlen(unit) + 1; 866f5155727SJiri Olsa 867f5155727SJiri Olsa if (color) 868f5155727SJiri Olsa mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1; 869f5155727SJiri Olsa 870f5155727SJiri Olsa color_snprintf(str, sizeof(str), color ?: "", fmt, val); 871f5155727SJiri Olsa fprintf(out, "%*s ", mlen, str); 87254b50916SAndi Kleen } 87354b50916SAndi Kleen 87454b50916SAndi Kleen static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, 87554b50916SAndi Kleen const char *fmt, 87654b50916SAndi Kleen const char *unit, double val) 87754b50916SAndi Kleen { 87854b50916SAndi Kleen struct outstate *os = ctx; 87954b50916SAndi Kleen FILE *out = os->fh; 88054b50916SAndi Kleen char buf[64], *vals, *ends; 88154b50916SAndi Kleen char tbuf[1024]; 88254b50916SAndi Kleen 88354b50916SAndi Kleen if (!valid_only_metric(unit)) 88454b50916SAndi Kleen return; 88554b50916SAndi Kleen unit = fixunit(tbuf, os->evsel, unit); 88654b50916SAndi Kleen snprintf(buf, sizeof buf, fmt, val); 887b07c40dfSTaeung Song ends = vals = ltrim(buf); 88854b50916SAndi Kleen while (isdigit(*ends) || *ends == '.') 88954b50916SAndi Kleen ends++; 89054b50916SAndi Kleen *ends = 0; 89154b50916SAndi Kleen fprintf(out, "%s%s", vals, csv_sep); 89254b50916SAndi Kleen } 89354b50916SAndi Kleen 89454b50916SAndi Kleen static void new_line_metric(void *ctx __maybe_unused) 89554b50916SAndi Kleen { 89654b50916SAndi Kleen } 89754b50916SAndi Kleen 89854b50916SAndi Kleen static void print_metric_header(void *ctx, const char *color __maybe_unused, 89954b50916SAndi Kleen const char *fmt __maybe_unused, 90054b50916SAndi Kleen const char *unit, double val __maybe_unused) 90154b50916SAndi Kleen { 90254b50916SAndi Kleen struct outstate *os = ctx; 90354b50916SAndi Kleen char tbuf[1024]; 90454b50916SAndi Kleen 90554b50916SAndi Kleen if (!valid_only_metric(unit)) 90654b50916SAndi Kleen return; 90754b50916SAndi Kleen unit = fixunit(tbuf, os->evsel, unit); 90854b50916SAndi Kleen if (csv_output) 90954b50916SAndi Kleen fprintf(os->fh, "%s%s", unit, csv_sep); 91054b50916SAndi Kleen else 911c1a1f5d9SJiri Olsa fprintf(os->fh, "%*s ", metric_only_len, unit); 91254b50916SAndi Kleen } 91354b50916SAndi Kleen 91444d49a60SAndi Kleen static int first_shadow_cpu(struct perf_evsel *evsel, int id) 91544d49a60SAndi Kleen { 91644d49a60SAndi Kleen int i; 91744d49a60SAndi Kleen 91844d49a60SAndi Kleen if (!aggr_get_id) 91944d49a60SAndi Kleen return 0; 92044d49a60SAndi Kleen 92144d49a60SAndi Kleen if (stat_config.aggr_mode == AGGR_NONE) 92244d49a60SAndi Kleen return id; 92344d49a60SAndi Kleen 92444d49a60SAndi Kleen if (stat_config.aggr_mode == AGGR_GLOBAL) 92544d49a60SAndi Kleen return 0; 92644d49a60SAndi Kleen 92744d49a60SAndi Kleen for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { 92844d49a60SAndi Kleen int cpu2 = perf_evsel__cpus(evsel)->map[i]; 92944d49a60SAndi Kleen 93044d49a60SAndi Kleen if (aggr_get_id(evsel_list->cpus, cpu2) == id) 93144d49a60SAndi Kleen return cpu2; 93244d49a60SAndi Kleen } 93344d49a60SAndi Kleen return 0; 93444d49a60SAndi Kleen } 93544d49a60SAndi Kleen 936556b1fb7SJiri Olsa static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) 937556b1fb7SJiri Olsa { 9385821522eSJiri Olsa FILE *output = stat_config.output; 939556b1fb7SJiri Olsa double sc = evsel->scale; 940556b1fb7SJiri Olsa const char *fmt; 941556b1fb7SJiri Olsa 942556b1fb7SJiri Olsa if (csv_output) { 943e3b03b6cSAndi Kleen fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; 944556b1fb7SJiri Olsa } else { 945556b1fb7SJiri Olsa if (big_num) 946e3b03b6cSAndi Kleen fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s"; 947556b1fb7SJiri Olsa else 948e3b03b6cSAndi Kleen fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; 949556b1fb7SJiri Olsa } 950556b1fb7SJiri Olsa 951556b1fb7SJiri Olsa aggr_printout(evsel, id, nr); 952556b1fb7SJiri Olsa 953556b1fb7SJiri Olsa fprintf(output, fmt, avg, csv_sep); 954556b1fb7SJiri Olsa 955556b1fb7SJiri Olsa if (evsel->unit) 956556b1fb7SJiri Olsa fprintf(output, "%-*s%s", 957556b1fb7SJiri Olsa csv_output ? 0 : unit_width, 958556b1fb7SJiri Olsa evsel->unit, csv_sep); 959556b1fb7SJiri Olsa 960556b1fb7SJiri Olsa fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel)); 961556b1fb7SJiri Olsa 962556b1fb7SJiri Olsa if (evsel->cgrp) 963556b1fb7SJiri Olsa fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 964eedfcb4bSAndi Kleen } 965556b1fb7SJiri Olsa 96630060eaeSKan Liang static bool is_mixed_hw_group(struct perf_evsel *counter) 96730060eaeSKan Liang { 96830060eaeSKan Liang struct perf_evlist *evlist = counter->evlist; 96930060eaeSKan Liang u32 pmu_type = counter->attr.type; 97030060eaeSKan Liang struct perf_evsel *pos; 97130060eaeSKan Liang 97230060eaeSKan Liang if (counter->nr_members < 2) 97330060eaeSKan Liang return false; 97430060eaeSKan Liang 97530060eaeSKan Liang evlist__for_each_entry(evlist, pos) { 97630060eaeSKan Liang /* software events can be part of any hardware group */ 97730060eaeSKan Liang if (pos->attr.type == PERF_TYPE_SOFTWARE) 97830060eaeSKan Liang continue; 97930060eaeSKan Liang if (pmu_type == PERF_TYPE_SOFTWARE) { 98030060eaeSKan Liang pmu_type = pos->attr.type; 98130060eaeSKan Liang continue; 98230060eaeSKan Liang } 98330060eaeSKan Liang if (pmu_type != pos->attr.type) 98430060eaeSKan Liang return true; 98530060eaeSKan Liang } 98630060eaeSKan Liang 98730060eaeSKan Liang return false; 98830060eaeSKan Liang } 98930060eaeSKan Liang 990f9483392SAndi Kleen static void printout(int id, int nr, struct perf_evsel *counter, double uval, 991e0128b30SJin Yao char *prefix, u64 run, u64 ena, double noise, 992e0128b30SJin Yao struct runtime_stat *st) 993eedfcb4bSAndi Kleen { 994140aeadcSAndi Kleen struct perf_stat_output_ctx out; 995f9483392SAndi Kleen struct outstate os = { 996f9483392SAndi Kleen .fh = stat_config.output, 99744d49a60SAndi Kleen .prefix = prefix ? prefix : "", 99844d49a60SAndi Kleen .id = id, 99944d49a60SAndi Kleen .nr = nr, 100044d49a60SAndi Kleen .evsel = counter, 1001f9483392SAndi Kleen }; 1002140aeadcSAndi Kleen print_metric_t pm = print_metric_std; 1003140aeadcSAndi Kleen void (*nl)(void *); 1004556b1fb7SJiri Olsa 100554b50916SAndi Kleen if (metric_only) { 100654b50916SAndi Kleen nl = new_line_metric; 100754b50916SAndi Kleen if (csv_output) 100854b50916SAndi Kleen pm = print_metric_only_csv; 100954b50916SAndi Kleen else 101054b50916SAndi Kleen pm = print_metric_only; 101154b50916SAndi Kleen } else 1012140aeadcSAndi Kleen nl = new_line_std; 1013eedfcb4bSAndi Kleen 101454b50916SAndi Kleen if (csv_output && !metric_only) { 101592a61f64SAndi Kleen static int aggr_fields[] = { 101692a61f64SAndi Kleen [AGGR_GLOBAL] = 0, 101792a61f64SAndi Kleen [AGGR_THREAD] = 1, 101892a61f64SAndi Kleen [AGGR_NONE] = 1, 101992a61f64SAndi Kleen [AGGR_SOCKET] = 2, 102092a61f64SAndi Kleen [AGGR_CORE] = 2, 102192a61f64SAndi Kleen }; 102292a61f64SAndi Kleen 102392a61f64SAndi Kleen pm = print_metric_csv; 102492a61f64SAndi Kleen nl = new_line_csv; 102592a61f64SAndi Kleen os.nfields = 3; 102692a61f64SAndi Kleen os.nfields += aggr_fields[stat_config.aggr_mode]; 102792a61f64SAndi Kleen if (counter->cgrp) 102892a61f64SAndi Kleen os.nfields++; 102992a61f64SAndi Kleen } 1030b002f3bbSAndi Kleen if (run == 0 || ena == 0 || counter->counts->scaled == -1) { 103154b50916SAndi Kleen if (metric_only) { 103254b50916SAndi Kleen pm(&os, NULL, "", "", 0); 103354b50916SAndi Kleen return; 103454b50916SAndi Kleen } 1035cb110f47SAndi Kleen aggr_printout(counter, id, nr); 1036cb110f47SAndi Kleen 1037cb110f47SAndi Kleen fprintf(stat_config.output, "%*s%s", 1038cb110f47SAndi Kleen csv_output ? 0 : 18, 1039cb110f47SAndi Kleen counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1040cb110f47SAndi Kleen csv_sep); 1041cb110f47SAndi Kleen 104230060eaeSKan Liang if (counter->supported) { 104302d492e5SBorislav Petkov print_free_counters_hint = 1; 104430060eaeSKan Liang if (is_mixed_hw_group(counter)) 104530060eaeSKan Liang print_mixed_hw_group_error = 1; 104630060eaeSKan Liang } 104702d492e5SBorislav Petkov 1048cb110f47SAndi Kleen fprintf(stat_config.output, "%-*s%s", 1049cb110f47SAndi Kleen csv_output ? 0 : unit_width, 1050cb110f47SAndi Kleen counter->unit, csv_sep); 1051cb110f47SAndi Kleen 1052cb110f47SAndi Kleen fprintf(stat_config.output, "%*s", 1053cb110f47SAndi Kleen csv_output ? 0 : -25, 1054cb110f47SAndi Kleen perf_evsel__name(counter)); 1055cb110f47SAndi Kleen 1056cb110f47SAndi Kleen if (counter->cgrp) 1057cb110f47SAndi Kleen fprintf(stat_config.output, "%s%s", 1058cb110f47SAndi Kleen csv_sep, counter->cgrp->name); 1059cb110f47SAndi Kleen 106092a61f64SAndi Kleen if (!csv_output) 106192a61f64SAndi Kleen pm(&os, NULL, NULL, "", 0); 106292a61f64SAndi Kleen print_noise(counter, noise); 1063cb110f47SAndi Kleen print_running(run, ena); 106492a61f64SAndi Kleen if (csv_output) 106592a61f64SAndi Kleen pm(&os, NULL, NULL, "", 0); 1066cb110f47SAndi Kleen return; 1067cb110f47SAndi Kleen } 1068cb110f47SAndi Kleen 10690aa802a7SJiri Olsa if (!metric_only) 1070eedfcb4bSAndi Kleen abs_printout(id, nr, counter, uval); 1071eedfcb4bSAndi Kleen 1072140aeadcSAndi Kleen out.print_metric = pm; 1073140aeadcSAndi Kleen out.new_line = nl; 1074140aeadcSAndi Kleen out.ctx = &os; 107537932c18SAndi Kleen out.force_header = false; 1076140aeadcSAndi Kleen 107754b50916SAndi Kleen if (csv_output && !metric_only) { 107892a61f64SAndi Kleen print_noise(counter, noise); 107992a61f64SAndi Kleen print_running(run, ena); 108092a61f64SAndi Kleen } 108192a61f64SAndi Kleen 1082140aeadcSAndi Kleen perf_stat__print_shadow_stats(counter, uval, 108344d49a60SAndi Kleen first_shadow_cpu(counter, id), 1084e0128b30SJin Yao &out, &metric_events, st); 108554b50916SAndi Kleen if (!csv_output && !metric_only) { 1086cb110f47SAndi Kleen print_noise(counter, noise); 1087cb110f47SAndi Kleen print_running(run, ena); 1088556b1fb7SJiri Olsa } 108992a61f64SAndi Kleen } 1090556b1fb7SJiri Olsa 109144d49a60SAndi Kleen static void aggr_update_shadow(void) 109244d49a60SAndi Kleen { 109344d49a60SAndi Kleen int cpu, s2, id, s; 109444d49a60SAndi Kleen u64 val; 109544d49a60SAndi Kleen struct perf_evsel *counter; 109644d49a60SAndi Kleen 109744d49a60SAndi Kleen for (s = 0; s < aggr_map->nr; s++) { 109844d49a60SAndi Kleen id = aggr_map->map[s]; 1099e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 110044d49a60SAndi Kleen val = 0; 110144d49a60SAndi Kleen for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 110244d49a60SAndi Kleen s2 = aggr_get_id(evsel_list->cpus, cpu); 110344d49a60SAndi Kleen if (s2 != id) 110444d49a60SAndi Kleen continue; 110544d49a60SAndi Kleen val += perf_counts(counter->counts, cpu, 0)->val; 110644d49a60SAndi Kleen } 110754830dd0SJiri Olsa perf_stat__update_shadow_stats(counter, val, 11081fcd0394SJin Yao first_shadow_cpu(counter, id), 11091fcd0394SJin Yao &rt_stat); 111044d49a60SAndi Kleen } 111144d49a60SAndi Kleen } 111244d49a60SAndi Kleen } 111344d49a60SAndi Kleen 11148c5421c0SAgustin Vega-Frias static void uniquify_event_name(struct perf_evsel *counter) 11158c5421c0SAgustin Vega-Frias { 11168c5421c0SAgustin Vega-Frias char *new_name; 11178c5421c0SAgustin Vega-Frias char *config; 11188c5421c0SAgustin Vega-Frias 111980ee8c58SKan Liang if (counter->uniquified_name || 112080ee8c58SKan Liang !counter->pmu_name || !strncmp(counter->name, counter->pmu_name, 11218c5421c0SAgustin Vega-Frias strlen(counter->pmu_name))) 11228c5421c0SAgustin Vega-Frias return; 11238c5421c0SAgustin Vega-Frias 11248c5421c0SAgustin Vega-Frias config = strchr(counter->name, '/'); 11258c5421c0SAgustin Vega-Frias if (config) { 11268c5421c0SAgustin Vega-Frias if (asprintf(&new_name, 11278c5421c0SAgustin Vega-Frias "%s%s", counter->pmu_name, config) > 0) { 11288c5421c0SAgustin Vega-Frias free(counter->name); 11298c5421c0SAgustin Vega-Frias counter->name = new_name; 11308c5421c0SAgustin Vega-Frias } 11318c5421c0SAgustin Vega-Frias } else { 11328c5421c0SAgustin Vega-Frias if (asprintf(&new_name, 11338c5421c0SAgustin Vega-Frias "%s [%s]", counter->name, counter->pmu_name) > 0) { 11348c5421c0SAgustin Vega-Frias free(counter->name); 11358c5421c0SAgustin Vega-Frias counter->name = new_name; 11368c5421c0SAgustin Vega-Frias } 11378c5421c0SAgustin Vega-Frias } 113880ee8c58SKan Liang 113980ee8c58SKan Liang counter->uniquified_name = true; 11408c5421c0SAgustin Vega-Frias } 11418c5421c0SAgustin Vega-Frias 1142430daf2dSAndi Kleen static void collect_all_aliases(struct perf_evsel *counter, 1143fbe51fbaSAndi Kleen void (*cb)(struct perf_evsel *counter, void *data, 1144fbe51fbaSAndi Kleen bool first), 1145fbe51fbaSAndi Kleen void *data) 1146fbe51fbaSAndi Kleen { 1147430daf2dSAndi Kleen struct perf_evsel *alias; 1148430daf2dSAndi Kleen 1149430daf2dSAndi Kleen alias = list_prepare_entry(counter, &(evsel_list->entries), node); 1150430daf2dSAndi Kleen list_for_each_entry_continue (alias, &evsel_list->entries, node) { 1151430daf2dSAndi Kleen if (strcmp(perf_evsel__name(alias), perf_evsel__name(counter)) || 1152430daf2dSAndi Kleen alias->scale != counter->scale || 1153430daf2dSAndi Kleen alias->cgrp != counter->cgrp || 1154430daf2dSAndi Kleen strcmp(alias->unit, counter->unit) || 11550aa802a7SJiri Olsa perf_evsel__is_clock(alias) != perf_evsel__is_clock(counter)) 1156430daf2dSAndi Kleen break; 1157430daf2dSAndi Kleen alias->merged_stat = true; 1158430daf2dSAndi Kleen cb(alias, data, false); 1159430daf2dSAndi Kleen } 1160430daf2dSAndi Kleen } 1161430daf2dSAndi Kleen 1162430daf2dSAndi Kleen static bool collect_data(struct perf_evsel *counter, 1163430daf2dSAndi Kleen void (*cb)(struct perf_evsel *counter, void *data, 1164430daf2dSAndi Kleen bool first), 1165430daf2dSAndi Kleen void *data) 1166430daf2dSAndi Kleen { 1167430daf2dSAndi Kleen if (counter->merged_stat) 1168430daf2dSAndi Kleen return false; 1169fbe51fbaSAndi Kleen cb(counter, data, true); 11708c5421c0SAgustin Vega-Frias if (no_merge) 11718c5421c0SAgustin Vega-Frias uniquify_event_name(counter); 11728c5421c0SAgustin Vega-Frias else if (counter->auto_merge_stats) 1173430daf2dSAndi Kleen collect_all_aliases(counter, cb, data); 1174430daf2dSAndi Kleen return true; 1175fbe51fbaSAndi Kleen } 1176fbe51fbaSAndi Kleen 1177fbe51fbaSAndi Kleen struct aggr_data { 1178fbe51fbaSAndi Kleen u64 ena, run, val; 1179fbe51fbaSAndi Kleen int id; 1180fbe51fbaSAndi Kleen int nr; 1181fbe51fbaSAndi Kleen int cpu; 1182fbe51fbaSAndi Kleen }; 1183fbe51fbaSAndi Kleen 1184fbe51fbaSAndi Kleen static void aggr_cb(struct perf_evsel *counter, void *data, bool first) 1185fbe51fbaSAndi Kleen { 1186fbe51fbaSAndi Kleen struct aggr_data *ad = data; 1187fbe51fbaSAndi Kleen int cpu, s2; 1188fbe51fbaSAndi Kleen 1189fbe51fbaSAndi Kleen for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1190fbe51fbaSAndi Kleen struct perf_counts_values *counts; 1191fbe51fbaSAndi Kleen 1192fbe51fbaSAndi Kleen s2 = aggr_get_id(perf_evsel__cpus(counter), cpu); 1193fbe51fbaSAndi Kleen if (s2 != ad->id) 1194fbe51fbaSAndi Kleen continue; 1195fbe51fbaSAndi Kleen if (first) 1196fbe51fbaSAndi Kleen ad->nr++; 1197fbe51fbaSAndi Kleen counts = perf_counts(counter->counts, cpu, 0); 1198b4229e9dSAndi Kleen /* 1199b4229e9dSAndi Kleen * When any result is bad, make them all to give 1200b4229e9dSAndi Kleen * consistent output in interval mode. 1201b4229e9dSAndi Kleen */ 1202b4229e9dSAndi Kleen if (counts->ena == 0 || counts->run == 0 || 1203b4229e9dSAndi Kleen counter->counts->scaled == -1) { 1204b4229e9dSAndi Kleen ad->ena = 0; 1205b4229e9dSAndi Kleen ad->run = 0; 1206b4229e9dSAndi Kleen break; 1207b4229e9dSAndi Kleen } 1208fbe51fbaSAndi Kleen ad->val += counts->val; 1209fbe51fbaSAndi Kleen ad->ena += counts->ena; 1210fbe51fbaSAndi Kleen ad->run += counts->run; 1211fbe51fbaSAndi Kleen } 1212fbe51fbaSAndi Kleen } 1213fbe51fbaSAndi Kleen 121486ee6e18SStephane Eranian static void print_aggr(char *prefix) 1215d7e7a451SStephane Eranian { 12165821522eSJiri Olsa FILE *output = stat_config.output; 1217d7e7a451SStephane Eranian struct perf_evsel *counter; 1218fbe51fbaSAndi Kleen int s, id, nr; 1219410136f5SStephane Eranian double uval; 1220d7e7a451SStephane Eranian u64 ena, run, val; 122154b50916SAndi Kleen bool first; 1222d7e7a451SStephane Eranian 122386ee6e18SStephane Eranian if (!(aggr_map || aggr_get_id)) 1224d7e7a451SStephane Eranian return; 1225d7e7a451SStephane Eranian 122644d49a60SAndi Kleen aggr_update_shadow(); 122744d49a60SAndi Kleen 122854b50916SAndi Kleen /* 122954b50916SAndi Kleen * With metric_only everything is on a single line. 123054b50916SAndi Kleen * Without each counter has its own line. 123154b50916SAndi Kleen */ 123286ee6e18SStephane Eranian for (s = 0; s < aggr_map->nr; s++) { 1233fbe51fbaSAndi Kleen struct aggr_data ad; 123454b50916SAndi Kleen if (prefix && metric_only) 123554b50916SAndi Kleen fprintf(output, "%s", prefix); 123654b50916SAndi Kleen 1237fbe51fbaSAndi Kleen ad.id = id = aggr_map->map[s]; 123854b50916SAndi Kleen first = true; 1239e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 1240e864c5caSAndi Kleen if (is_duration_time(counter)) 1241e864c5caSAndi Kleen continue; 1242e864c5caSAndi Kleen 1243fbe51fbaSAndi Kleen ad.val = ad.ena = ad.run = 0; 1244fbe51fbaSAndi Kleen ad.nr = 0; 1245430daf2dSAndi Kleen if (!collect_data(counter, aggr_cb, &ad)) 1246430daf2dSAndi Kleen continue; 1247fbe51fbaSAndi Kleen nr = ad.nr; 1248fbe51fbaSAndi Kleen ena = ad.ena; 1249fbe51fbaSAndi Kleen run = ad.run; 1250fbe51fbaSAndi Kleen val = ad.val; 125154b50916SAndi Kleen if (first && metric_only) { 125254b50916SAndi Kleen first = false; 125354b50916SAndi Kleen aggr_printout(counter, id, nr); 125454b50916SAndi Kleen } 125554b50916SAndi Kleen if (prefix && !metric_only) 1256d7e7a451SStephane Eranian fprintf(output, "%s", prefix); 1257d7e7a451SStephane Eranian 1258410136f5SStephane Eranian uval = val * counter->scale; 1259e0128b30SJin Yao printout(id, nr, counter, uval, prefix, run, ena, 1.0, 1260e0128b30SJin Yao &rt_stat); 126154b50916SAndi Kleen if (!metric_only) 1262d7e7a451SStephane Eranian fputc('\n', output); 1263d7e7a451SStephane Eranian } 126454b50916SAndi Kleen if (metric_only) 126554b50916SAndi Kleen fputc('\n', output); 1266d7e7a451SStephane Eranian } 1267d7e7a451SStephane Eranian } 1268d7e7a451SStephane Eranian 126929734550SJin Yao static int cmp_val(const void *a, const void *b) 127032b8af82SJiri Olsa { 127129734550SJin Yao return ((struct perf_aggr_thread_value *)b)->val - 127229734550SJin Yao ((struct perf_aggr_thread_value *)a)->val; 127329734550SJin Yao } 127429734550SJin Yao 127529734550SJin Yao static struct perf_aggr_thread_value *sort_aggr_thread( 127629734550SJin Yao struct perf_evsel *counter, 127729734550SJin Yao int nthreads, int ncpus, 127829734550SJin Yao int *ret) 127929734550SJin Yao { 128029734550SJin Yao int cpu, thread, i = 0; 128132b8af82SJiri Olsa double uval; 128229734550SJin Yao struct perf_aggr_thread_value *buf; 128329734550SJin Yao 128429734550SJin Yao buf = calloc(nthreads, sizeof(struct perf_aggr_thread_value)); 128529734550SJin Yao if (!buf) 128629734550SJin Yao return NULL; 128732b8af82SJiri Olsa 128832b8af82SJiri Olsa for (thread = 0; thread < nthreads; thread++) { 128932b8af82SJiri Olsa u64 ena = 0, run = 0, val = 0; 129032b8af82SJiri Olsa 129132b8af82SJiri Olsa for (cpu = 0; cpu < ncpus; cpu++) { 129232b8af82SJiri Olsa val += perf_counts(counter->counts, cpu, thread)->val; 129332b8af82SJiri Olsa ena += perf_counts(counter->counts, cpu, thread)->ena; 129432b8af82SJiri Olsa run += perf_counts(counter->counts, cpu, thread)->run; 129532b8af82SJiri Olsa } 129632b8af82SJiri Olsa 129729734550SJin Yao uval = val * counter->scale; 129829734550SJin Yao 129929734550SJin Yao /* 130029734550SJin Yao * Skip value 0 when enabling --per-thread globally, 130129734550SJin Yao * otherwise too many 0 output. 130229734550SJin Yao */ 130329734550SJin Yao if (uval == 0.0 && target__has_per_thread(&target)) 130429734550SJin Yao continue; 130529734550SJin Yao 130629734550SJin Yao buf[i].counter = counter; 130729734550SJin Yao buf[i].id = thread; 130829734550SJin Yao buf[i].uval = uval; 130929734550SJin Yao buf[i].val = val; 131029734550SJin Yao buf[i].run = run; 131129734550SJin Yao buf[i].ena = ena; 131229734550SJin Yao i++; 131329734550SJin Yao } 131429734550SJin Yao 131529734550SJin Yao qsort(buf, i, sizeof(struct perf_aggr_thread_value), cmp_val); 131629734550SJin Yao 131729734550SJin Yao if (ret) 131829734550SJin Yao *ret = i; 131929734550SJin Yao 132029734550SJin Yao return buf; 132129734550SJin Yao } 132229734550SJin Yao 132329734550SJin Yao static void print_aggr_thread(struct perf_evsel *counter, char *prefix) 132429734550SJin Yao { 132529734550SJin Yao FILE *output = stat_config.output; 132629734550SJin Yao int nthreads = thread_map__nr(counter->threads); 132729734550SJin Yao int ncpus = cpu_map__nr(counter->cpus); 132829734550SJin Yao int thread, sorted_threads, id; 132929734550SJin Yao struct perf_aggr_thread_value *buf; 133029734550SJin Yao 133129734550SJin Yao buf = sort_aggr_thread(counter, nthreads, ncpus, &sorted_threads); 133229734550SJin Yao if (!buf) { 133329734550SJin Yao perror("cannot sort aggr thread"); 133429734550SJin Yao return; 133529734550SJin Yao } 133629734550SJin Yao 133729734550SJin Yao for (thread = 0; thread < sorted_threads; thread++) { 133832b8af82SJiri Olsa if (prefix) 133932b8af82SJiri Olsa fprintf(output, "%s", prefix); 134032b8af82SJiri Olsa 134129734550SJin Yao id = buf[thread].id; 134214e72a21SJin Yao if (stat_config.stats) 134329734550SJin Yao printout(id, 0, buf[thread].counter, buf[thread].uval, 134429734550SJin Yao prefix, buf[thread].run, buf[thread].ena, 1.0, 134529734550SJin Yao &stat_config.stats[id]); 134614e72a21SJin Yao else 134729734550SJin Yao printout(id, 0, buf[thread].counter, buf[thread].uval, 134829734550SJin Yao prefix, buf[thread].run, buf[thread].ena, 1.0, 134929734550SJin Yao &rt_stat); 135032b8af82SJiri Olsa fputc('\n', output); 135132b8af82SJiri Olsa } 135229734550SJin Yao 135329734550SJin Yao free(buf); 135432b8af82SJiri Olsa } 135532b8af82SJiri Olsa 1356fbe51fbaSAndi Kleen struct caggr_data { 1357fbe51fbaSAndi Kleen double avg, avg_enabled, avg_running; 1358fbe51fbaSAndi Kleen }; 1359fbe51fbaSAndi Kleen 1360fbe51fbaSAndi Kleen static void counter_aggr_cb(struct perf_evsel *counter, void *data, 1361fbe51fbaSAndi Kleen bool first __maybe_unused) 1362fbe51fbaSAndi Kleen { 1363fbe51fbaSAndi Kleen struct caggr_data *cd = data; 1364e669e833SArnaldo Carvalho de Melo struct perf_stat_evsel *ps = counter->stats; 1365fbe51fbaSAndi Kleen 1366fbe51fbaSAndi Kleen cd->avg += avg_stats(&ps->res_stats[0]); 1367fbe51fbaSAndi Kleen cd->avg_enabled += avg_stats(&ps->res_stats[1]); 1368fbe51fbaSAndi Kleen cd->avg_running += avg_stats(&ps->res_stats[2]); 1369fbe51fbaSAndi Kleen } 1370fbe51fbaSAndi Kleen 137142202dd5SIngo Molnar /* 137242202dd5SIngo Molnar * Print out the results of a single counter: 1373f5b4a9c3SStephane Eranian * aggregated counts in system-wide mode 137442202dd5SIngo Molnar */ 137513370a9bSStephane Eranian static void print_counter_aggr(struct perf_evsel *counter, char *prefix) 137642202dd5SIngo Molnar { 13775821522eSJiri Olsa FILE *output = stat_config.output; 1378410136f5SStephane Eranian double uval; 1379fbe51fbaSAndi Kleen struct caggr_data cd = { .avg = 0.0 }; 1380d73515c0SAndi Kleen 1381430daf2dSAndi Kleen if (!collect_data(counter, counter_aggr_cb, &cd)) 1382430daf2dSAndi Kleen return; 138342202dd5SIngo Molnar 138454b50916SAndi Kleen if (prefix && !metric_only) 138513370a9bSStephane Eranian fprintf(output, "%s", prefix); 138613370a9bSStephane Eranian 1387fbe51fbaSAndi Kleen uval = cd.avg * counter->scale; 1388e0128b30SJin Yao printout(-1, 0, counter, uval, prefix, cd.avg_running, cd.avg_enabled, 1389e0128b30SJin Yao cd.avg, &rt_stat); 139054b50916SAndi Kleen if (!metric_only) 13914aa9015fSStephane Eranian fprintf(output, "\n"); 139242202dd5SIngo Molnar } 139342202dd5SIngo Molnar 1394fbe51fbaSAndi Kleen static void counter_cb(struct perf_evsel *counter, void *data, 1395fbe51fbaSAndi Kleen bool first __maybe_unused) 1396fbe51fbaSAndi Kleen { 1397fbe51fbaSAndi Kleen struct aggr_data *ad = data; 1398fbe51fbaSAndi Kleen 1399fbe51fbaSAndi Kleen ad->val += perf_counts(counter->counts, ad->cpu, 0)->val; 1400fbe51fbaSAndi Kleen ad->ena += perf_counts(counter->counts, ad->cpu, 0)->ena; 1401fbe51fbaSAndi Kleen ad->run += perf_counts(counter->counts, ad->cpu, 0)->run; 1402fbe51fbaSAndi Kleen } 1403fbe51fbaSAndi Kleen 1404f5b4a9c3SStephane Eranian /* 1405f5b4a9c3SStephane Eranian * Print out the results of a single counter: 1406f5b4a9c3SStephane Eranian * does not use aggregated count in system-wide 1407f5b4a9c3SStephane Eranian */ 140813370a9bSStephane Eranian static void print_counter(struct perf_evsel *counter, char *prefix) 1409f5b4a9c3SStephane Eranian { 14105821522eSJiri Olsa FILE *output = stat_config.output; 1411f5b4a9c3SStephane Eranian u64 ena, run, val; 1412410136f5SStephane Eranian double uval; 1413f5b4a9c3SStephane Eranian int cpu; 1414f5b4a9c3SStephane Eranian 14157ae92e74SYan, Zheng for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1416fbe51fbaSAndi Kleen struct aggr_data ad = { .cpu = cpu }; 1417fbe51fbaSAndi Kleen 1418430daf2dSAndi Kleen if (!collect_data(counter, counter_cb, &ad)) 1419430daf2dSAndi Kleen return; 1420fbe51fbaSAndi Kleen val = ad.val; 1421fbe51fbaSAndi Kleen ena = ad.ena; 1422fbe51fbaSAndi Kleen run = ad.run; 142313370a9bSStephane Eranian 142413370a9bSStephane Eranian if (prefix) 142513370a9bSStephane Eranian fprintf(output, "%s", prefix); 142613370a9bSStephane Eranian 1427410136f5SStephane Eranian uval = val * counter->scale; 1428e0128b30SJin Yao printout(cpu, 0, counter, uval, prefix, run, ena, 1.0, 1429e0128b30SJin Yao &rt_stat); 1430f5b4a9c3SStephane Eranian 14314aa9015fSStephane Eranian fputc('\n', output); 1432f5b4a9c3SStephane Eranian } 1433f5b4a9c3SStephane Eranian } 1434f5b4a9c3SStephane Eranian 1435206cab65SAndi Kleen static void print_no_aggr_metric(char *prefix) 1436206cab65SAndi Kleen { 1437206cab65SAndi Kleen int cpu; 1438206cab65SAndi Kleen int nrcpus = 0; 1439206cab65SAndi Kleen struct perf_evsel *counter; 1440206cab65SAndi Kleen u64 ena, run, val; 1441206cab65SAndi Kleen double uval; 1442206cab65SAndi Kleen 1443206cab65SAndi Kleen nrcpus = evsel_list->cpus->nr; 1444206cab65SAndi Kleen for (cpu = 0; cpu < nrcpus; cpu++) { 1445206cab65SAndi Kleen bool first = true; 1446206cab65SAndi Kleen 1447206cab65SAndi Kleen if (prefix) 1448206cab65SAndi Kleen fputs(prefix, stat_config.output); 1449e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 1450e864c5caSAndi Kleen if (is_duration_time(counter)) 1451e864c5caSAndi Kleen continue; 1452206cab65SAndi Kleen if (first) { 1453206cab65SAndi Kleen aggr_printout(counter, cpu, 0); 1454206cab65SAndi Kleen first = false; 1455206cab65SAndi Kleen } 1456206cab65SAndi Kleen val = perf_counts(counter->counts, cpu, 0)->val; 1457206cab65SAndi Kleen ena = perf_counts(counter->counts, cpu, 0)->ena; 1458206cab65SAndi Kleen run = perf_counts(counter->counts, cpu, 0)->run; 1459206cab65SAndi Kleen 1460206cab65SAndi Kleen uval = val * counter->scale; 1461e0128b30SJin Yao printout(cpu, 0, counter, uval, prefix, run, ena, 1.0, 1462e0128b30SJin Yao &rt_stat); 1463206cab65SAndi Kleen } 1464206cab65SAndi Kleen fputc('\n', stat_config.output); 1465206cab65SAndi Kleen } 1466206cab65SAndi Kleen } 1467206cab65SAndi Kleen 146854b50916SAndi Kleen static int aggr_header_lens[] = { 146954b50916SAndi Kleen [AGGR_CORE] = 18, 147054b50916SAndi Kleen [AGGR_SOCKET] = 12, 1471206cab65SAndi Kleen [AGGR_NONE] = 6, 147254b50916SAndi Kleen [AGGR_THREAD] = 24, 147354b50916SAndi Kleen [AGGR_GLOBAL] = 0, 147454b50916SAndi Kleen }; 147554b50916SAndi Kleen 1476c51fd639SAndi Kleen static const char *aggr_header_csv[] = { 1477c51fd639SAndi Kleen [AGGR_CORE] = "core,cpus,", 1478c51fd639SAndi Kleen [AGGR_SOCKET] = "socket,cpus", 1479c51fd639SAndi Kleen [AGGR_NONE] = "cpu,", 1480c51fd639SAndi Kleen [AGGR_THREAD] = "comm-pid,", 1481c51fd639SAndi Kleen [AGGR_GLOBAL] = "" 1482c51fd639SAndi Kleen }; 1483c51fd639SAndi Kleen 148441c8ca2aSAndi Kleen static void print_metric_headers(const char *prefix, bool no_indent) 148554b50916SAndi Kleen { 148654b50916SAndi Kleen struct perf_stat_output_ctx out; 148754b50916SAndi Kleen struct perf_evsel *counter; 148854b50916SAndi Kleen struct outstate os = { 148954b50916SAndi Kleen .fh = stat_config.output 149054b50916SAndi Kleen }; 149154b50916SAndi Kleen 149254b50916SAndi Kleen if (prefix) 149354b50916SAndi Kleen fprintf(stat_config.output, "%s", prefix); 149454b50916SAndi Kleen 149541c8ca2aSAndi Kleen if (!csv_output && !no_indent) 149654b50916SAndi Kleen fprintf(stat_config.output, "%*s", 149754b50916SAndi Kleen aggr_header_lens[stat_config.aggr_mode], ""); 1498c51fd639SAndi Kleen if (csv_output) { 1499c51fd639SAndi Kleen if (stat_config.interval) 1500c51fd639SAndi Kleen fputs("time,", stat_config.output); 1501c51fd639SAndi Kleen fputs(aggr_header_csv[stat_config.aggr_mode], 1502c51fd639SAndi Kleen stat_config.output); 1503c51fd639SAndi Kleen } 150454b50916SAndi Kleen 150554b50916SAndi Kleen /* Print metrics headers only */ 1506e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 1507e864c5caSAndi Kleen if (is_duration_time(counter)) 1508e864c5caSAndi Kleen continue; 150954b50916SAndi Kleen os.evsel = counter; 151054b50916SAndi Kleen out.ctx = &os; 151154b50916SAndi Kleen out.print_metric = print_metric_header; 151254b50916SAndi Kleen out.new_line = new_line_metric; 151337932c18SAndi Kleen out.force_header = true; 151454b50916SAndi Kleen os.evsel = counter; 151554b50916SAndi Kleen perf_stat__print_shadow_stats(counter, 0, 151654b50916SAndi Kleen 0, 1517b18f3e36SAndi Kleen &out, 1518e0128b30SJin Yao &metric_events, 1519e0128b30SJin Yao &rt_stat); 152054b50916SAndi Kleen } 152154b50916SAndi Kleen fputc('\n', stat_config.output); 152254b50916SAndi Kleen } 152354b50916SAndi Kleen 1524d4f63a47SJiri Olsa static void print_interval(char *prefix, struct timespec *ts) 152542202dd5SIngo Molnar { 15265821522eSJiri Olsa FILE *output = stat_config.output; 1527d4f63a47SJiri Olsa static int num_print_interval; 1528d4f63a47SJiri Olsa 15299660e08eSJiri Olsa if (interval_clear) 15309660e08eSJiri Olsa puts(CONSOLE_CLEAR); 15319660e08eSJiri Olsa 1532d4f63a47SJiri Olsa sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); 1533d4f63a47SJiri Olsa 15349660e08eSJiri Olsa if ((num_print_interval == 0 && !csv_output) || interval_clear) { 1535421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 1536d4f63a47SJiri Olsa case AGGR_SOCKET: 153741c8ca2aSAndi Kleen fprintf(output, "# time socket cpus"); 153841c8ca2aSAndi Kleen if (!metric_only) 153941c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1540d4f63a47SJiri Olsa break; 1541d4f63a47SJiri Olsa case AGGR_CORE: 154241c8ca2aSAndi Kleen fprintf(output, "# time core cpus"); 154341c8ca2aSAndi Kleen if (!metric_only) 154441c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1545d4f63a47SJiri Olsa break; 1546d4f63a47SJiri Olsa case AGGR_NONE: 154741c8ca2aSAndi Kleen fprintf(output, "# time CPU "); 154841c8ca2aSAndi Kleen if (!metric_only) 154941c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1550d4f63a47SJiri Olsa break; 155132b8af82SJiri Olsa case AGGR_THREAD: 155241c8ca2aSAndi Kleen fprintf(output, "# time comm-pid"); 155341c8ca2aSAndi Kleen if (!metric_only) 155441c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 155532b8af82SJiri Olsa break; 1556d4f63a47SJiri Olsa case AGGR_GLOBAL: 1557d4f63a47SJiri Olsa default: 155841c8ca2aSAndi Kleen fprintf(output, "# time"); 155941c8ca2aSAndi Kleen if (!metric_only) 156041c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1561208df99eSJiri Olsa case AGGR_UNSET: 1562208df99eSJiri Olsa break; 1563d4f63a47SJiri Olsa } 1564d4f63a47SJiri Olsa } 1565d4f63a47SJiri Olsa 1566c818cc06SJiri Olsa if ((num_print_interval == 0 || interval_clear) && metric_only) 156741c8ca2aSAndi Kleen print_metric_headers(" ", true); 1568d4f63a47SJiri Olsa if (++num_print_interval == 25) 1569d4f63a47SJiri Olsa num_print_interval = 0; 1570d4f63a47SJiri Olsa } 1571d4f63a47SJiri Olsa 1572d4f63a47SJiri Olsa static void print_header(int argc, const char **argv) 1573d4f63a47SJiri Olsa { 15745821522eSJiri Olsa FILE *output = stat_config.output; 157569aad6f1SArnaldo Carvalho de Melo int i; 157642202dd5SIngo Molnar 157786470930SIngo Molnar fflush(stdout); 157886470930SIngo Molnar 1579d7470b6aSStephane Eranian if (!csv_output) { 15804aa9015fSStephane Eranian fprintf(output, "\n"); 15814aa9015fSStephane Eranian fprintf(output, " Performance counter stats for "); 158262d3b617SDavid Ahern if (target.system_wide) 158362d3b617SDavid Ahern fprintf(output, "\'system wide"); 158462d3b617SDavid Ahern else if (target.cpu_list) 158562d3b617SDavid Ahern fprintf(output, "\'CPU(s) %s", target.cpu_list); 1586602ad878SArnaldo Carvalho de Melo else if (!target__has_task(&target)) { 1587ba6039b6SJiri Olsa fprintf(output, "\'%s", argv ? argv[0] : "pipe"); 1588ba6039b6SJiri Olsa for (i = 1; argv && (i < argc); i++) 15894aa9015fSStephane Eranian fprintf(output, " %s", argv[i]); 159020f946b4SNamhyung Kim } else if (target.pid) 159120f946b4SNamhyung Kim fprintf(output, "process id \'%s", target.pid); 1592d6d901c2SZhang, Yanmin else 159320f946b4SNamhyung Kim fprintf(output, "thread id \'%s", target.tid); 159486470930SIngo Molnar 15954aa9015fSStephane Eranian fprintf(output, "\'"); 159642202dd5SIngo Molnar if (run_count > 1) 15974aa9015fSStephane Eranian fprintf(output, " (%d runs)", run_count); 15984aa9015fSStephane Eranian fprintf(output, ":\n\n"); 1599d7470b6aSStephane Eranian } 1600f5b4a9c3SStephane Eranian } 160186470930SIngo Molnar 1602bc22de9bSJiri Olsa static int get_precision(double num) 1603bc22de9bSJiri Olsa { 1604bc22de9bSJiri Olsa if (num > 1) 1605bc22de9bSJiri Olsa return 0; 1606bc22de9bSJiri Olsa 1607bc22de9bSJiri Olsa return lround(ceil(-log10(num))); 1608bc22de9bSJiri Olsa } 1609bc22de9bSJiri Olsa 1610e55c14afSJiri Olsa static void print_table(FILE *output, int precision, double avg) 1611e55c14afSJiri Olsa { 1612e55c14afSJiri Olsa char tmp[64]; 1613e55c14afSJiri Olsa int idx, indent = 0; 1614e55c14afSJiri Olsa 1615e55c14afSJiri Olsa scnprintf(tmp, 64, " %17.*f", precision, avg); 1616e55c14afSJiri Olsa while (tmp[indent] == ' ') 1617e55c14afSJiri Olsa indent++; 1618e55c14afSJiri Olsa 1619e55c14afSJiri Olsa fprintf(output, "%*s# Table of individual measurements:\n", indent, ""); 1620e55c14afSJiri Olsa 1621e55c14afSJiri Olsa for (idx = 0; idx < run_count; idx++) { 1622e55c14afSJiri Olsa double run = (double) walltime_run[idx] / NSEC_PER_SEC; 1623abc60badSJiri Olsa int h, n = 1 + abs((int) (100.0 * (run - avg)/run) / 5); 1624e55c14afSJiri Olsa 1625abc60badSJiri Olsa fprintf(output, " %17.*f (%+.*f) ", 1626e55c14afSJiri Olsa precision, run, precision, run - avg); 1627abc60badSJiri Olsa 1628abc60badSJiri Olsa for (h = 0; h < n; h++) 1629abc60badSJiri Olsa fprintf(output, "#"); 1630abc60badSJiri Olsa 1631abc60badSJiri Olsa fprintf(output, "\n"); 1632e55c14afSJiri Olsa } 1633e55c14afSJiri Olsa 1634e55c14afSJiri Olsa fprintf(output, "\n%*s# Final result:\n", indent, ""); 1635e55c14afSJiri Olsa } 1636e55c14afSJiri Olsa 16370ce2da14SJiri Olsa static double timeval2double(struct timeval *t) 16380ce2da14SJiri Olsa { 16390ce2da14SJiri Olsa return t->tv_sec + (double) t->tv_usec/USEC_PER_SEC; 16400ce2da14SJiri Olsa } 16410ce2da14SJiri Olsa 1642d4f63a47SJiri Olsa static void print_footer(void) 1643d4f63a47SJiri Olsa { 1644bc22de9bSJiri Olsa double avg = avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; 16455821522eSJiri Olsa FILE *output = stat_config.output; 1646918c7b06SAndi Kleen int n; 16475821522eSJiri Olsa 1648c3305257SIngo Molnar if (!null_run) 16494aa9015fSStephane Eranian fprintf(output, "\n"); 1650bc22de9bSJiri Olsa 1651bc22de9bSJiri Olsa if (run_count == 1) { 1652bc22de9bSJiri Olsa fprintf(output, " %17.9f seconds time elapsed", avg); 16530ce2da14SJiri Olsa 16540ce2da14SJiri Olsa if (ru_display) { 16550ce2da14SJiri Olsa double ru_utime = timeval2double(&ru_data.ru_utime); 16560ce2da14SJiri Olsa double ru_stime = timeval2double(&ru_data.ru_stime); 16570ce2da14SJiri Olsa 16580ce2da14SJiri Olsa fprintf(output, "\n\n"); 16590ce2da14SJiri Olsa fprintf(output, " %17.9f seconds user\n", ru_utime); 16600ce2da14SJiri Olsa fprintf(output, " %17.9f seconds sys\n", ru_stime); 16610ce2da14SJiri Olsa } 1662bc22de9bSJiri Olsa } else { 1663bc22de9bSJiri Olsa double sd = stddev_stats(&walltime_nsecs_stats) / NSEC_PER_SEC; 1664bc22de9bSJiri Olsa /* 1665bc22de9bSJiri Olsa * Display at most 2 more significant 1666bc22de9bSJiri Olsa * digits than the stddev inaccuracy. 1667bc22de9bSJiri Olsa */ 1668bc22de9bSJiri Olsa int precision = get_precision(sd) + 2; 1669bc22de9bSJiri Olsa 1670e55c14afSJiri Olsa if (walltime_run_table) 1671e55c14afSJiri Olsa print_table(output, precision, avg); 1672e55c14afSJiri Olsa 1673bc22de9bSJiri Olsa fprintf(output, " %17.*f +- %.*f seconds time elapsed", 1674bc22de9bSJiri Olsa precision, avg, precision, sd); 1675bc22de9bSJiri Olsa 1676bc22de9bSJiri Olsa print_noise_pct(sd, avg); 1677566747e6SIngo Molnar } 16784aa9015fSStephane Eranian fprintf(output, "\n\n"); 167902d492e5SBorislav Petkov 1680918c7b06SAndi Kleen if (print_free_counters_hint && 1681918c7b06SAndi Kleen sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 && 1682918c7b06SAndi Kleen n > 0) 168302d492e5SBorislav Petkov fprintf(output, 168402d492e5SBorislav Petkov "Some events weren't counted. Try disabling the NMI watchdog:\n" 168502d492e5SBorislav Petkov " echo 0 > /proc/sys/kernel/nmi_watchdog\n" 168602d492e5SBorislav Petkov " perf stat ...\n" 168702d492e5SBorislav Petkov " echo 1 > /proc/sys/kernel/nmi_watchdog\n"); 168830060eaeSKan Liang 168930060eaeSKan Liang if (print_mixed_hw_group_error) 169030060eaeSKan Liang fprintf(output, 169130060eaeSKan Liang "The events in group usually have to be from " 169230060eaeSKan Liang "the same PMU. Try reorganizing the group.\n"); 169386470930SIngo Molnar } 1694d4f63a47SJiri Olsa 1695a5a9eac1SJiri Olsa static void 1696a5a9eac1SJiri Olsa perf_evlist__print_counters(struct perf_evlist *evlist, 1697b64df7f3SJiri Olsa struct perf_stat_config *config, 1698a5a9eac1SJiri Olsa struct timespec *ts, 1699a5a9eac1SJiri Olsa int argc, const char **argv) 1700d4f63a47SJiri Olsa { 1701b64df7f3SJiri Olsa int interval = config->interval; 1702d4f63a47SJiri Olsa struct perf_evsel *counter; 1703d4f63a47SJiri Olsa char buf[64], *prefix = NULL; 1704d4f63a47SJiri Olsa 1705d4f63a47SJiri Olsa if (interval) 1706d4f63a47SJiri Olsa print_interval(prefix = buf, ts); 1707d4f63a47SJiri Olsa else 1708d4f63a47SJiri Olsa print_header(argc, argv); 1709d4f63a47SJiri Olsa 171054b50916SAndi Kleen if (metric_only) { 171154b50916SAndi Kleen static int num_print_iv; 171254b50916SAndi Kleen 171341c8ca2aSAndi Kleen if (num_print_iv == 0 && !interval) 171441c8ca2aSAndi Kleen print_metric_headers(prefix, false); 171554b50916SAndi Kleen if (num_print_iv++ == 25) 171654b50916SAndi Kleen num_print_iv = 0; 1717b64df7f3SJiri Olsa if (config->aggr_mode == AGGR_GLOBAL && prefix) 1718b64df7f3SJiri Olsa fprintf(config->output, "%s", prefix); 171954b50916SAndi Kleen } 172054b50916SAndi Kleen 1721b64df7f3SJiri Olsa switch (config->aggr_mode) { 1722d4f63a47SJiri Olsa case AGGR_CORE: 1723d4f63a47SJiri Olsa case AGGR_SOCKET: 1724d4f63a47SJiri Olsa print_aggr(prefix); 1725d4f63a47SJiri Olsa break; 172632b8af82SJiri Olsa case AGGR_THREAD: 1727a5a9eac1SJiri Olsa evlist__for_each_entry(evlist, counter) { 1728e864c5caSAndi Kleen if (is_duration_time(counter)) 1729e864c5caSAndi Kleen continue; 173032b8af82SJiri Olsa print_aggr_thread(counter, prefix); 1731e864c5caSAndi Kleen } 173232b8af82SJiri Olsa break; 1733d4f63a47SJiri Olsa case AGGR_GLOBAL: 1734a5a9eac1SJiri Olsa evlist__for_each_entry(evlist, counter) { 1735e864c5caSAndi Kleen if (is_duration_time(counter)) 1736e864c5caSAndi Kleen continue; 1737d4f63a47SJiri Olsa print_counter_aggr(counter, prefix); 1738e864c5caSAndi Kleen } 173954b50916SAndi Kleen if (metric_only) 1740b64df7f3SJiri Olsa fputc('\n', config->output); 1741d4f63a47SJiri Olsa break; 1742d4f63a47SJiri Olsa case AGGR_NONE: 1743206cab65SAndi Kleen if (metric_only) 1744206cab65SAndi Kleen print_no_aggr_metric(prefix); 1745206cab65SAndi Kleen else { 1746a5a9eac1SJiri Olsa evlist__for_each_entry(evlist, counter) { 1747e864c5caSAndi Kleen if (is_duration_time(counter)) 1748e864c5caSAndi Kleen continue; 1749d4f63a47SJiri Olsa print_counter(counter, prefix); 1750206cab65SAndi Kleen } 1751e864c5caSAndi Kleen } 1752d4f63a47SJiri Olsa break; 1753208df99eSJiri Olsa case AGGR_UNSET: 1754d4f63a47SJiri Olsa default: 1755d4f63a47SJiri Olsa break; 1756d4f63a47SJiri Olsa } 1757d4f63a47SJiri Olsa 1758d4f63a47SJiri Olsa if (!interval && !csv_output) 1759d4f63a47SJiri Olsa print_footer(); 1760d4f63a47SJiri Olsa 1761b64df7f3SJiri Olsa fflush(config->output); 1762d7470b6aSStephane Eranian } 176386470930SIngo Molnar 1764a5a9eac1SJiri Olsa static void print_counters(struct timespec *ts, int argc, const char **argv) 1765a5a9eac1SJiri Olsa { 17660174820aSJiri Olsa /* Do not print anything if we record to the pipe. */ 17670174820aSJiri Olsa if (STAT_RECORD && perf_stat.data.is_pipe) 17680174820aSJiri Olsa return; 17690174820aSJiri Olsa 1770b64df7f3SJiri Olsa perf_evlist__print_counters(evsel_list, &stat_config, 1771b64df7f3SJiri Olsa ts, argc, argv); 1772a5a9eac1SJiri Olsa } 1773a5a9eac1SJiri Olsa 1774f7b7c26eSPeter Zijlstra static volatile int signr = -1; 1775f7b7c26eSPeter Zijlstra 177686470930SIngo Molnar static void skip_signal(int signo) 177786470930SIngo Molnar { 1778ec0d3d1fSJiri Olsa if ((child_pid == -1) || stat_config.interval) 177960666c63SLiming Wang done = 1; 178060666c63SLiming Wang 1781f7b7c26eSPeter Zijlstra signr = signo; 1782d07f0b12SStephane Eranian /* 1783d07f0b12SStephane Eranian * render child_pid harmless 1784d07f0b12SStephane Eranian * won't send SIGTERM to a random 1785d07f0b12SStephane Eranian * process in case of race condition 1786d07f0b12SStephane Eranian * and fast PID recycling 1787d07f0b12SStephane Eranian */ 1788d07f0b12SStephane Eranian child_pid = -1; 1789f7b7c26eSPeter Zijlstra } 1790f7b7c26eSPeter Zijlstra 1791f7b7c26eSPeter Zijlstra static void sig_atexit(void) 1792f7b7c26eSPeter Zijlstra { 1793d07f0b12SStephane Eranian sigset_t set, oset; 1794d07f0b12SStephane Eranian 1795d07f0b12SStephane Eranian /* 1796d07f0b12SStephane Eranian * avoid race condition with SIGCHLD handler 1797d07f0b12SStephane Eranian * in skip_signal() which is modifying child_pid 1798d07f0b12SStephane Eranian * goal is to avoid send SIGTERM to a random 1799d07f0b12SStephane Eranian * process 1800d07f0b12SStephane Eranian */ 1801d07f0b12SStephane Eranian sigemptyset(&set); 1802d07f0b12SStephane Eranian sigaddset(&set, SIGCHLD); 1803d07f0b12SStephane Eranian sigprocmask(SIG_BLOCK, &set, &oset); 1804d07f0b12SStephane Eranian 1805933da83aSChris Wilson if (child_pid != -1) 1806933da83aSChris Wilson kill(child_pid, SIGTERM); 1807933da83aSChris Wilson 1808d07f0b12SStephane Eranian sigprocmask(SIG_SETMASK, &oset, NULL); 1809d07f0b12SStephane Eranian 1810f7b7c26eSPeter Zijlstra if (signr == -1) 1811f7b7c26eSPeter Zijlstra return; 1812f7b7c26eSPeter Zijlstra 1813f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 1814f7b7c26eSPeter Zijlstra kill(getpid(), signr); 181586470930SIngo Molnar } 181686470930SIngo Molnar 18171d037ca1SIrina Tirdea static int stat__set_big_num(const struct option *opt __maybe_unused, 18181d037ca1SIrina Tirdea const char *s __maybe_unused, int unset) 1819d7470b6aSStephane Eranian { 1820d7470b6aSStephane Eranian big_num_opt = unset ? 0 : 1; 1821d7470b6aSStephane Eranian return 0; 1822d7470b6aSStephane Eranian } 1823d7470b6aSStephane Eranian 182444b1e60aSAndi Kleen static int enable_metric_only(const struct option *opt __maybe_unused, 182544b1e60aSAndi Kleen const char *s __maybe_unused, int unset) 182644b1e60aSAndi Kleen { 182744b1e60aSAndi Kleen force_metric_only = true; 182844b1e60aSAndi Kleen metric_only = !unset; 182944b1e60aSAndi Kleen return 0; 183044b1e60aSAndi Kleen } 183144b1e60aSAndi Kleen 1832b18f3e36SAndi Kleen static int parse_metric_groups(const struct option *opt, 1833b18f3e36SAndi Kleen const char *str, 1834b18f3e36SAndi Kleen int unset __maybe_unused) 1835b18f3e36SAndi Kleen { 1836b18f3e36SAndi Kleen return metricgroup__parse_groups(opt, str, &metric_events); 1837b18f3e36SAndi Kleen } 1838b18f3e36SAndi Kleen 1839e0547311SJiri Olsa static const struct option stat_options[] = { 1840e0547311SJiri Olsa OPT_BOOLEAN('T', "transaction", &transaction_run, 1841e0547311SJiri Olsa "hardware transaction statistics"), 1842e0547311SJiri Olsa OPT_CALLBACK('e', "event", &evsel_list, "event", 1843e0547311SJiri Olsa "event selector. use 'perf list' to list available events", 1844e0547311SJiri Olsa parse_events_option), 1845e0547311SJiri Olsa OPT_CALLBACK(0, "filter", &evsel_list, "filter", 1846e0547311SJiri Olsa "event filter", parse_filter), 18475698f26bSJiri Olsa OPT_BOOLEAN('i', "no-inherit", &stat_config.no_inherit, 1848e0547311SJiri Olsa "child tasks do not inherit counters"), 1849e0547311SJiri Olsa OPT_STRING('p', "pid", &target.pid, "pid", 1850e0547311SJiri Olsa "stat events on existing process id"), 1851e0547311SJiri Olsa OPT_STRING('t', "tid", &target.tid, "tid", 1852e0547311SJiri Olsa "stat events on existing thread id"), 1853e0547311SJiri Olsa OPT_BOOLEAN('a', "all-cpus", &target.system_wide, 1854e0547311SJiri Olsa "system-wide collection from all CPUs"), 1855e0547311SJiri Olsa OPT_BOOLEAN('g', "group", &group, 1856e0547311SJiri Olsa "put the counters into a counter group"), 1857e0547311SJiri Olsa OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"), 1858e0547311SJiri Olsa OPT_INCR('v', "verbose", &verbose, 1859e0547311SJiri Olsa "be more verbose (show counter open errors, etc)"), 1860e0547311SJiri Olsa OPT_INTEGER('r', "repeat", &run_count, 1861e0547311SJiri Olsa "repeat command and print average + stddev (max: 100, forever: 0)"), 1862e55c14afSJiri Olsa OPT_BOOLEAN(0, "table", &walltime_run_table, 1863e55c14afSJiri Olsa "display details about each run (only with -r option)"), 1864e0547311SJiri Olsa OPT_BOOLEAN('n', "null", &null_run, 1865e0547311SJiri Olsa "null run - dont start any counters"), 1866e0547311SJiri Olsa OPT_INCR('d', "detailed", &detailed_run, 1867e0547311SJiri Olsa "detailed run - start a lot of events"), 1868e0547311SJiri Olsa OPT_BOOLEAN('S', "sync", &sync_run, 1869e0547311SJiri Olsa "call sync() before starting a run"), 1870e0547311SJiri Olsa OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1871e0547311SJiri Olsa "print large numbers with thousands\' separators", 1872e0547311SJiri Olsa stat__set_big_num), 1873e0547311SJiri Olsa OPT_STRING('C', "cpu", &target.cpu_list, "cpu", 1874e0547311SJiri Olsa "list of cpus to monitor in system-wide"), 1875e0547311SJiri Olsa OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, 1876e0547311SJiri Olsa "disable CPU count aggregation", AGGR_NONE), 1877430daf2dSAndi Kleen OPT_BOOLEAN(0, "no-merge", &no_merge, "Do not merge identical named events"), 1878e0547311SJiri Olsa OPT_STRING('x', "field-separator", &csv_sep, "separator", 1879e0547311SJiri Olsa "print counts with custom separator"), 1880e0547311SJiri Olsa OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 1881e0547311SJiri Olsa "monitor event in cgroup name only", parse_cgroups), 1882e0547311SJiri Olsa OPT_STRING('o', "output", &output_name, "file", "output file name"), 1883e0547311SJiri Olsa OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), 1884e0547311SJiri Olsa OPT_INTEGER(0, "log-fd", &output_fd, 1885e0547311SJiri Olsa "log output to fd, instead of stderr"), 1886e0547311SJiri Olsa OPT_STRING(0, "pre", &pre_cmd, "command", 1887e0547311SJiri Olsa "command to run prior to the measured command"), 1888e0547311SJiri Olsa OPT_STRING(0, "post", &post_cmd, "command", 1889e0547311SJiri Olsa "command to run after to the measured command"), 1890e0547311SJiri Olsa OPT_UINTEGER('I', "interval-print", &stat_config.interval, 18919dc9a95fSAlexey Budankov "print counts at regular interval in ms " 18929dc9a95fSAlexey Budankov "(overhead is possible for values <= 100ms)"), 1893db06a269Syuzhoujian OPT_INTEGER(0, "interval-count", &stat_config.times, 1894db06a269Syuzhoujian "print counts for fixed number of times"), 18959660e08eSJiri Olsa OPT_BOOLEAN(0, "interval-clear", &interval_clear, 18969660e08eSJiri Olsa "clear screen in between new interval"), 1897f1f8ad52Syuzhoujian OPT_UINTEGER(0, "timeout", &stat_config.timeout, 1898f1f8ad52Syuzhoujian "stop workload and print counts after a timeout period in ms (>= 10ms)"), 1899e0547311SJiri Olsa OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, 1900e0547311SJiri Olsa "aggregate counts per processor socket", AGGR_SOCKET), 1901e0547311SJiri Olsa OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, 1902e0547311SJiri Olsa "aggregate counts per physical processor core", AGGR_CORE), 1903e0547311SJiri Olsa OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode, 1904e0547311SJiri Olsa "aggregate counts per thread", AGGR_THREAD), 1905728c0ee0SJiri Olsa OPT_UINTEGER('D', "delay", &stat_config.initial_delay, 1906e0547311SJiri Olsa "ms to wait before starting measurement after program start"), 190744b1e60aSAndi Kleen OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, 190844b1e60aSAndi Kleen "Only print computed metrics. No raw values", enable_metric_only), 190944b1e60aSAndi Kleen OPT_BOOLEAN(0, "topdown", &topdown_run, 191044b1e60aSAndi Kleen "measure topdown level 1 statistics"), 1911daefd0bcSKan Liang OPT_BOOLEAN(0, "smi-cost", &smi_cost, 1912daefd0bcSKan Liang "measure SMI cost"), 1913b18f3e36SAndi Kleen OPT_CALLBACK('M', "metrics", &evsel_list, "metric/metric group list", 1914b18f3e36SAndi Kleen "monitor specified metrics or metric groups (separated by ,)", 1915b18f3e36SAndi Kleen parse_metric_groups), 1916e0547311SJiri Olsa OPT_END() 1917e0547311SJiri Olsa }; 1918e0547311SJiri Olsa 19191fe7a300SJiri Olsa static int perf_stat__get_socket(struct cpu_map *map, int cpu) 19201fe7a300SJiri Olsa { 19211fe7a300SJiri Olsa return cpu_map__get_socket(map, cpu, NULL); 19221fe7a300SJiri Olsa } 19231fe7a300SJiri Olsa 19241fe7a300SJiri Olsa static int perf_stat__get_core(struct cpu_map *map, int cpu) 19251fe7a300SJiri Olsa { 19261fe7a300SJiri Olsa return cpu_map__get_core(map, cpu, NULL); 19271fe7a300SJiri Olsa } 19281fe7a300SJiri Olsa 19291e5a2931SJiri Olsa static int cpu_map__get_max(struct cpu_map *map) 19301e5a2931SJiri Olsa { 19311e5a2931SJiri Olsa int i, max = -1; 19321e5a2931SJiri Olsa 19331e5a2931SJiri Olsa for (i = 0; i < map->nr; i++) { 19341e5a2931SJiri Olsa if (map->map[i] > max) 19351e5a2931SJiri Olsa max = map->map[i]; 19361e5a2931SJiri Olsa } 19371e5a2931SJiri Olsa 19381e5a2931SJiri Olsa return max; 19391e5a2931SJiri Olsa } 19401e5a2931SJiri Olsa 19411e5a2931SJiri Olsa static struct cpu_map *cpus_aggr_map; 19421e5a2931SJiri Olsa 19431e5a2931SJiri Olsa static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx) 19441e5a2931SJiri Olsa { 19451e5a2931SJiri Olsa int cpu; 19461e5a2931SJiri Olsa 19471e5a2931SJiri Olsa if (idx >= map->nr) 19481e5a2931SJiri Olsa return -1; 19491e5a2931SJiri Olsa 19501e5a2931SJiri Olsa cpu = map->map[idx]; 19511e5a2931SJiri Olsa 19521e5a2931SJiri Olsa if (cpus_aggr_map->map[cpu] == -1) 19531e5a2931SJiri Olsa cpus_aggr_map->map[cpu] = get_id(map, idx); 19541e5a2931SJiri Olsa 19551e5a2931SJiri Olsa return cpus_aggr_map->map[cpu]; 19561e5a2931SJiri Olsa } 19571e5a2931SJiri Olsa 19581e5a2931SJiri Olsa static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) 19591e5a2931SJiri Olsa { 19601e5a2931SJiri Olsa return perf_stat__get_aggr(perf_stat__get_socket, map, idx); 19611e5a2931SJiri Olsa } 19621e5a2931SJiri Olsa 19631e5a2931SJiri Olsa static int perf_stat__get_core_cached(struct cpu_map *map, int idx) 19641e5a2931SJiri Olsa { 19651e5a2931SJiri Olsa return perf_stat__get_aggr(perf_stat__get_core, map, idx); 19661e5a2931SJiri Olsa } 19671e5a2931SJiri Olsa 196886ee6e18SStephane Eranian static int perf_stat_init_aggr_mode(void) 196986ee6e18SStephane Eranian { 19701e5a2931SJiri Olsa int nr; 19711e5a2931SJiri Olsa 1972421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 197386ee6e18SStephane Eranian case AGGR_SOCKET: 197486ee6e18SStephane Eranian if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { 197586ee6e18SStephane Eranian perror("cannot build socket map"); 197686ee6e18SStephane Eranian return -1; 197786ee6e18SStephane Eranian } 19781e5a2931SJiri Olsa aggr_get_id = perf_stat__get_socket_cached; 197986ee6e18SStephane Eranian break; 198012c08a9fSStephane Eranian case AGGR_CORE: 198112c08a9fSStephane Eranian if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { 198212c08a9fSStephane Eranian perror("cannot build core map"); 198312c08a9fSStephane Eranian return -1; 198412c08a9fSStephane Eranian } 19851e5a2931SJiri Olsa aggr_get_id = perf_stat__get_core_cached; 198612c08a9fSStephane Eranian break; 198786ee6e18SStephane Eranian case AGGR_NONE: 198886ee6e18SStephane Eranian case AGGR_GLOBAL: 198932b8af82SJiri Olsa case AGGR_THREAD: 1990208df99eSJiri Olsa case AGGR_UNSET: 199186ee6e18SStephane Eranian default: 199286ee6e18SStephane Eranian break; 199386ee6e18SStephane Eranian } 19941e5a2931SJiri Olsa 19951e5a2931SJiri Olsa /* 19961e5a2931SJiri Olsa * The evsel_list->cpus is the base we operate on, 19971e5a2931SJiri Olsa * taking the highest cpu number to be the size of 19981e5a2931SJiri Olsa * the aggregation translate cpumap. 19991e5a2931SJiri Olsa */ 20001e5a2931SJiri Olsa nr = cpu_map__get_max(evsel_list->cpus); 20011e5a2931SJiri Olsa cpus_aggr_map = cpu_map__empty_new(nr + 1); 20021e5a2931SJiri Olsa return cpus_aggr_map ? 0 : -ENOMEM; 200386ee6e18SStephane Eranian } 200486ee6e18SStephane Eranian 2005544c2ae7SMasami Hiramatsu static void perf_stat__exit_aggr_mode(void) 2006544c2ae7SMasami Hiramatsu { 2007544c2ae7SMasami Hiramatsu cpu_map__put(aggr_map); 2008544c2ae7SMasami Hiramatsu cpu_map__put(cpus_aggr_map); 2009544c2ae7SMasami Hiramatsu aggr_map = NULL; 2010544c2ae7SMasami Hiramatsu cpus_aggr_map = NULL; 2011544c2ae7SMasami Hiramatsu } 2012544c2ae7SMasami Hiramatsu 201368d702f7SJiri Olsa static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx) 201468d702f7SJiri Olsa { 201568d702f7SJiri Olsa int cpu; 201668d702f7SJiri Olsa 201768d702f7SJiri Olsa if (idx > map->nr) 201868d702f7SJiri Olsa return -1; 201968d702f7SJiri Olsa 202068d702f7SJiri Olsa cpu = map->map[idx]; 202168d702f7SJiri Olsa 2022da8a58b5SJan Stancek if (cpu >= env->nr_cpus_avail) 202368d702f7SJiri Olsa return -1; 202468d702f7SJiri Olsa 202568d702f7SJiri Olsa return cpu; 202668d702f7SJiri Olsa } 202768d702f7SJiri Olsa 202868d702f7SJiri Olsa static int perf_env__get_socket(struct cpu_map *map, int idx, void *data) 202968d702f7SJiri Olsa { 203068d702f7SJiri Olsa struct perf_env *env = data; 203168d702f7SJiri Olsa int cpu = perf_env__get_cpu(env, map, idx); 203268d702f7SJiri Olsa 203368d702f7SJiri Olsa return cpu == -1 ? -1 : env->cpu[cpu].socket_id; 203468d702f7SJiri Olsa } 203568d702f7SJiri Olsa 203668d702f7SJiri Olsa static int perf_env__get_core(struct cpu_map *map, int idx, void *data) 203768d702f7SJiri Olsa { 203868d702f7SJiri Olsa struct perf_env *env = data; 203968d702f7SJiri Olsa int core = -1, cpu = perf_env__get_cpu(env, map, idx); 204068d702f7SJiri Olsa 204168d702f7SJiri Olsa if (cpu != -1) { 204268d702f7SJiri Olsa int socket_id = env->cpu[cpu].socket_id; 204368d702f7SJiri Olsa 204468d702f7SJiri Olsa /* 204568d702f7SJiri Olsa * Encode socket in upper 16 bits 204668d702f7SJiri Olsa * core_id is relative to socket, and 204768d702f7SJiri Olsa * we need a global id. So we combine 204868d702f7SJiri Olsa * socket + core id. 204968d702f7SJiri Olsa */ 205068d702f7SJiri Olsa core = (socket_id << 16) | (env->cpu[cpu].core_id & 0xffff); 205168d702f7SJiri Olsa } 205268d702f7SJiri Olsa 205368d702f7SJiri Olsa return core; 205468d702f7SJiri Olsa } 205568d702f7SJiri Olsa 205668d702f7SJiri Olsa static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus, 205768d702f7SJiri Olsa struct cpu_map **sockp) 205868d702f7SJiri Olsa { 205968d702f7SJiri Olsa return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env); 206068d702f7SJiri Olsa } 206168d702f7SJiri Olsa 206268d702f7SJiri Olsa static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus, 206368d702f7SJiri Olsa struct cpu_map **corep) 206468d702f7SJiri Olsa { 206568d702f7SJiri Olsa return cpu_map__build_map(cpus, corep, perf_env__get_core, env); 206668d702f7SJiri Olsa } 206768d702f7SJiri Olsa 206868d702f7SJiri Olsa static int perf_stat__get_socket_file(struct cpu_map *map, int idx) 206968d702f7SJiri Olsa { 207068d702f7SJiri Olsa return perf_env__get_socket(map, idx, &perf_stat.session->header.env); 207168d702f7SJiri Olsa } 207268d702f7SJiri Olsa 207368d702f7SJiri Olsa static int perf_stat__get_core_file(struct cpu_map *map, int idx) 207468d702f7SJiri Olsa { 207568d702f7SJiri Olsa return perf_env__get_core(map, idx, &perf_stat.session->header.env); 207668d702f7SJiri Olsa } 207768d702f7SJiri Olsa 207868d702f7SJiri Olsa static int perf_stat_init_aggr_mode_file(struct perf_stat *st) 207968d702f7SJiri Olsa { 208068d702f7SJiri Olsa struct perf_env *env = &st->session->header.env; 208168d702f7SJiri Olsa 208268d702f7SJiri Olsa switch (stat_config.aggr_mode) { 208368d702f7SJiri Olsa case AGGR_SOCKET: 208468d702f7SJiri Olsa if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) { 208568d702f7SJiri Olsa perror("cannot build socket map"); 208668d702f7SJiri Olsa return -1; 208768d702f7SJiri Olsa } 208868d702f7SJiri Olsa aggr_get_id = perf_stat__get_socket_file; 208968d702f7SJiri Olsa break; 209068d702f7SJiri Olsa case AGGR_CORE: 209168d702f7SJiri Olsa if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) { 209268d702f7SJiri Olsa perror("cannot build core map"); 209368d702f7SJiri Olsa return -1; 209468d702f7SJiri Olsa } 209568d702f7SJiri Olsa aggr_get_id = perf_stat__get_core_file; 209668d702f7SJiri Olsa break; 209768d702f7SJiri Olsa case AGGR_NONE: 209868d702f7SJiri Olsa case AGGR_GLOBAL: 209968d702f7SJiri Olsa case AGGR_THREAD: 210068d702f7SJiri Olsa case AGGR_UNSET: 210168d702f7SJiri Olsa default: 210268d702f7SJiri Olsa break; 210368d702f7SJiri Olsa } 210468d702f7SJiri Olsa 210568d702f7SJiri Olsa return 0; 210668d702f7SJiri Olsa } 210768d702f7SJiri Olsa 210844b1e60aSAndi Kleen static int topdown_filter_events(const char **attr, char **str, bool use_group) 210944b1e60aSAndi Kleen { 211044b1e60aSAndi Kleen int off = 0; 211144b1e60aSAndi Kleen int i; 211244b1e60aSAndi Kleen int len = 0; 211344b1e60aSAndi Kleen char *s; 211444b1e60aSAndi Kleen 211544b1e60aSAndi Kleen for (i = 0; attr[i]; i++) { 211644b1e60aSAndi Kleen if (pmu_have_event("cpu", attr[i])) { 211744b1e60aSAndi Kleen len += strlen(attr[i]) + 1; 211844b1e60aSAndi Kleen attr[i - off] = attr[i]; 211944b1e60aSAndi Kleen } else 212044b1e60aSAndi Kleen off++; 212144b1e60aSAndi Kleen } 212244b1e60aSAndi Kleen attr[i - off] = NULL; 212344b1e60aSAndi Kleen 212444b1e60aSAndi Kleen *str = malloc(len + 1 + 2); 212544b1e60aSAndi Kleen if (!*str) 212644b1e60aSAndi Kleen return -1; 212744b1e60aSAndi Kleen s = *str; 212844b1e60aSAndi Kleen if (i - off == 0) { 212944b1e60aSAndi Kleen *s = 0; 213044b1e60aSAndi Kleen return 0; 213144b1e60aSAndi Kleen } 213244b1e60aSAndi Kleen if (use_group) 213344b1e60aSAndi Kleen *s++ = '{'; 213444b1e60aSAndi Kleen for (i = 0; attr[i]; i++) { 213544b1e60aSAndi Kleen strcpy(s, attr[i]); 213644b1e60aSAndi Kleen s += strlen(s); 213744b1e60aSAndi Kleen *s++ = ','; 213844b1e60aSAndi Kleen } 213944b1e60aSAndi Kleen if (use_group) { 214044b1e60aSAndi Kleen s[-1] = '}'; 214144b1e60aSAndi Kleen *s = 0; 214244b1e60aSAndi Kleen } else 214344b1e60aSAndi Kleen s[-1] = 0; 214444b1e60aSAndi Kleen return 0; 214544b1e60aSAndi Kleen } 214644b1e60aSAndi Kleen 214744b1e60aSAndi Kleen __weak bool arch_topdown_check_group(bool *warn) 214844b1e60aSAndi Kleen { 214944b1e60aSAndi Kleen *warn = false; 215044b1e60aSAndi Kleen return false; 215144b1e60aSAndi Kleen } 215244b1e60aSAndi Kleen 215344b1e60aSAndi Kleen __weak void arch_topdown_group_warn(void) 215444b1e60aSAndi Kleen { 215544b1e60aSAndi Kleen } 215644b1e60aSAndi Kleen 21572cba3ffbSIngo Molnar /* 21582cba3ffbSIngo Molnar * Add default attributes, if there were no attributes specified or 21592cba3ffbSIngo Molnar * if -d/--detailed, -d -d or -d -d -d is used: 21602cba3ffbSIngo Molnar */ 21612cba3ffbSIngo Molnar static int add_default_attributes(void) 21622cba3ffbSIngo Molnar { 216344b1e60aSAndi Kleen int err; 21649dec4473SAndi Kleen struct perf_event_attr default_attrs0[] = { 2165b070a547SArnaldo Carvalho de Melo 2166b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 2167b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES }, 2168b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 2169b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 2170b070a547SArnaldo Carvalho de Melo 2171b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 21729dec4473SAndi Kleen }; 21739dec4473SAndi Kleen struct perf_event_attr frontend_attrs[] = { 2174b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 21759dec4473SAndi Kleen }; 21769dec4473SAndi Kleen struct perf_event_attr backend_attrs[] = { 2177b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 21789dec4473SAndi Kleen }; 21799dec4473SAndi Kleen struct perf_event_attr default_attrs1[] = { 2180b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 2181b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 2182b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 2183b070a547SArnaldo Carvalho de Melo 2184b070a547SArnaldo Carvalho de Melo }; 2185b070a547SArnaldo Carvalho de Melo 2186b070a547SArnaldo Carvalho de Melo /* 2187b070a547SArnaldo Carvalho de Melo * Detailed stats (-d), covering the L1 and last level data caches: 2188b070a547SArnaldo Carvalho de Melo */ 2189b070a547SArnaldo Carvalho de Melo struct perf_event_attr detailed_attrs[] = { 2190b070a547SArnaldo Carvalho de Melo 2191b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2192b070a547SArnaldo Carvalho de Melo .config = 2193b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 2194b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2195b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 2196b070a547SArnaldo Carvalho de Melo 2197b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2198b070a547SArnaldo Carvalho de Melo .config = 2199b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 2200b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2201b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2202b070a547SArnaldo Carvalho de Melo 2203b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2204b070a547SArnaldo Carvalho de Melo .config = 2205b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_LL << 0 | 2206b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2207b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 2208b070a547SArnaldo Carvalho de Melo 2209b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2210b070a547SArnaldo Carvalho de Melo .config = 2211b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_LL << 0 | 2212b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2213b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2214b070a547SArnaldo Carvalho de Melo }; 2215b070a547SArnaldo Carvalho de Melo 2216b070a547SArnaldo Carvalho de Melo /* 2217b070a547SArnaldo Carvalho de Melo * Very detailed stats (-d -d), covering the instruction cache and the TLB caches: 2218b070a547SArnaldo Carvalho de Melo */ 2219b070a547SArnaldo Carvalho de Melo struct perf_event_attr very_detailed_attrs[] = { 2220b070a547SArnaldo Carvalho de Melo 2221b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2222b070a547SArnaldo Carvalho de Melo .config = 2223b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1I << 0 | 2224b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2225b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 2226b070a547SArnaldo Carvalho de Melo 2227b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2228b070a547SArnaldo Carvalho de Melo .config = 2229b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1I << 0 | 2230b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2231b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2232b070a547SArnaldo Carvalho de Melo 2233b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2234b070a547SArnaldo Carvalho de Melo .config = 2235b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_DTLB << 0 | 2236b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2237b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 2238b070a547SArnaldo Carvalho de Melo 2239b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2240b070a547SArnaldo Carvalho de Melo .config = 2241b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_DTLB << 0 | 2242b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2243b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2244b070a547SArnaldo Carvalho de Melo 2245b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2246b070a547SArnaldo Carvalho de Melo .config = 2247b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_ITLB << 0 | 2248b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2249b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 2250b070a547SArnaldo Carvalho de Melo 2251b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2252b070a547SArnaldo Carvalho de Melo .config = 2253b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_ITLB << 0 | 2254b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 2255b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2256b070a547SArnaldo Carvalho de Melo 2257b070a547SArnaldo Carvalho de Melo }; 2258b070a547SArnaldo Carvalho de Melo 2259b070a547SArnaldo Carvalho de Melo /* 2260b070a547SArnaldo Carvalho de Melo * Very, very detailed stats (-d -d -d), adding prefetch events: 2261b070a547SArnaldo Carvalho de Melo */ 2262b070a547SArnaldo Carvalho de Melo struct perf_event_attr very_very_detailed_attrs[] = { 2263b070a547SArnaldo Carvalho de Melo 2264b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2265b070a547SArnaldo Carvalho de Melo .config = 2266b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 2267b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 2268b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 2269b070a547SArnaldo Carvalho de Melo 2270b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 2271b070a547SArnaldo Carvalho de Melo .config = 2272b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 2273b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 2274b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 2275b070a547SArnaldo Carvalho de Melo }; 2276a5cfa621SJiri Olsa struct parse_events_error errinfo; 2277b070a547SArnaldo Carvalho de Melo 22782cba3ffbSIngo Molnar /* Set attrs if no event is selected and !null_run: */ 22792cba3ffbSIngo Molnar if (null_run) 22802cba3ffbSIngo Molnar return 0; 22812cba3ffbSIngo Molnar 22824cabc3d1SAndi Kleen if (transaction_run) { 2283742d92ffSThomas Richter /* Handle -T as -M transaction. Once platform specific metrics 2284742d92ffSThomas Richter * support has been added to the json files, all archictures 2285742d92ffSThomas Richter * will use this approach. To determine transaction support 2286742d92ffSThomas Richter * on an architecture test for such a metric name. 2287742d92ffSThomas Richter */ 2288742d92ffSThomas Richter if (metricgroup__has_metric("transaction")) { 2289742d92ffSThomas Richter struct option opt = { .value = &evsel_list }; 2290742d92ffSThomas Richter 2291742d92ffSThomas Richter return metricgroup__parse_groups(&opt, "transaction", 2292742d92ffSThomas Richter &metric_events); 2293742d92ffSThomas Richter } 2294742d92ffSThomas Richter 22954cabc3d1SAndi Kleen if (pmu_have_event("cpu", "cycles-ct") && 22964cabc3d1SAndi Kleen pmu_have_event("cpu", "el-start")) 2297fca32340SThomas Richter err = parse_events(evsel_list, transaction_attrs, 2298fca32340SThomas Richter &errinfo); 22994cabc3d1SAndi Kleen else 2300fca32340SThomas Richter err = parse_events(evsel_list, 2301fca32340SThomas Richter transaction_limited_attrs, 2302fca32340SThomas Richter &errinfo); 2303a454742cSJiri Olsa if (err) { 23044cabc3d1SAndi Kleen fprintf(stderr, "Cannot set up transaction events\n"); 2305a5cfa621SJiri Olsa parse_events_print_error(&errinfo, transaction_attrs); 23064cabc3d1SAndi Kleen return -1; 23074cabc3d1SAndi Kleen } 23084cabc3d1SAndi Kleen return 0; 23094cabc3d1SAndi Kleen } 23104cabc3d1SAndi Kleen 2311daefd0bcSKan Liang if (smi_cost) { 2312daefd0bcSKan Liang int smi; 2313daefd0bcSKan Liang 2314daefd0bcSKan Liang if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) { 2315daefd0bcSKan Liang fprintf(stderr, "freeze_on_smi is not supported.\n"); 2316daefd0bcSKan Liang return -1; 2317daefd0bcSKan Liang } 2318daefd0bcSKan Liang 2319daefd0bcSKan Liang if (!smi) { 2320daefd0bcSKan Liang if (sysfs__write_int(FREEZE_ON_SMI_PATH, 1) < 0) { 2321daefd0bcSKan Liang fprintf(stderr, "Failed to set freeze_on_smi.\n"); 2322daefd0bcSKan Liang return -1; 2323daefd0bcSKan Liang } 2324daefd0bcSKan Liang smi_reset = true; 2325daefd0bcSKan Liang } 2326daefd0bcSKan Liang 2327daefd0bcSKan Liang if (pmu_have_event("msr", "aperf") && 2328daefd0bcSKan Liang pmu_have_event("msr", "smi")) { 2329daefd0bcSKan Liang if (!force_metric_only) 2330daefd0bcSKan Liang metric_only = true; 2331a5cfa621SJiri Olsa err = parse_events(evsel_list, smi_cost_attrs, &errinfo); 2332daefd0bcSKan Liang } else { 2333daefd0bcSKan Liang fprintf(stderr, "To measure SMI cost, it needs " 2334daefd0bcSKan Liang "msr/aperf/, msr/smi/ and cpu/cycles/ support\n"); 2335a5cfa621SJiri Olsa parse_events_print_error(&errinfo, smi_cost_attrs); 2336daefd0bcSKan Liang return -1; 2337daefd0bcSKan Liang } 2338daefd0bcSKan Liang if (err) { 2339daefd0bcSKan Liang fprintf(stderr, "Cannot set up SMI cost events\n"); 2340daefd0bcSKan Liang return -1; 2341daefd0bcSKan Liang } 2342daefd0bcSKan Liang return 0; 2343daefd0bcSKan Liang } 2344daefd0bcSKan Liang 234544b1e60aSAndi Kleen if (topdown_run) { 234644b1e60aSAndi Kleen char *str = NULL; 234744b1e60aSAndi Kleen bool warn = false; 234844b1e60aSAndi Kleen 234944b1e60aSAndi Kleen if (stat_config.aggr_mode != AGGR_GLOBAL && 235044b1e60aSAndi Kleen stat_config.aggr_mode != AGGR_CORE) { 235144b1e60aSAndi Kleen pr_err("top down event configuration requires --per-core mode\n"); 235244b1e60aSAndi Kleen return -1; 235344b1e60aSAndi Kleen } 235444b1e60aSAndi Kleen stat_config.aggr_mode = AGGR_CORE; 235544b1e60aSAndi Kleen if (nr_cgroups || !target__has_cpu(&target)) { 235644b1e60aSAndi Kleen pr_err("top down event configuration requires system-wide mode (-a)\n"); 235744b1e60aSAndi Kleen return -1; 235844b1e60aSAndi Kleen } 235944b1e60aSAndi Kleen 236044b1e60aSAndi Kleen if (!force_metric_only) 236144b1e60aSAndi Kleen metric_only = true; 236244b1e60aSAndi Kleen if (topdown_filter_events(topdown_attrs, &str, 236344b1e60aSAndi Kleen arch_topdown_check_group(&warn)) < 0) { 236444b1e60aSAndi Kleen pr_err("Out of memory\n"); 236544b1e60aSAndi Kleen return -1; 236644b1e60aSAndi Kleen } 236744b1e60aSAndi Kleen if (topdown_attrs[0] && str) { 236844b1e60aSAndi Kleen if (warn) 236944b1e60aSAndi Kleen arch_topdown_group_warn(); 2370a5cfa621SJiri Olsa err = parse_events(evsel_list, str, &errinfo); 237144b1e60aSAndi Kleen if (err) { 237244b1e60aSAndi Kleen fprintf(stderr, 237344b1e60aSAndi Kleen "Cannot set up top down events %s: %d\n", 237444b1e60aSAndi Kleen str, err); 237544b1e60aSAndi Kleen free(str); 2376a5cfa621SJiri Olsa parse_events_print_error(&errinfo, str); 237744b1e60aSAndi Kleen return -1; 237844b1e60aSAndi Kleen } 237944b1e60aSAndi Kleen } else { 238044b1e60aSAndi Kleen fprintf(stderr, "System does not support topdown\n"); 238144b1e60aSAndi Kleen return -1; 238244b1e60aSAndi Kleen } 238344b1e60aSAndi Kleen free(str); 238444b1e60aSAndi Kleen } 238544b1e60aSAndi Kleen 23862cba3ffbSIngo Molnar if (!evsel_list->nr_entries) { 2387a1f3d567SNamhyung Kim if (target__has_cpu(&target)) 2388a1f3d567SNamhyung Kim default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; 2389a1f3d567SNamhyung Kim 23909dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) 23919dec4473SAndi Kleen return -1; 23929dec4473SAndi Kleen if (pmu_have_event("cpu", "stalled-cycles-frontend")) { 23939dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, 23949dec4473SAndi Kleen frontend_attrs) < 0) 23959dec4473SAndi Kleen return -1; 23969dec4473SAndi Kleen } 23979dec4473SAndi Kleen if (pmu_have_event("cpu", "stalled-cycles-backend")) { 23989dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, 23999dec4473SAndi Kleen backend_attrs) < 0) 24009dec4473SAndi Kleen return -1; 24019dec4473SAndi Kleen } 24029dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0) 24032cba3ffbSIngo Molnar return -1; 24042cba3ffbSIngo Molnar } 24052cba3ffbSIngo Molnar 24062cba3ffbSIngo Molnar /* Detailed events get appended to the event list: */ 24072cba3ffbSIngo Molnar 24082cba3ffbSIngo Molnar if (detailed_run < 1) 24092cba3ffbSIngo Molnar return 0; 24102cba3ffbSIngo Molnar 24112cba3ffbSIngo Molnar /* Append detailed run extra attributes: */ 241279695e1bSArnaldo Carvalho de Melo if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) 24132cba3ffbSIngo Molnar return -1; 24142cba3ffbSIngo Molnar 24152cba3ffbSIngo Molnar if (detailed_run < 2) 24162cba3ffbSIngo Molnar return 0; 24172cba3ffbSIngo Molnar 24182cba3ffbSIngo Molnar /* Append very detailed run extra attributes: */ 241979695e1bSArnaldo Carvalho de Melo if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) 24202cba3ffbSIngo Molnar return -1; 24212cba3ffbSIngo Molnar 24222cba3ffbSIngo Molnar if (detailed_run < 3) 24232cba3ffbSIngo Molnar return 0; 24242cba3ffbSIngo Molnar 24252cba3ffbSIngo Molnar /* Append very, very detailed run extra attributes: */ 242679695e1bSArnaldo Carvalho de Melo return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 24272cba3ffbSIngo Molnar } 24282cba3ffbSIngo Molnar 24298a59f3ccSJiri Olsa static const char * const stat_record_usage[] = { 24304979d0c7SJiri Olsa "perf stat record [<options>]", 24314979d0c7SJiri Olsa NULL, 24324979d0c7SJiri Olsa }; 24334979d0c7SJiri Olsa 24343ba78bd0SJiri Olsa static void init_features(struct perf_session *session) 24353ba78bd0SJiri Olsa { 24363ba78bd0SJiri Olsa int feat; 24373ba78bd0SJiri Olsa 24383ba78bd0SJiri Olsa for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 24393ba78bd0SJiri Olsa perf_header__set_feat(&session->header, feat); 24403ba78bd0SJiri Olsa 24413ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 24423ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 24433ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 24443ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 24453ba78bd0SJiri Olsa } 24463ba78bd0SJiri Olsa 24474979d0c7SJiri Olsa static int __cmd_record(int argc, const char **argv) 24484979d0c7SJiri Olsa { 24494979d0c7SJiri Olsa struct perf_session *session; 24508ceb41d7SJiri Olsa struct perf_data *data = &perf_stat.data; 24514979d0c7SJiri Olsa 24528a59f3ccSJiri Olsa argc = parse_options(argc, argv, stat_options, stat_record_usage, 24534979d0c7SJiri Olsa PARSE_OPT_STOP_AT_NON_OPTION); 24544979d0c7SJiri Olsa 24554979d0c7SJiri Olsa if (output_name) 2456eae8ad80SJiri Olsa data->file.path = output_name; 24574979d0c7SJiri Olsa 2458e9d6db8eSJiri Olsa if (run_count != 1 || forever) { 2459e9d6db8eSJiri Olsa pr_err("Cannot use -r option with perf stat record.\n"); 2460e9d6db8eSJiri Olsa return -1; 2461e9d6db8eSJiri Olsa } 2462e9d6db8eSJiri Olsa 24638ceb41d7SJiri Olsa session = perf_session__new(data, false, NULL); 24644979d0c7SJiri Olsa if (session == NULL) { 24654979d0c7SJiri Olsa pr_err("Perf session creation failed.\n"); 24664979d0c7SJiri Olsa return -1; 24674979d0c7SJiri Olsa } 24684979d0c7SJiri Olsa 24693ba78bd0SJiri Olsa init_features(session); 24703ba78bd0SJiri Olsa 24714979d0c7SJiri Olsa session->evlist = evsel_list; 24724979d0c7SJiri Olsa perf_stat.session = session; 24734979d0c7SJiri Olsa perf_stat.record = true; 24744979d0c7SJiri Olsa return argc; 24754979d0c7SJiri Olsa } 24764979d0c7SJiri Olsa 2477a56f9390SJiri Olsa static int process_stat_round_event(struct perf_tool *tool __maybe_unused, 2478a56f9390SJiri Olsa union perf_event *event, 2479a56f9390SJiri Olsa struct perf_session *session) 2480a56f9390SJiri Olsa { 2481e3b03b6cSAndi Kleen struct stat_round_event *stat_round = &event->stat_round; 2482a56f9390SJiri Olsa struct perf_evsel *counter; 2483a56f9390SJiri Olsa struct timespec tsh, *ts = NULL; 2484a56f9390SJiri Olsa const char **argv = session->header.env.cmdline_argv; 2485a56f9390SJiri Olsa int argc = session->header.env.nr_cmdline; 2486a56f9390SJiri Olsa 2487e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) 2488a56f9390SJiri Olsa perf_stat_process_counter(&stat_config, counter); 2489a56f9390SJiri Olsa 2490e3b03b6cSAndi Kleen if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) 2491e3b03b6cSAndi Kleen update_stats(&walltime_nsecs_stats, stat_round->time); 2492a56f9390SJiri Olsa 2493e3b03b6cSAndi Kleen if (stat_config.interval && stat_round->time) { 2494bd48c63eSArnaldo Carvalho de Melo tsh.tv_sec = stat_round->time / NSEC_PER_SEC; 2495bd48c63eSArnaldo Carvalho de Melo tsh.tv_nsec = stat_round->time % NSEC_PER_SEC; 2496a56f9390SJiri Olsa ts = &tsh; 2497a56f9390SJiri Olsa } 2498a56f9390SJiri Olsa 2499a56f9390SJiri Olsa print_counters(ts, argc, argv); 2500a56f9390SJiri Olsa return 0; 2501a56f9390SJiri Olsa } 2502a56f9390SJiri Olsa 250362ba18baSJiri Olsa static 25047e6a7998SArnaldo Carvalho de Melo int process_stat_config_event(struct perf_tool *tool, 250562ba18baSJiri Olsa union perf_event *event, 250662ba18baSJiri Olsa struct perf_session *session __maybe_unused) 250762ba18baSJiri Olsa { 250868d702f7SJiri Olsa struct perf_stat *st = container_of(tool, struct perf_stat, tool); 250968d702f7SJiri Olsa 251062ba18baSJiri Olsa perf_event__read_stat_config(&stat_config, &event->stat_config); 251168d702f7SJiri Olsa 251289af4e05SJiri Olsa if (cpu_map__empty(st->cpus)) { 251389af4e05SJiri Olsa if (st->aggr_mode != AGGR_UNSET) 251489af4e05SJiri Olsa pr_warning("warning: processing task data, aggregation mode not set\n"); 251589af4e05SJiri Olsa return 0; 251689af4e05SJiri Olsa } 251789af4e05SJiri Olsa 251889af4e05SJiri Olsa if (st->aggr_mode != AGGR_UNSET) 251989af4e05SJiri Olsa stat_config.aggr_mode = st->aggr_mode; 252089af4e05SJiri Olsa 25218ceb41d7SJiri Olsa if (perf_stat.data.is_pipe) 252268d702f7SJiri Olsa perf_stat_init_aggr_mode(); 252368d702f7SJiri Olsa else 252468d702f7SJiri Olsa perf_stat_init_aggr_mode_file(st); 252568d702f7SJiri Olsa 252662ba18baSJiri Olsa return 0; 252762ba18baSJiri Olsa } 252862ba18baSJiri Olsa 25291975d36eSJiri Olsa static int set_maps(struct perf_stat *st) 25301975d36eSJiri Olsa { 25311975d36eSJiri Olsa if (!st->cpus || !st->threads) 25321975d36eSJiri Olsa return 0; 25331975d36eSJiri Olsa 25341975d36eSJiri Olsa if (WARN_ONCE(st->maps_allocated, "stats double allocation\n")) 25351975d36eSJiri Olsa return -EINVAL; 25361975d36eSJiri Olsa 25371975d36eSJiri Olsa perf_evlist__set_maps(evsel_list, st->cpus, st->threads); 25381975d36eSJiri Olsa 25391975d36eSJiri Olsa if (perf_evlist__alloc_stats(evsel_list, true)) 25401975d36eSJiri Olsa return -ENOMEM; 25411975d36eSJiri Olsa 25421975d36eSJiri Olsa st->maps_allocated = true; 25431975d36eSJiri Olsa return 0; 25441975d36eSJiri Olsa } 25451975d36eSJiri Olsa 25461975d36eSJiri Olsa static 25477e6a7998SArnaldo Carvalho de Melo int process_thread_map_event(struct perf_tool *tool, 25481975d36eSJiri Olsa union perf_event *event, 25491975d36eSJiri Olsa struct perf_session *session __maybe_unused) 25501975d36eSJiri Olsa { 25511975d36eSJiri Olsa struct perf_stat *st = container_of(tool, struct perf_stat, tool); 25521975d36eSJiri Olsa 25531975d36eSJiri Olsa if (st->threads) { 25541975d36eSJiri Olsa pr_warning("Extra thread map event, ignoring.\n"); 25551975d36eSJiri Olsa return 0; 25561975d36eSJiri Olsa } 25571975d36eSJiri Olsa 25581975d36eSJiri Olsa st->threads = thread_map__new_event(&event->thread_map); 25591975d36eSJiri Olsa if (!st->threads) 25601975d36eSJiri Olsa return -ENOMEM; 25611975d36eSJiri Olsa 25621975d36eSJiri Olsa return set_maps(st); 25631975d36eSJiri Olsa } 25641975d36eSJiri Olsa 25651975d36eSJiri Olsa static 25667e6a7998SArnaldo Carvalho de Melo int process_cpu_map_event(struct perf_tool *tool, 25671975d36eSJiri Olsa union perf_event *event, 25681975d36eSJiri Olsa struct perf_session *session __maybe_unused) 25691975d36eSJiri Olsa { 25701975d36eSJiri Olsa struct perf_stat *st = container_of(tool, struct perf_stat, tool); 25711975d36eSJiri Olsa struct cpu_map *cpus; 25721975d36eSJiri Olsa 25731975d36eSJiri Olsa if (st->cpus) { 25741975d36eSJiri Olsa pr_warning("Extra cpu map event, ignoring.\n"); 25751975d36eSJiri Olsa return 0; 25761975d36eSJiri Olsa } 25771975d36eSJiri Olsa 25781975d36eSJiri Olsa cpus = cpu_map__new_data(&event->cpu_map.data); 25791975d36eSJiri Olsa if (!cpus) 25801975d36eSJiri Olsa return -ENOMEM; 25811975d36eSJiri Olsa 25821975d36eSJiri Olsa st->cpus = cpus; 25831975d36eSJiri Olsa return set_maps(st); 25841975d36eSJiri Olsa } 25851975d36eSJiri Olsa 258656739444SJin Yao static int runtime_stat_new(struct perf_stat_config *config, int nthreads) 258756739444SJin Yao { 258856739444SJin Yao int i; 258956739444SJin Yao 259056739444SJin Yao config->stats = calloc(nthreads, sizeof(struct runtime_stat)); 259156739444SJin Yao if (!config->stats) 259256739444SJin Yao return -1; 259356739444SJin Yao 259456739444SJin Yao config->stats_num = nthreads; 259556739444SJin Yao 259656739444SJin Yao for (i = 0; i < nthreads; i++) 259756739444SJin Yao runtime_stat__init(&config->stats[i]); 259856739444SJin Yao 259956739444SJin Yao return 0; 260056739444SJin Yao } 260156739444SJin Yao 260256739444SJin Yao static void runtime_stat_delete(struct perf_stat_config *config) 260356739444SJin Yao { 260456739444SJin Yao int i; 260556739444SJin Yao 260656739444SJin Yao if (!config->stats) 260756739444SJin Yao return; 260856739444SJin Yao 260956739444SJin Yao for (i = 0; i < config->stats_num; i++) 261056739444SJin Yao runtime_stat__exit(&config->stats[i]); 261156739444SJin Yao 261256739444SJin Yao free(config->stats); 261356739444SJin Yao } 261456739444SJin Yao 26158a59f3ccSJiri Olsa static const char * const stat_report_usage[] = { 2616ba6039b6SJiri Olsa "perf stat report [<options>]", 2617ba6039b6SJiri Olsa NULL, 2618ba6039b6SJiri Olsa }; 2619ba6039b6SJiri Olsa 2620ba6039b6SJiri Olsa static struct perf_stat perf_stat = { 2621ba6039b6SJiri Olsa .tool = { 2622ba6039b6SJiri Olsa .attr = perf_event__process_attr, 2623fa6ea781SJiri Olsa .event_update = perf_event__process_event_update, 26241975d36eSJiri Olsa .thread_map = process_thread_map_event, 26251975d36eSJiri Olsa .cpu_map = process_cpu_map_event, 262662ba18baSJiri Olsa .stat_config = process_stat_config_event, 2627a56f9390SJiri Olsa .stat = perf_event__process_stat_event, 2628a56f9390SJiri Olsa .stat_round = process_stat_round_event, 2629ba6039b6SJiri Olsa }, 263089af4e05SJiri Olsa .aggr_mode = AGGR_UNSET, 2631ba6039b6SJiri Olsa }; 2632ba6039b6SJiri Olsa 2633ba6039b6SJiri Olsa static int __cmd_report(int argc, const char **argv) 2634ba6039b6SJiri Olsa { 2635ba6039b6SJiri Olsa struct perf_session *session; 2636ba6039b6SJiri Olsa const struct option options[] = { 2637ba6039b6SJiri Olsa OPT_STRING('i', "input", &input_name, "file", "input file name"), 263889af4e05SJiri Olsa OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode, 263989af4e05SJiri Olsa "aggregate counts per processor socket", AGGR_SOCKET), 264089af4e05SJiri Olsa OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode, 264189af4e05SJiri Olsa "aggregate counts per physical processor core", AGGR_CORE), 264289af4e05SJiri Olsa OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode, 264389af4e05SJiri Olsa "disable CPU count aggregation", AGGR_NONE), 2644ba6039b6SJiri Olsa OPT_END() 2645ba6039b6SJiri Olsa }; 2646ba6039b6SJiri Olsa struct stat st; 2647ba6039b6SJiri Olsa int ret; 2648ba6039b6SJiri Olsa 26498a59f3ccSJiri Olsa argc = parse_options(argc, argv, options, stat_report_usage, 0); 2650ba6039b6SJiri Olsa 2651ba6039b6SJiri Olsa if (!input_name || !strlen(input_name)) { 2652ba6039b6SJiri Olsa if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 2653ba6039b6SJiri Olsa input_name = "-"; 2654ba6039b6SJiri Olsa else 2655ba6039b6SJiri Olsa input_name = "perf.data"; 2656ba6039b6SJiri Olsa } 2657ba6039b6SJiri Olsa 2658eae8ad80SJiri Olsa perf_stat.data.file.path = input_name; 26598ceb41d7SJiri Olsa perf_stat.data.mode = PERF_DATA_MODE_READ; 2660ba6039b6SJiri Olsa 26618ceb41d7SJiri Olsa session = perf_session__new(&perf_stat.data, false, &perf_stat.tool); 2662ba6039b6SJiri Olsa if (session == NULL) 2663ba6039b6SJiri Olsa return -1; 2664ba6039b6SJiri Olsa 2665ba6039b6SJiri Olsa perf_stat.session = session; 2666ba6039b6SJiri Olsa stat_config.output = stderr; 2667ba6039b6SJiri Olsa evsel_list = session->evlist; 2668ba6039b6SJiri Olsa 2669ba6039b6SJiri Olsa ret = perf_session__process_events(session); 2670ba6039b6SJiri Olsa if (ret) 2671ba6039b6SJiri Olsa return ret; 2672ba6039b6SJiri Olsa 2673ba6039b6SJiri Olsa perf_session__delete(session); 2674ba6039b6SJiri Olsa return 0; 2675ba6039b6SJiri Olsa } 2676ba6039b6SJiri Olsa 2677e3ba76deSJiri Olsa static void setup_system_wide(int forks) 2678e3ba76deSJiri Olsa { 2679e3ba76deSJiri Olsa /* 2680e3ba76deSJiri Olsa * Make system wide (-a) the default target if 2681e3ba76deSJiri Olsa * no target was specified and one of following 2682e3ba76deSJiri Olsa * conditions is met: 2683e3ba76deSJiri Olsa * 2684e3ba76deSJiri Olsa * - there's no workload specified 2685e3ba76deSJiri Olsa * - there is workload specified but all requested 2686e3ba76deSJiri Olsa * events are system wide events 2687e3ba76deSJiri Olsa */ 2688e3ba76deSJiri Olsa if (!target__none(&target)) 2689e3ba76deSJiri Olsa return; 2690e3ba76deSJiri Olsa 2691e3ba76deSJiri Olsa if (!forks) 2692e3ba76deSJiri Olsa target.system_wide = true; 2693e3ba76deSJiri Olsa else { 2694e3ba76deSJiri Olsa struct perf_evsel *counter; 2695e3ba76deSJiri Olsa 2696e3ba76deSJiri Olsa evlist__for_each_entry(evsel_list, counter) { 2697e3ba76deSJiri Olsa if (!counter->system_wide) 2698e3ba76deSJiri Olsa return; 2699e3ba76deSJiri Olsa } 2700e3ba76deSJiri Olsa 2701e3ba76deSJiri Olsa if (evsel_list->nr_entries) 2702e3ba76deSJiri Olsa target.system_wide = true; 2703e3ba76deSJiri Olsa } 2704e3ba76deSJiri Olsa } 2705e3ba76deSJiri Olsa 2706b0ad8ea6SArnaldo Carvalho de Melo int cmd_stat(int argc, const char **argv) 270786470930SIngo Molnar { 2708b070a547SArnaldo Carvalho de Melo const char * const stat_usage[] = { 2709b070a547SArnaldo Carvalho de Melo "perf stat [<options>] [<command>]", 2710b070a547SArnaldo Carvalho de Melo NULL 2711b070a547SArnaldo Carvalho de Melo }; 2712cc03c542SNamhyung Kim int status = -EINVAL, run_idx; 27134aa9015fSStephane Eranian const char *mode; 27145821522eSJiri Olsa FILE *output = stderr; 2715f1f8ad52Syuzhoujian unsigned int interval, timeout; 2716ba6039b6SJiri Olsa const char * const stat_subcommands[] = { "record", "report" }; 271742202dd5SIngo Molnar 27185af52b51SStephane Eranian setlocale(LC_ALL, ""); 27195af52b51SStephane Eranian 2720334fe7a3SNamhyung Kim evsel_list = perf_evlist__new(); 2721361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 2722361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 2723361c99a6SArnaldo Carvalho de Melo 27241669e509SWang Nan parse_events__shrink_config_terms(); 27254979d0c7SJiri Olsa argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands, 27264979d0c7SJiri Olsa (const char **) stat_usage, 2727a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 272837932c18SAndi Kleen perf_stat__collect_metric_expr(evsel_list); 2729fb4605baSAndi Kleen perf_stat__init_shadow_stats(); 2730d7470b6aSStephane Eranian 27316edb78a2SJiri Olsa if (csv_sep) { 27326edb78a2SJiri Olsa csv_output = true; 27336edb78a2SJiri Olsa if (!strcmp(csv_sep, "\\t")) 27346edb78a2SJiri Olsa csv_sep = "\t"; 27356edb78a2SJiri Olsa } else 27366edb78a2SJiri Olsa csv_sep = DEFAULT_SEPARATOR; 27376edb78a2SJiri Olsa 27384979d0c7SJiri Olsa if (argc && !strncmp(argv[0], "rec", 3)) { 27394979d0c7SJiri Olsa argc = __cmd_record(argc, argv); 27404979d0c7SJiri Olsa if (argc < 0) 27414979d0c7SJiri Olsa return -1; 2742ba6039b6SJiri Olsa } else if (argc && !strncmp(argv[0], "rep", 3)) 2743ba6039b6SJiri Olsa return __cmd_report(argc, argv); 27444979d0c7SJiri Olsa 2745ec0d3d1fSJiri Olsa interval = stat_config.interval; 2746f1f8ad52Syuzhoujian timeout = stat_config.timeout; 2747ec0d3d1fSJiri Olsa 27484979d0c7SJiri Olsa /* 27494979d0c7SJiri Olsa * For record command the -o is already taken care of. 27504979d0c7SJiri Olsa */ 27514979d0c7SJiri Olsa if (!STAT_RECORD && output_name && strcmp(output_name, "-")) 27524aa9015fSStephane Eranian output = NULL; 27534aa9015fSStephane Eranian 275456f3bae7SJim Cromie if (output_name && output_fd) { 275556f3bae7SJim Cromie fprintf(stderr, "cannot use both --output and --log-fd\n"); 2756e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "o", 1); 2757e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "log-fd", 0); 2758cc03c542SNamhyung Kim goto out; 275956f3bae7SJim Cromie } 2760fc3e4d07SStephane Eranian 276154b50916SAndi Kleen if (metric_only && stat_config.aggr_mode == AGGR_THREAD) { 276254b50916SAndi Kleen fprintf(stderr, "--metric-only is not supported with --per-thread\n"); 276354b50916SAndi Kleen goto out; 276454b50916SAndi Kleen } 276554b50916SAndi Kleen 276654b50916SAndi Kleen if (metric_only && run_count > 1) { 276754b50916SAndi Kleen fprintf(stderr, "--metric-only is not supported with -r\n"); 276854b50916SAndi Kleen goto out; 276954b50916SAndi Kleen } 277054b50916SAndi Kleen 2771e55c14afSJiri Olsa if (walltime_run_table && run_count <= 1) { 2772e55c14afSJiri Olsa fprintf(stderr, "--table is only supported with -r\n"); 2773e55c14afSJiri Olsa parse_options_usage(stat_usage, stat_options, "r", 1); 2774e55c14afSJiri Olsa parse_options_usage(NULL, stat_options, "table", 0); 2775e55c14afSJiri Olsa goto out; 2776e55c14afSJiri Olsa } 2777e55c14afSJiri Olsa 2778fc3e4d07SStephane Eranian if (output_fd < 0) { 2779fc3e4d07SStephane Eranian fprintf(stderr, "argument to --log-fd must be a > 0\n"); 2780e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "log-fd", 0); 2781cc03c542SNamhyung Kim goto out; 2782fc3e4d07SStephane Eranian } 2783fc3e4d07SStephane Eranian 27844aa9015fSStephane Eranian if (!output) { 27854aa9015fSStephane Eranian struct timespec tm; 27864aa9015fSStephane Eranian mode = append_file ? "a" : "w"; 27874aa9015fSStephane Eranian 27884aa9015fSStephane Eranian output = fopen(output_name, mode); 27894aa9015fSStephane Eranian if (!output) { 27904aa9015fSStephane Eranian perror("failed to create output file"); 2791fceda7feSDavid Ahern return -1; 27924aa9015fSStephane Eranian } 27934aa9015fSStephane Eranian clock_gettime(CLOCK_REALTIME, &tm); 27944aa9015fSStephane Eranian fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 2795fc3e4d07SStephane Eranian } else if (output_fd > 0) { 279656f3bae7SJim Cromie mode = append_file ? "a" : "w"; 279756f3bae7SJim Cromie output = fdopen(output_fd, mode); 279856f3bae7SJim Cromie if (!output) { 279956f3bae7SJim Cromie perror("Failed opening logfd"); 280056f3bae7SJim Cromie return -errno; 280156f3bae7SJim Cromie } 28024aa9015fSStephane Eranian } 28034aa9015fSStephane Eranian 28045821522eSJiri Olsa stat_config.output = output; 28055821522eSJiri Olsa 2806d7470b6aSStephane Eranian /* 2807d7470b6aSStephane Eranian * let the spreadsheet do the pretty-printing 2808d7470b6aSStephane Eranian */ 2809d7470b6aSStephane Eranian if (csv_output) { 281061a9f324SJim Cromie /* User explicitly passed -B? */ 2811d7470b6aSStephane Eranian if (big_num_opt == 1) { 2812d7470b6aSStephane Eranian fprintf(stderr, "-B option not supported with -x\n"); 2813e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "B", 1); 2814e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "x", 1); 2815cc03c542SNamhyung Kim goto out; 2816d7470b6aSStephane Eranian } else /* Nope, so disable big number formatting */ 2817d7470b6aSStephane Eranian big_num = false; 2818d7470b6aSStephane Eranian } else if (big_num_opt == 0) /* User passed --no-big-num */ 2819d7470b6aSStephane Eranian big_num = false; 2820d7470b6aSStephane Eranian 2821e3ba76deSJiri Olsa setup_system_wide(argc); 2822ac3063bdSDavid Ahern 28230ce2da14SJiri Olsa /* 28240ce2da14SJiri Olsa * Display user/system times only for single 28250ce2da14SJiri Olsa * run and when there's specified tracee. 28260ce2da14SJiri Olsa */ 28270ce2da14SJiri Olsa if ((run_count == 1) && target__none(&target)) 28280ce2da14SJiri Olsa ru_display = true; 28290ce2da14SJiri Olsa 2830a7e191c3SFrederik Deweerdt if (run_count < 0) { 2831cc03c542SNamhyung Kim pr_err("Run count must be a positive number\n"); 2832e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "r", 1); 2833cc03c542SNamhyung Kim goto out; 2834a7e191c3SFrederik Deweerdt } else if (run_count == 0) { 2835a7e191c3SFrederik Deweerdt forever = true; 2836a7e191c3SFrederik Deweerdt run_count = 1; 2837a7e191c3SFrederik Deweerdt } 283886470930SIngo Molnar 2839e55c14afSJiri Olsa if (walltime_run_table) { 2840e55c14afSJiri Olsa walltime_run = zalloc(run_count * sizeof(walltime_run[0])); 2841e55c14afSJiri Olsa if (!walltime_run) { 2842e55c14afSJiri Olsa pr_err("failed to setup -r option"); 2843e55c14afSJiri Olsa goto out; 2844e55c14afSJiri Olsa } 2845e55c14afSJiri Olsa } 2846e55c14afSJiri Olsa 28471d9f8d1bSJin Yao if ((stat_config.aggr_mode == AGGR_THREAD) && 28481d9f8d1bSJin Yao !target__has_task(&target)) { 28491d9f8d1bSJin Yao if (!target.system_wide || target.cpu_list) { 28501d9f8d1bSJin Yao fprintf(stderr, "The --per-thread option is only " 28511d9f8d1bSJin Yao "available when monitoring via -p -t -a " 28521d9f8d1bSJin Yao "options or only --per-thread.\n"); 2853e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "p", 1); 2854e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "t", 1); 285532b8af82SJiri Olsa goto out; 285632b8af82SJiri Olsa } 28571d9f8d1bSJin Yao } 285832b8af82SJiri Olsa 285932b8af82SJiri Olsa /* 286032b8af82SJiri Olsa * no_aggr, cgroup are for system-wide only 286132b8af82SJiri Olsa * --per-thread is aggregated per thread, we dont mix it with cpu mode 286232b8af82SJiri Olsa */ 2863421a50f3SJiri Olsa if (((stat_config.aggr_mode != AGGR_GLOBAL && 2864421a50f3SJiri Olsa stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) && 2865602ad878SArnaldo Carvalho de Melo !target__has_cpu(&target)) { 2866023695d9SStephane Eranian fprintf(stderr, "both cgroup and no-aggregation " 2867023695d9SStephane Eranian "modes only available in system-wide mode\n"); 2868023695d9SStephane Eranian 2869e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "G", 1); 2870e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "A", 1); 2871e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "a", 1); 2872cc03c542SNamhyung Kim goto out; 2873d7e7a451SStephane Eranian } 2874d7e7a451SStephane Eranian 28752cba3ffbSIngo Molnar if (add_default_attributes()) 2876c6264defSIngo Molnar goto out; 287786470930SIngo Molnar 2878602ad878SArnaldo Carvalho de Melo target__validate(&target); 28795c98d466SArnaldo Carvalho de Melo 28801d9f8d1bSJin Yao if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide)) 28811d9f8d1bSJin Yao target.per_thread = true; 28821d9f8d1bSJin Yao 288377a6f014SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &target) < 0) { 2884602ad878SArnaldo Carvalho de Melo if (target__has_task(&target)) { 28855c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 2886e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "p", 1); 2887e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "t", 1); 2888602ad878SArnaldo Carvalho de Melo } else if (target__has_cpu(&target)) { 288960d567e2SArnaldo Carvalho de Melo perror("failed to parse CPUs map"); 2890e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "C", 1); 2891e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "a", 1); 2892cc03c542SNamhyung Kim } 2893cc03c542SNamhyung Kim goto out; 289460d567e2SArnaldo Carvalho de Melo } 289532b8af82SJiri Olsa 289632b8af82SJiri Olsa /* 289732b8af82SJiri Olsa * Initialize thread_map with comm names, 289832b8af82SJiri Olsa * so we could print it out on output. 289932b8af82SJiri Olsa */ 290056739444SJin Yao if (stat_config.aggr_mode == AGGR_THREAD) { 290132b8af82SJiri Olsa thread_map__read_comms(evsel_list->threads); 290256739444SJin Yao if (target.system_wide) { 290356739444SJin Yao if (runtime_stat_new(&stat_config, 290456739444SJin Yao thread_map__nr(evsel_list->threads))) { 290556739444SJin Yao goto out; 290656739444SJin Yao } 290756739444SJin Yao } 290856739444SJin Yao } 290932b8af82SJiri Olsa 2910db06a269Syuzhoujian if (stat_config.times && interval) 2911db06a269Syuzhoujian interval_count = true; 2912db06a269Syuzhoujian else if (stat_config.times && !interval) { 2913db06a269Syuzhoujian pr_err("interval-count option should be used together with " 2914db06a269Syuzhoujian "interval-print.\n"); 2915db06a269Syuzhoujian parse_options_usage(stat_usage, stat_options, "interval-count", 0); 2916db06a269Syuzhoujian parse_options_usage(stat_usage, stat_options, "I", 1); 2917db06a269Syuzhoujian goto out; 2918db06a269Syuzhoujian } 2919c45c6ea2SStephane Eranian 2920f1f8ad52Syuzhoujian if (timeout && timeout < 100) { 2921f1f8ad52Syuzhoujian if (timeout < 10) { 2922f1f8ad52Syuzhoujian pr_err("timeout must be >= 10ms.\n"); 2923f1f8ad52Syuzhoujian parse_options_usage(stat_usage, stat_options, "timeout", 0); 2924f1f8ad52Syuzhoujian goto out; 2925f1f8ad52Syuzhoujian } else 2926f1f8ad52Syuzhoujian pr_warning("timeout < 100ms. " 2927f1f8ad52Syuzhoujian "The overhead percentage could be high in some cases. " 2928f1f8ad52Syuzhoujian "Please proceed with caution.\n"); 2929f1f8ad52Syuzhoujian } 2930f1f8ad52Syuzhoujian if (timeout && interval) { 2931f1f8ad52Syuzhoujian pr_err("timeout option is not supported with interval-print.\n"); 2932f1f8ad52Syuzhoujian parse_options_usage(stat_usage, stat_options, "timeout", 0); 2933f1f8ad52Syuzhoujian parse_options_usage(stat_usage, stat_options, "I", 1); 2934f1f8ad52Syuzhoujian goto out; 2935f1f8ad52Syuzhoujian } 2936f1f8ad52Syuzhoujian 2937d134ffb9SArnaldo Carvalho de Melo if (perf_evlist__alloc_stats(evsel_list, interval)) 293803ad9747SArnaldo Carvalho de Melo goto out; 2939d6d901c2SZhang, Yanmin 294086ee6e18SStephane Eranian if (perf_stat_init_aggr_mode()) 294103ad9747SArnaldo Carvalho de Melo goto out; 294286ee6e18SStephane Eranian 294386470930SIngo Molnar /* 29447d9ad16aSJiri Olsa * Set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless 29457d9ad16aSJiri Olsa * while avoiding that older tools show confusing messages. 29467d9ad16aSJiri Olsa * 29477d9ad16aSJiri Olsa * However for pipe sessions we need to keep it zero, 29487d9ad16aSJiri Olsa * because script's perf_evsel__check_attr is triggered 29497d9ad16aSJiri Olsa * by attr->sample_type != 0, and we can't run it on 29507d9ad16aSJiri Olsa * stat sessions. 29517d9ad16aSJiri Olsa */ 29527d9ad16aSJiri Olsa stat_config.identifier = !(STAT_RECORD && perf_stat.data.is_pipe); 29537d9ad16aSJiri Olsa 29547d9ad16aSJiri Olsa /* 295586470930SIngo Molnar * We dont want to block the signals - that would cause 295686470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 295786470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 295886470930SIngo Molnar * task, but being ignored by perf stat itself: 295986470930SIngo Molnar */ 2960f7b7c26eSPeter Zijlstra atexit(sig_atexit); 2961a7e191c3SFrederik Deweerdt if (!forever) 296286470930SIngo Molnar signal(SIGINT, skip_signal); 296313370a9bSStephane Eranian signal(SIGCHLD, skip_signal); 296486470930SIngo Molnar signal(SIGALRM, skip_signal); 296586470930SIngo Molnar signal(SIGABRT, skip_signal); 296686470930SIngo Molnar 296742202dd5SIngo Molnar status = 0; 2968a7e191c3SFrederik Deweerdt for (run_idx = 0; forever || run_idx < run_count; run_idx++) { 2969bb963e16SNamhyung Kim if (run_count != 1 && verbose > 0) 29704aa9015fSStephane Eranian fprintf(output, "[ perf stat: executing run #%d ... ]\n", 29714aa9015fSStephane Eranian run_idx + 1); 2972f9cef0a9SIngo Molnar 2973e55c14afSJiri Olsa status = run_perf_stat(argc, argv, run_idx); 2974a7e191c3SFrederik Deweerdt if (forever && status != -1) { 2975d4f63a47SJiri Olsa print_counters(NULL, argc, argv); 2976254ecbc7SJiri Olsa perf_stat__reset_stats(); 2977a7e191c3SFrederik Deweerdt } 297842202dd5SIngo Molnar } 297942202dd5SIngo Molnar 2980a7e191c3SFrederik Deweerdt if (!forever && status != -1 && !interval) 2981d4f63a47SJiri Olsa print_counters(NULL, argc, argv); 2982d134ffb9SArnaldo Carvalho de Melo 29834979d0c7SJiri Olsa if (STAT_RECORD) { 29844979d0c7SJiri Olsa /* 29854979d0c7SJiri Olsa * We synthesize the kernel mmap record just so that older tools 29864979d0c7SJiri Olsa * don't emit warnings about not being able to resolve symbols 29874979d0c7SJiri Olsa * due to /proc/sys/kernel/kptr_restrict settings and instear provide 29884979d0c7SJiri Olsa * a saner message about no samples being in the perf.data file. 29894979d0c7SJiri Olsa * 29904979d0c7SJiri Olsa * This also serves to suppress a warning about f_header.data.size == 0 29918b99b1a4SJiri Olsa * in header.c at the moment 'perf stat record' gets introduced, which 29928b99b1a4SJiri Olsa * is not really needed once we start adding the stat specific PERF_RECORD_ 29938b99b1a4SJiri Olsa * records, but the need to suppress the kptr_restrict messages in older 29948b99b1a4SJiri Olsa * tools remain -acme 29954979d0c7SJiri Olsa */ 29968ceb41d7SJiri Olsa int fd = perf_data__fd(&perf_stat.data); 29974979d0c7SJiri Olsa int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat, 29984979d0c7SJiri Olsa process_synthesized_event, 29994979d0c7SJiri Olsa &perf_stat.session->machines.host); 30004979d0c7SJiri Olsa if (err) { 30014979d0c7SJiri Olsa pr_warning("Couldn't synthesize the kernel mmap record, harmless, " 30024979d0c7SJiri Olsa "older tools may produce warnings about this file\n."); 30034979d0c7SJiri Olsa } 30044979d0c7SJiri Olsa 30057aad0c32SJiri Olsa if (!interval) { 30067aad0c32SJiri Olsa if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL)) 30077aad0c32SJiri Olsa pr_err("failed to write stat round event\n"); 30087aad0c32SJiri Olsa } 30097aad0c32SJiri Olsa 30108ceb41d7SJiri Olsa if (!perf_stat.data.is_pipe) { 30114979d0c7SJiri Olsa perf_stat.session->header.data_size += perf_stat.bytes_written; 30124979d0c7SJiri Olsa perf_session__write_header(perf_stat.session, evsel_list, fd, true); 3013664c98d4SJiri Olsa } 30144979d0c7SJiri Olsa 30154979d0c7SJiri Olsa perf_session__delete(perf_stat.session); 30164979d0c7SJiri Olsa } 30174979d0c7SJiri Olsa 3018544c2ae7SMasami Hiramatsu perf_stat__exit_aggr_mode(); 3019d134ffb9SArnaldo Carvalho de Melo perf_evlist__free_stats(evsel_list); 30200015e2e1SArnaldo Carvalho de Melo out: 3021e55c14afSJiri Olsa free(walltime_run); 3022e55c14afSJiri Olsa 3023daefd0bcSKan Liang if (smi_cost && smi_reset) 3024daefd0bcSKan Liang sysfs__write_int(FREEZE_ON_SMI_PATH, 0); 3025daefd0bcSKan Liang 30260015e2e1SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 302756739444SJin Yao 302856739444SJin Yao runtime_stat_delete(&stat_config); 302956739444SJin Yao 303042202dd5SIngo Molnar return status; 303186470930SIngo Molnar } 3032