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" 55a5d243d0SIngo Molnar #include "util/color.h" 560007eceaSXiao Guangrong #include "util/stat.h" 5760666c63SLiming Wang #include "util/header.h" 58a12b51c4SPaul Mackerras #include "util/cpumap.h" 59d6d901c2SZhang, Yanmin #include "util/thread.h" 60fd78260bSArnaldo Carvalho de Melo #include "util/thread_map.h" 61d809560bSJiri Olsa #include "util/counts.h" 6244b1e60aSAndi Kleen #include "util/group.h" 634979d0c7SJiri Olsa #include "util/session.h" 64ba6039b6SJiri Olsa #include "util/tool.h" 6544b1e60aSAndi Kleen #include "util/group.h" 66ba6039b6SJiri Olsa #include "asm/bug.h" 6786470930SIngo Molnar 6844b1e60aSAndi Kleen #include <api/fs/fs.h> 691f16c575SPeter Zijlstra #include <stdlib.h> 7086470930SIngo Molnar #include <sys/prctl.h> 715af52b51SStephane Eranian #include <locale.h> 72e3b03b6cSAndi Kleen #include <math.h> 7386470930SIngo Molnar 74d7470b6aSStephane Eranian #define DEFAULT_SEPARATOR " " 752cee77c4SDavid Ahern #define CNTR_NOT_SUPPORTED "<not supported>" 762cee77c4SDavid Ahern #define CNTR_NOT_COUNTED "<not counted>" 77d7470b6aSStephane Eranian 78d4f63a47SJiri Olsa static void print_counters(struct timespec *ts, int argc, const char **argv); 7913370a9bSStephane Eranian 804cabc3d1SAndi Kleen /* Default events used for perf stat -T */ 81a454742cSJiri Olsa static const char *transaction_attrs = { 82a454742cSJiri Olsa "task-clock," 834cabc3d1SAndi Kleen "{" 844cabc3d1SAndi Kleen "instructions," 854cabc3d1SAndi Kleen "cycles," 864cabc3d1SAndi Kleen "cpu/cycles-t/," 874cabc3d1SAndi Kleen "cpu/tx-start/," 884cabc3d1SAndi Kleen "cpu/el-start/," 894cabc3d1SAndi Kleen "cpu/cycles-ct/" 904cabc3d1SAndi Kleen "}" 914cabc3d1SAndi Kleen }; 924cabc3d1SAndi Kleen 934cabc3d1SAndi Kleen /* More limited version when the CPU does not have all events. */ 94a454742cSJiri Olsa static const char * transaction_limited_attrs = { 95a454742cSJiri Olsa "task-clock," 964cabc3d1SAndi Kleen "{" 974cabc3d1SAndi Kleen "instructions," 984cabc3d1SAndi Kleen "cycles," 994cabc3d1SAndi Kleen "cpu/cycles-t/," 1004cabc3d1SAndi Kleen "cpu/tx-start/" 1014cabc3d1SAndi Kleen "}" 1024cabc3d1SAndi Kleen }; 1034cabc3d1SAndi Kleen 10444b1e60aSAndi Kleen static const char * topdown_attrs[] = { 10544b1e60aSAndi Kleen "topdown-total-slots", 10644b1e60aSAndi Kleen "topdown-slots-retired", 10744b1e60aSAndi Kleen "topdown-recovery-bubbles", 10844b1e60aSAndi Kleen "topdown-fetch-bubbles", 10944b1e60aSAndi Kleen "topdown-slots-issued", 11044b1e60aSAndi Kleen NULL, 11144b1e60aSAndi Kleen }; 11244b1e60aSAndi Kleen 113666e6d48SRobert Richter static struct perf_evlist *evsel_list; 114361c99a6SArnaldo Carvalho de Melo 115602ad878SArnaldo Carvalho de Melo static struct target target = { 11677a6f014SNamhyung Kim .uid = UINT_MAX, 11777a6f014SNamhyung Kim }; 11842202dd5SIngo Molnar 1191e5a2931SJiri Olsa typedef int (*aggr_get_id_t)(struct cpu_map *m, int cpu); 1201e5a2931SJiri Olsa 1213d632595SJaswinder Singh Rajput static int run_count = 1; 1222e6cdf99SStephane Eranian static bool no_inherit = false; 123d07f0b12SStephane Eranian static volatile pid_t child_pid = -1; 124c0555642SIan Munsie static bool null_run = false; 1252cba3ffbSIngo Molnar static int detailed_run = 0; 1264cabc3d1SAndi Kleen static bool transaction_run; 12744b1e60aSAndi Kleen static bool topdown_run = false; 128201e0b06SArnaldo Carvalho de Melo static bool big_num = true; 129d7470b6aSStephane Eranian static int big_num_opt = -1; 130d7470b6aSStephane Eranian static const char *csv_sep = NULL; 131d7470b6aSStephane Eranian static bool csv_output = false; 13243bece79SLin Ming static bool group = false; 1331f16c575SPeter Zijlstra static const char *pre_cmd = NULL; 1341f16c575SPeter Zijlstra static const char *post_cmd = NULL; 1351f16c575SPeter Zijlstra static bool sync_run = false; 13641191688SAndi Kleen static unsigned int initial_delay = 0; 137410136f5SStephane Eranian static unsigned int unit_width = 4; /* strlen("unit") */ 138a7e191c3SFrederik Deweerdt static bool forever = false; 13954b50916SAndi Kleen static bool metric_only = false; 14044b1e60aSAndi Kleen static bool force_metric_only = false; 14113370a9bSStephane Eranian static struct timespec ref_time; 14286ee6e18SStephane Eranian static struct cpu_map *aggr_map; 1431e5a2931SJiri Olsa static aggr_get_id_t aggr_get_id; 144e0547311SJiri Olsa static bool append_file; 145e0547311SJiri Olsa static const char *output_name; 146e0547311SJiri Olsa static int output_fd; 1475af52b51SStephane Eranian 1484979d0c7SJiri Olsa struct perf_stat { 1494979d0c7SJiri Olsa bool record; 1504979d0c7SJiri Olsa struct perf_data_file file; 1514979d0c7SJiri Olsa struct perf_session *session; 1524979d0c7SJiri Olsa u64 bytes_written; 153ba6039b6SJiri Olsa struct perf_tool tool; 1541975d36eSJiri Olsa bool maps_allocated; 1551975d36eSJiri Olsa struct cpu_map *cpus; 1561975d36eSJiri Olsa struct thread_map *threads; 15789af4e05SJiri Olsa enum aggr_mode aggr_mode; 1584979d0c7SJiri Olsa }; 1594979d0c7SJiri Olsa 1604979d0c7SJiri Olsa static struct perf_stat perf_stat; 1614979d0c7SJiri Olsa #define STAT_RECORD perf_stat.record 1624979d0c7SJiri Olsa 16360666c63SLiming Wang static volatile int done = 0; 16460666c63SLiming Wang 165421a50f3SJiri Olsa static struct perf_stat_config stat_config = { 166421a50f3SJiri Olsa .aggr_mode = AGGR_GLOBAL, 167711a572eSJiri Olsa .scale = true, 168421a50f3SJiri Olsa }; 169421a50f3SJiri Olsa 17013370a9bSStephane Eranian static inline void diff_timespec(struct timespec *r, struct timespec *a, 17113370a9bSStephane Eranian struct timespec *b) 17213370a9bSStephane Eranian { 17313370a9bSStephane Eranian r->tv_sec = a->tv_sec - b->tv_sec; 17413370a9bSStephane Eranian if (a->tv_nsec < b->tv_nsec) { 17513370a9bSStephane Eranian r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec; 17613370a9bSStephane Eranian r->tv_sec--; 17713370a9bSStephane Eranian } else { 17813370a9bSStephane Eranian r->tv_nsec = a->tv_nsec - b->tv_nsec ; 17913370a9bSStephane Eranian } 18013370a9bSStephane Eranian } 18113370a9bSStephane Eranian 182254ecbc7SJiri Olsa static void perf_stat__reset_stats(void) 183254ecbc7SJiri Olsa { 184254ecbc7SJiri Olsa perf_evlist__reset_stats(evsel_list); 185f87027b9SJiri Olsa perf_stat__reset_shadow_stats(); 1861eda3b21SJiri Olsa } 1871eda3b21SJiri Olsa 188cac21425SJiri Olsa static int create_perf_stat_counter(struct perf_evsel *evsel) 18986470930SIngo Molnar { 19069aad6f1SArnaldo Carvalho de Melo struct perf_event_attr *attr = &evsel->attr; 191727ab04eSArnaldo Carvalho de Melo 192711a572eSJiri Olsa if (stat_config.scale) 19386470930SIngo Molnar attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 19486470930SIngo Molnar PERF_FORMAT_TOTAL_TIME_RUNNING; 19586470930SIngo Molnar 1962e6cdf99SStephane Eranian attr->inherit = !no_inherit; 1975d2cd909SArnaldo Carvalho de Melo 1986acd8e92SJiri Olsa /* 1996acd8e92SJiri Olsa * Some events get initialized with sample_(period/type) set, 2006acd8e92SJiri Olsa * like tracepoints. Clear it up for counting. 2016acd8e92SJiri Olsa */ 2026acd8e92SJiri Olsa attr->sample_period = 0; 2036db1a5c1SJiri Olsa 2044979d0c7SJiri Olsa /* 2054979d0c7SJiri Olsa * But set sample_type to PERF_SAMPLE_IDENTIFIER, which should be harmless 2064979d0c7SJiri Olsa * while avoiding that older tools show confusing messages. 2076db1a5c1SJiri Olsa * 2086db1a5c1SJiri Olsa * However for pipe sessions we need to keep it zero, 2096db1a5c1SJiri Olsa * because script's perf_evsel__check_attr is triggered 2106db1a5c1SJiri Olsa * by attr->sample_type != 0, and we can't run it on 2116db1a5c1SJiri Olsa * stat sessions. 2124979d0c7SJiri Olsa */ 2136db1a5c1SJiri Olsa if (!(STAT_RECORD && perf_stat.file.is_pipe)) 2144979d0c7SJiri Olsa attr->sample_type = PERF_SAMPLE_IDENTIFIER; 2156acd8e92SJiri Olsa 21667ccdecdSJiri Olsa /* 21767ccdecdSJiri Olsa * Disabling all counters initially, they will be enabled 21867ccdecdSJiri Olsa * either manually by us or by kernel via enable_on_exec 21967ccdecdSJiri Olsa * set later. 22067ccdecdSJiri Olsa */ 221c8280cecSJiri Olsa if (perf_evsel__is_group_leader(evsel)) { 22267ccdecdSJiri Olsa attr->disabled = 1; 22367ccdecdSJiri Olsa 224c8280cecSJiri Olsa /* 225c8280cecSJiri Olsa * In case of initial_delay we enable tracee 226c8280cecSJiri Olsa * events manually. 227c8280cecSJiri Olsa */ 228c8280cecSJiri Olsa if (target__none(&target) && !initial_delay) 229c8280cecSJiri Olsa attr->enable_on_exec = 1; 230c8280cecSJiri Olsa } 231c8280cecSJiri Olsa 232602ad878SArnaldo Carvalho de Melo if (target__has_cpu(&target)) 233594ac61aSArnaldo Carvalho de Melo return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel)); 2345622c07bSStephane Eranian 235594ac61aSArnaldo Carvalho de Melo return perf_evsel__open_per_thread(evsel, evsel_list->threads); 23686470930SIngo Molnar } 23786470930SIngo Molnar 23886470930SIngo Molnar /* 23986470930SIngo Molnar * Does the counter have nsecs as a unit? 24086470930SIngo Molnar */ 241daec78a0SArnaldo Carvalho de Melo static inline int nsec_counter(struct perf_evsel *evsel) 24286470930SIngo Molnar { 243daec78a0SArnaldo Carvalho de Melo if (perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK) || 244daec78a0SArnaldo Carvalho de Melo perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) 24586470930SIngo Molnar return 1; 24686470930SIngo Molnar 24786470930SIngo Molnar return 0; 24886470930SIngo Molnar } 24986470930SIngo Molnar 2508b99b1a4SJiri Olsa static int process_synthesized_event(struct perf_tool *tool __maybe_unused, 2514979d0c7SJiri Olsa union perf_event *event, 2524979d0c7SJiri Olsa struct perf_sample *sample __maybe_unused, 2534979d0c7SJiri Olsa struct machine *machine __maybe_unused) 2544979d0c7SJiri Olsa { 2558b99b1a4SJiri Olsa if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) { 2568b99b1a4SJiri Olsa pr_err("failed to write perf data, error: %m\n"); 2578b99b1a4SJiri Olsa return -1; 2588b99b1a4SJiri Olsa } 2598b99b1a4SJiri Olsa 2608b99b1a4SJiri Olsa perf_stat.bytes_written += event->header.size; 2618b99b1a4SJiri Olsa return 0; 2624979d0c7SJiri Olsa } 2634979d0c7SJiri Olsa 2641975d36eSJiri Olsa static int write_stat_round_event(u64 tm, u64 type) 2657aad0c32SJiri Olsa { 2661975d36eSJiri Olsa return perf_event__synthesize_stat_round(NULL, tm, type, 2677aad0c32SJiri Olsa process_synthesized_event, 2687aad0c32SJiri Olsa NULL); 2697aad0c32SJiri Olsa } 2707aad0c32SJiri Olsa 2717aad0c32SJiri Olsa #define WRITE_STAT_ROUND_EVENT(time, interval) \ 2727aad0c32SJiri Olsa write_stat_round_event(time, PERF_STAT_ROUND_TYPE__ ## interval) 2737aad0c32SJiri Olsa 2745a6ea81bSJiri Olsa #define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 2755a6ea81bSJiri Olsa 2765a6ea81bSJiri Olsa static int 2775a6ea81bSJiri Olsa perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread, 2785a6ea81bSJiri Olsa struct perf_counts_values *count) 2795a6ea81bSJiri Olsa { 2805a6ea81bSJiri Olsa struct perf_sample_id *sid = SID(counter, cpu, thread); 2815a6ea81bSJiri Olsa 2825a6ea81bSJiri Olsa return perf_event__synthesize_stat(NULL, cpu, thread, sid->id, count, 2835a6ea81bSJiri Olsa process_synthesized_event, NULL); 2845a6ea81bSJiri Olsa } 2855a6ea81bSJiri Olsa 286f5b4a9c3SStephane Eranian /* 287f5b4a9c3SStephane Eranian * Read out the results of a single counter: 288f5b4a9c3SStephane Eranian * do not aggregate counts across CPUs in system-wide mode 289f5b4a9c3SStephane Eranian */ 290c52b12edSArnaldo Carvalho de Melo static int read_counter(struct perf_evsel *counter) 291f5b4a9c3SStephane Eranian { 2929bf1a529SJiri Olsa int nthreads = thread_map__nr(evsel_list->threads); 2939bf1a529SJiri Olsa int ncpus = perf_evsel__nr_cpus(counter); 2949bf1a529SJiri Olsa int cpu, thread; 295f5b4a9c3SStephane Eranian 2963b4331d9SSuzuki K. Poulose if (!counter->supported) 2973b4331d9SSuzuki K. Poulose return -ENOENT; 2983b4331d9SSuzuki K. Poulose 2999bf1a529SJiri Olsa if (counter->system_wide) 3009bf1a529SJiri Olsa nthreads = 1; 3019bf1a529SJiri Olsa 3029bf1a529SJiri Olsa for (thread = 0; thread < nthreads; thread++) { 3039bf1a529SJiri Olsa for (cpu = 0; cpu < ncpus; cpu++) { 3043b3eb044SJiri Olsa struct perf_counts_values *count; 3053b3eb044SJiri Olsa 3063b3eb044SJiri Olsa count = perf_counts(counter->counts, cpu, thread); 3073b3eb044SJiri Olsa if (perf_evsel__read(counter, cpu, thread, count)) 308c52b12edSArnaldo Carvalho de Melo return -1; 3095a6ea81bSJiri Olsa 3105a6ea81bSJiri Olsa if (STAT_RECORD) { 3115a6ea81bSJiri Olsa if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { 3125a6ea81bSJiri Olsa pr_err("failed to write stat event\n"); 3135a6ea81bSJiri Olsa return -1; 3145a6ea81bSJiri Olsa } 3155a6ea81bSJiri Olsa } 3160b1abbf4SAndi Kleen 3170b1abbf4SAndi Kleen if (verbose > 1) { 3180b1abbf4SAndi Kleen fprintf(stat_config.output, 3190b1abbf4SAndi Kleen "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 3200b1abbf4SAndi Kleen perf_evsel__name(counter), 3210b1abbf4SAndi Kleen cpu, 3220b1abbf4SAndi Kleen count->val, count->ena, count->run); 3230b1abbf4SAndi Kleen } 324f5b4a9c3SStephane Eranian } 3259bf1a529SJiri Olsa } 326c52b12edSArnaldo Carvalho de Melo 327c52b12edSArnaldo Carvalho de Melo return 0; 32886470930SIngo Molnar } 32986470930SIngo Molnar 3305fc472a6SJiri Olsa static void read_counters(bool close_counters) 331106a94a0SJiri Olsa { 332106a94a0SJiri Olsa struct perf_evsel *counter; 333106a94a0SJiri Olsa 334e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 3353b3eb044SJiri Olsa if (read_counter(counter)) 336245bad8eSAndi Kleen pr_debug("failed to read counter %s\n", counter->name); 3373b3eb044SJiri Olsa 338f80010ebSJiri Olsa if (perf_stat_process_counter(&stat_config, counter)) 3393b3eb044SJiri Olsa pr_warning("failed to process counter %s\n", counter->name); 340106a94a0SJiri Olsa 3415fc472a6SJiri Olsa if (close_counters) { 342106a94a0SJiri Olsa perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 343106a94a0SJiri Olsa thread_map__nr(evsel_list->threads)); 344106a94a0SJiri Olsa } 345106a94a0SJiri Olsa } 346106a94a0SJiri Olsa } 347106a94a0SJiri Olsa 348ba411a95SJiri Olsa static void process_interval(void) 34913370a9bSStephane Eranian { 35013370a9bSStephane Eranian struct timespec ts, rs; 35113370a9bSStephane Eranian 352106a94a0SJiri Olsa read_counters(false); 35386ee6e18SStephane Eranian 35413370a9bSStephane Eranian clock_gettime(CLOCK_MONOTONIC, &ts); 35513370a9bSStephane Eranian diff_timespec(&rs, &ts, &ref_time); 35613370a9bSStephane Eranian 3577aad0c32SJiri Olsa if (STAT_RECORD) { 3587aad0c32SJiri Olsa if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL)) 3597aad0c32SJiri Olsa pr_err("failed to write stat round event\n"); 3607aad0c32SJiri Olsa } 3617aad0c32SJiri Olsa 362d4f63a47SJiri Olsa print_counters(&rs, 0, NULL); 36313370a9bSStephane Eranian } 36413370a9bSStephane Eranian 36567ccdecdSJiri Olsa static void enable_counters(void) 36641191688SAndi Kleen { 36767ccdecdSJiri Olsa if (initial_delay) 36841191688SAndi Kleen usleep(initial_delay * 1000); 36967ccdecdSJiri Olsa 37067ccdecdSJiri Olsa /* 37167ccdecdSJiri Olsa * We need to enable counters only if: 37267ccdecdSJiri Olsa * - we don't have tracee (attaching to task or cpu) 37367ccdecdSJiri Olsa * - we have initial delay configured 37467ccdecdSJiri Olsa */ 37567ccdecdSJiri Olsa if (!target__none(&target) || initial_delay) 376ab46db0aSJiri Olsa perf_evlist__enable(evsel_list); 37741191688SAndi Kleen } 37841191688SAndi Kleen 379f33cbe72SArnaldo Carvalho de Melo static volatile int workload_exec_errno; 3806af206fdSArnaldo Carvalho de Melo 3816af206fdSArnaldo Carvalho de Melo /* 3826af206fdSArnaldo Carvalho de Melo * perf_evlist__prepare_workload will send a SIGUSR1 3836af206fdSArnaldo Carvalho de Melo * if the fork fails, since we asked by setting its 3846af206fdSArnaldo Carvalho de Melo * want_signal to true. 3856af206fdSArnaldo Carvalho de Melo */ 386f33cbe72SArnaldo Carvalho de Melo static void workload_exec_failed_signal(int signo __maybe_unused, siginfo_t *info, 387f33cbe72SArnaldo Carvalho de Melo void *ucontext __maybe_unused) 3886af206fdSArnaldo Carvalho de Melo { 389f33cbe72SArnaldo Carvalho de Melo workload_exec_errno = info->si_value.sival_int; 3906af206fdSArnaldo Carvalho de Melo } 3916af206fdSArnaldo Carvalho de Melo 3927b60a7e3SJiri Olsa static bool has_unit(struct perf_evsel *counter) 3937b60a7e3SJiri Olsa { 3947b60a7e3SJiri Olsa return counter->unit && *counter->unit; 3957b60a7e3SJiri Olsa } 3967b60a7e3SJiri Olsa 3977b60a7e3SJiri Olsa static bool has_scale(struct perf_evsel *counter) 3987b60a7e3SJiri Olsa { 3997b60a7e3SJiri Olsa return counter->scale != 1; 4007b60a7e3SJiri Olsa } 4017b60a7e3SJiri Olsa 402664c98d4SJiri Olsa static int perf_stat_synthesize_config(bool is_pipe) 4038b99b1a4SJiri Olsa { 4047b60a7e3SJiri Olsa struct perf_evsel *counter; 4058b99b1a4SJiri Olsa int err; 4068b99b1a4SJiri Olsa 407664c98d4SJiri Olsa if (is_pipe) { 408664c98d4SJiri Olsa err = perf_event__synthesize_attrs(NULL, perf_stat.session, 409664c98d4SJiri Olsa process_synthesized_event); 410664c98d4SJiri Olsa if (err < 0) { 411664c98d4SJiri Olsa pr_err("Couldn't synthesize attrs.\n"); 412664c98d4SJiri Olsa return err; 413664c98d4SJiri Olsa } 414664c98d4SJiri Olsa } 415664c98d4SJiri Olsa 4167b60a7e3SJiri Olsa /* 4177b60a7e3SJiri Olsa * Synthesize other events stuff not carried within 4187b60a7e3SJiri Olsa * attr event - unit, scale, name 4197b60a7e3SJiri Olsa */ 420e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 4217b60a7e3SJiri Olsa if (!counter->supported) 4227b60a7e3SJiri Olsa continue; 4237b60a7e3SJiri Olsa 4247b60a7e3SJiri Olsa /* 4257b60a7e3SJiri Olsa * Synthesize unit and scale only if it's defined. 4267b60a7e3SJiri Olsa */ 4277b60a7e3SJiri Olsa if (has_unit(counter)) { 4287b60a7e3SJiri Olsa err = perf_event__synthesize_event_update_unit(NULL, counter, process_synthesized_event); 4297b60a7e3SJiri Olsa if (err < 0) { 4307b60a7e3SJiri Olsa pr_err("Couldn't synthesize evsel unit.\n"); 4317b60a7e3SJiri Olsa return err; 4327b60a7e3SJiri Olsa } 4337b60a7e3SJiri Olsa } 4347b60a7e3SJiri Olsa 4357b60a7e3SJiri Olsa if (has_scale(counter)) { 4367b60a7e3SJiri Olsa err = perf_event__synthesize_event_update_scale(NULL, counter, process_synthesized_event); 4377b60a7e3SJiri Olsa if (err < 0) { 4387b60a7e3SJiri Olsa pr_err("Couldn't synthesize evsel scale.\n"); 4397b60a7e3SJiri Olsa return err; 4407b60a7e3SJiri Olsa } 4417b60a7e3SJiri Olsa } 4427b60a7e3SJiri Olsa 4437b60a7e3SJiri Olsa if (counter->own_cpus) { 4447b60a7e3SJiri Olsa err = perf_event__synthesize_event_update_cpus(NULL, counter, process_synthesized_event); 4457b60a7e3SJiri Olsa if (err < 0) { 4467b60a7e3SJiri Olsa pr_err("Couldn't synthesize evsel scale.\n"); 4477b60a7e3SJiri Olsa return err; 4487b60a7e3SJiri Olsa } 4497b60a7e3SJiri Olsa } 4507b60a7e3SJiri Olsa 4517b60a7e3SJiri Olsa /* 4527b60a7e3SJiri Olsa * Name is needed only for pipe output, 4537b60a7e3SJiri Olsa * perf.data carries event names. 4547b60a7e3SJiri Olsa */ 4557b60a7e3SJiri Olsa if (is_pipe) { 4567b60a7e3SJiri Olsa err = perf_event__synthesize_event_update_name(NULL, counter, process_synthesized_event); 4577b60a7e3SJiri Olsa if (err < 0) { 4587b60a7e3SJiri Olsa pr_err("Couldn't synthesize evsel name.\n"); 4597b60a7e3SJiri Olsa return err; 4607b60a7e3SJiri Olsa } 4617b60a7e3SJiri Olsa } 4627b60a7e3SJiri Olsa } 4637b60a7e3SJiri Olsa 4648b99b1a4SJiri Olsa err = perf_event__synthesize_thread_map2(NULL, evsel_list->threads, 4658b99b1a4SJiri Olsa process_synthesized_event, 4668b99b1a4SJiri Olsa NULL); 4678b99b1a4SJiri Olsa if (err < 0) { 4688b99b1a4SJiri Olsa pr_err("Couldn't synthesize thread map.\n"); 4698b99b1a4SJiri Olsa return err; 4708b99b1a4SJiri Olsa } 4718b99b1a4SJiri Olsa 4728b99b1a4SJiri Olsa err = perf_event__synthesize_cpu_map(NULL, evsel_list->cpus, 4738b99b1a4SJiri Olsa process_synthesized_event, NULL); 4748b99b1a4SJiri Olsa if (err < 0) { 4758b99b1a4SJiri Olsa pr_err("Couldn't synthesize thread map.\n"); 4768b99b1a4SJiri Olsa return err; 4778b99b1a4SJiri Olsa } 4788b99b1a4SJiri Olsa 4798b99b1a4SJiri Olsa err = perf_event__synthesize_stat_config(NULL, &stat_config, 4808b99b1a4SJiri Olsa process_synthesized_event, NULL); 4818b99b1a4SJiri Olsa if (err < 0) { 4828b99b1a4SJiri Olsa pr_err("Couldn't synthesize config.\n"); 4838b99b1a4SJiri Olsa return err; 4848b99b1a4SJiri Olsa } 4858b99b1a4SJiri Olsa 4868b99b1a4SJiri Olsa return 0; 4878b99b1a4SJiri Olsa } 4888b99b1a4SJiri Olsa 4892af4646dSJiri Olsa #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 4902af4646dSJiri Olsa 4912af4646dSJiri Olsa static int __store_counter_ids(struct perf_evsel *counter, 4922af4646dSJiri Olsa struct cpu_map *cpus, 4932af4646dSJiri Olsa struct thread_map *threads) 4942af4646dSJiri Olsa { 4952af4646dSJiri Olsa int cpu, thread; 4962af4646dSJiri Olsa 4972af4646dSJiri Olsa for (cpu = 0; cpu < cpus->nr; cpu++) { 4982af4646dSJiri Olsa for (thread = 0; thread < threads->nr; thread++) { 4992af4646dSJiri Olsa int fd = FD(counter, cpu, thread); 5002af4646dSJiri Olsa 5012af4646dSJiri Olsa if (perf_evlist__id_add_fd(evsel_list, counter, 5022af4646dSJiri Olsa cpu, thread, fd) < 0) 5032af4646dSJiri Olsa return -1; 5042af4646dSJiri Olsa } 5052af4646dSJiri Olsa } 5062af4646dSJiri Olsa 5072af4646dSJiri Olsa return 0; 5082af4646dSJiri Olsa } 5092af4646dSJiri Olsa 5102af4646dSJiri Olsa static int store_counter_ids(struct perf_evsel *counter) 5112af4646dSJiri Olsa { 5122af4646dSJiri Olsa struct cpu_map *cpus = counter->cpus; 5132af4646dSJiri Olsa struct thread_map *threads = counter->threads; 5142af4646dSJiri Olsa 5152af4646dSJiri Olsa if (perf_evsel__alloc_id(counter, cpus->nr, threads->nr)) 5162af4646dSJiri Olsa return -ENOMEM; 5172af4646dSJiri Olsa 5182af4646dSJiri Olsa return __store_counter_ids(counter, cpus, threads); 5192af4646dSJiri Olsa } 5202af4646dSJiri Olsa 521acf28922SNamhyung Kim static int __run_perf_stat(int argc, const char **argv) 52286470930SIngo Molnar { 523ec0d3d1fSJiri Olsa int interval = stat_config.interval; 52456e52e85SArnaldo Carvalho de Melo char msg[512]; 52586470930SIngo Molnar unsigned long long t0, t1; 526cac21425SJiri Olsa struct perf_evsel *counter; 52713370a9bSStephane Eranian struct timespec ts; 528410136f5SStephane Eranian size_t l; 52942202dd5SIngo Molnar int status = 0; 5306be2850eSZhang, Yanmin const bool forks = (argc > 0); 531664c98d4SJiri Olsa bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false; 53286470930SIngo Molnar 53313370a9bSStephane Eranian if (interval) { 53413370a9bSStephane Eranian ts.tv_sec = interval / 1000; 53513370a9bSStephane Eranian ts.tv_nsec = (interval % 1000) * 1000000; 53613370a9bSStephane Eranian } else { 53713370a9bSStephane Eranian ts.tv_sec = 1; 53813370a9bSStephane Eranian ts.tv_nsec = 0; 53913370a9bSStephane Eranian } 54013370a9bSStephane Eranian 541acf28922SNamhyung Kim if (forks) { 542664c98d4SJiri Olsa if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe, 543735f7e0bSArnaldo Carvalho de Melo workload_exec_failed_signal) < 0) { 544acf28922SNamhyung Kim perror("failed to prepare workload"); 545fceda7feSDavid Ahern return -1; 546051ae7f7SPaul Mackerras } 547d20a47e7SNamhyung Kim child_pid = evsel_list->workload.pid; 54860666c63SLiming Wang } 549051ae7f7SPaul Mackerras 5506a4bb04cSJiri Olsa if (group) 55163dab225SArnaldo Carvalho de Melo perf_evlist__set_leader(evsel_list); 5526a4bb04cSJiri Olsa 553e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 55442ef8a78SArnaldo Carvalho de Melo try_again: 555cac21425SJiri Olsa if (create_perf_stat_counter(counter) < 0) { 556979987a5SDavid Ahern /* 557979987a5SDavid Ahern * PPC returns ENXIO for HW counters until 2.6.37 558979987a5SDavid Ahern * (behavior changed with commit b0a873e). 559979987a5SDavid Ahern */ 56038f6ae1eSAnton Blanchard if (errno == EINVAL || errno == ENOSYS || 561979987a5SDavid Ahern errno == ENOENT || errno == EOPNOTSUPP || 562979987a5SDavid Ahern errno == ENXIO) { 563c63ca0c0SDavid Ahern if (verbose) 564c63ca0c0SDavid Ahern ui__warning("%s event is not supported by the kernel.\n", 5657289f83cSArnaldo Carvalho de Melo perf_evsel__name(counter)); 5662cee77c4SDavid Ahern counter->supported = false; 567cb5ef600SKan Liang 568cb5ef600SKan Liang if ((counter->leader != counter) || 569cb5ef600SKan Liang !(counter->leader->nr_members > 1)) 570ede70290SIngo Molnar continue; 57142ef8a78SArnaldo Carvalho de Melo } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) { 57242ef8a78SArnaldo Carvalho de Melo if (verbose) 57342ef8a78SArnaldo Carvalho de Melo ui__warning("%s\n", msg); 57442ef8a78SArnaldo Carvalho de Melo goto try_again; 575c63ca0c0SDavid Ahern } 576ede70290SIngo Molnar 57756e52e85SArnaldo Carvalho de Melo perf_evsel__open_strerror(counter, &target, 57856e52e85SArnaldo Carvalho de Melo errno, msg, sizeof(msg)); 57956e52e85SArnaldo Carvalho de Melo ui__error("%s\n", msg); 58056e52e85SArnaldo Carvalho de Melo 581084ab9f8SArnaldo Carvalho de Melo if (child_pid != -1) 582084ab9f8SArnaldo Carvalho de Melo kill(child_pid, SIGTERM); 583fceda7feSDavid Ahern 584084ab9f8SArnaldo Carvalho de Melo return -1; 585084ab9f8SArnaldo Carvalho de Melo } 5862cee77c4SDavid Ahern counter->supported = true; 587410136f5SStephane Eranian 588410136f5SStephane Eranian l = strlen(counter->unit); 589410136f5SStephane Eranian if (l > unit_width) 590410136f5SStephane Eranian unit_width = l; 5912af4646dSJiri Olsa 5922af4646dSJiri Olsa if (STAT_RECORD && store_counter_ids(counter)) 5932af4646dSJiri Olsa return -1; 59448290609SArnaldo Carvalho de Melo } 59586470930SIngo Molnar 59623d4aad4SArnaldo Carvalho de Melo if (perf_evlist__apply_filters(evsel_list, &counter)) { 59723d4aad4SArnaldo Carvalho de Melo error("failed to set filter \"%s\" on event %s with %d (%s)\n", 59823d4aad4SArnaldo Carvalho de Melo counter->filter, perf_evsel__name(counter), errno, 599759e612bSMasami Hiramatsu strerror_r(errno, msg, sizeof(msg))); 600cfd748aeSFrederic Weisbecker return -1; 601cfd748aeSFrederic Weisbecker } 602cfd748aeSFrederic Weisbecker 6034979d0c7SJiri Olsa if (STAT_RECORD) { 6044979d0c7SJiri Olsa int err, fd = perf_data_file__fd(&perf_stat.file); 6054979d0c7SJiri Olsa 606664c98d4SJiri Olsa if (is_pipe) { 607664c98d4SJiri Olsa err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file)); 608664c98d4SJiri Olsa } else { 6094979d0c7SJiri Olsa err = perf_session__write_header(perf_stat.session, evsel_list, 6104979d0c7SJiri Olsa fd, false); 611664c98d4SJiri Olsa } 612664c98d4SJiri Olsa 6134979d0c7SJiri Olsa if (err < 0) 6144979d0c7SJiri Olsa return err; 6158b99b1a4SJiri Olsa 616664c98d4SJiri Olsa err = perf_stat_synthesize_config(is_pipe); 6178b99b1a4SJiri Olsa if (err < 0) 6188b99b1a4SJiri Olsa return err; 6194979d0c7SJiri Olsa } 6204979d0c7SJiri Olsa 62186470930SIngo Molnar /* 62286470930SIngo Molnar * Enable counters and exec the command: 62386470930SIngo Molnar */ 62486470930SIngo Molnar t0 = rdclock(); 62513370a9bSStephane Eranian clock_gettime(CLOCK_MONOTONIC, &ref_time); 62686470930SIngo Molnar 62760666c63SLiming Wang if (forks) { 628acf28922SNamhyung Kim perf_evlist__start_workload(evsel_list); 62967ccdecdSJiri Olsa enable_counters(); 630acf28922SNamhyung Kim 63113370a9bSStephane Eranian if (interval) { 63213370a9bSStephane Eranian while (!waitpid(child_pid, &status, WNOHANG)) { 63313370a9bSStephane Eranian nanosleep(&ts, NULL); 634ba411a95SJiri Olsa process_interval(); 63513370a9bSStephane Eranian } 63613370a9bSStephane Eranian } 63742202dd5SIngo Molnar wait(&status); 6386af206fdSArnaldo Carvalho de Melo 639f33cbe72SArnaldo Carvalho de Melo if (workload_exec_errno) { 640f33cbe72SArnaldo Carvalho de Melo const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 641f33cbe72SArnaldo Carvalho de Melo pr_err("Workload failed: %s\n", emsg); 6426af206fdSArnaldo Carvalho de Melo return -1; 643f33cbe72SArnaldo Carvalho de Melo } 6446af206fdSArnaldo Carvalho de Melo 64533e49ea7SAndi Kleen if (WIFSIGNALED(status)) 64633e49ea7SAndi Kleen psignal(WTERMSIG(status), argv[0]); 64760666c63SLiming Wang } else { 64867ccdecdSJiri Olsa enable_counters(); 64913370a9bSStephane Eranian while (!done) { 65013370a9bSStephane Eranian nanosleep(&ts, NULL); 65113370a9bSStephane Eranian if (interval) 652ba411a95SJiri Olsa process_interval(); 65313370a9bSStephane Eranian } 65460666c63SLiming Wang } 65586470930SIngo Molnar 65686470930SIngo Molnar t1 = rdclock(); 65786470930SIngo Molnar 6589e9772c4SPeter Zijlstra update_stats(&walltime_nsecs_stats, t1 - t0); 65942202dd5SIngo Molnar 660106a94a0SJiri Olsa read_counters(true); 661c52b12edSArnaldo Carvalho de Melo 66242202dd5SIngo Molnar return WEXITSTATUS(status); 66342202dd5SIngo Molnar } 66442202dd5SIngo Molnar 66541cde476SArnaldo Carvalho de Melo static int run_perf_stat(int argc, const char **argv) 6661f16c575SPeter Zijlstra { 6671f16c575SPeter Zijlstra int ret; 6681f16c575SPeter Zijlstra 6691f16c575SPeter Zijlstra if (pre_cmd) { 6701f16c575SPeter Zijlstra ret = system(pre_cmd); 6711f16c575SPeter Zijlstra if (ret) 6721f16c575SPeter Zijlstra return ret; 6731f16c575SPeter Zijlstra } 6741f16c575SPeter Zijlstra 6751f16c575SPeter Zijlstra if (sync_run) 6761f16c575SPeter Zijlstra sync(); 6771f16c575SPeter Zijlstra 6781f16c575SPeter Zijlstra ret = __run_perf_stat(argc, argv); 6791f16c575SPeter Zijlstra if (ret) 6801f16c575SPeter Zijlstra return ret; 6811f16c575SPeter Zijlstra 6821f16c575SPeter Zijlstra if (post_cmd) { 6831f16c575SPeter Zijlstra ret = system(post_cmd); 6841f16c575SPeter Zijlstra if (ret) 6851f16c575SPeter Zijlstra return ret; 6861f16c575SPeter Zijlstra } 6871f16c575SPeter Zijlstra 6881f16c575SPeter Zijlstra return ret; 6891f16c575SPeter Zijlstra } 6901f16c575SPeter Zijlstra 691d73515c0SAndi Kleen static void print_running(u64 run, u64 ena) 692d73515c0SAndi Kleen { 693d73515c0SAndi Kleen if (csv_output) { 6945821522eSJiri Olsa fprintf(stat_config.output, "%s%" PRIu64 "%s%.2f", 695d73515c0SAndi Kleen csv_sep, 696d73515c0SAndi Kleen run, 697d73515c0SAndi Kleen csv_sep, 698d73515c0SAndi Kleen ena ? 100.0 * run / ena : 100.0); 699d73515c0SAndi Kleen } else if (run != ena) { 7005821522eSJiri Olsa fprintf(stat_config.output, " (%.2f%%)", 100.0 * run / ena); 701d73515c0SAndi Kleen } 702d73515c0SAndi Kleen } 703d73515c0SAndi Kleen 704f99844cbSIngo Molnar static void print_noise_pct(double total, double avg) 705f99844cbSIngo Molnar { 7060007eceaSXiao Guangrong double pct = rel_stddev_stats(total, avg); 707f99844cbSIngo Molnar 7083ae9a34dSZhengyu He if (csv_output) 7095821522eSJiri Olsa fprintf(stat_config.output, "%s%.2f%%", csv_sep, pct); 710a1bca6ccSJim Cromie else if (pct) 7115821522eSJiri Olsa fprintf(stat_config.output, " ( +-%6.2f%% )", pct); 712f99844cbSIngo Molnar } 713f99844cbSIngo Molnar 71469aad6f1SArnaldo Carvalho de Melo static void print_noise(struct perf_evsel *evsel, double avg) 71542202dd5SIngo Molnar { 716581cc8a2SJiri Olsa struct perf_stat_evsel *ps; 71769aad6f1SArnaldo Carvalho de Melo 718849abde9SPeter Zijlstra if (run_count == 1) 719849abde9SPeter Zijlstra return; 720849abde9SPeter Zijlstra 72169aad6f1SArnaldo Carvalho de Melo ps = evsel->priv; 722f99844cbSIngo Molnar print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); 72342202dd5SIngo Molnar } 72442202dd5SIngo Molnar 72512c08a9fSStephane Eranian static void aggr_printout(struct perf_evsel *evsel, int id, int nr) 72642202dd5SIngo Molnar { 727421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 72812c08a9fSStephane Eranian case AGGR_CORE: 7295821522eSJiri Olsa fprintf(stat_config.output, "S%d-C%*d%s%*d%s", 73012c08a9fSStephane Eranian cpu_map__id_to_socket(id), 73112c08a9fSStephane Eranian csv_output ? 0 : -8, 73212c08a9fSStephane Eranian cpu_map__id_to_cpu(id), 73312c08a9fSStephane Eranian csv_sep, 73412c08a9fSStephane Eranian csv_output ? 0 : 4, 73512c08a9fSStephane Eranian nr, 73612c08a9fSStephane Eranian csv_sep); 73712c08a9fSStephane Eranian break; 73886ee6e18SStephane Eranian case AGGR_SOCKET: 7395821522eSJiri Olsa fprintf(stat_config.output, "S%*d%s%*d%s", 740d7e7a451SStephane Eranian csv_output ? 0 : -5, 74112c08a9fSStephane Eranian id, 742d7e7a451SStephane Eranian csv_sep, 743d7e7a451SStephane Eranian csv_output ? 0 : 4, 744d7e7a451SStephane Eranian nr, 745d7e7a451SStephane Eranian csv_sep); 74686ee6e18SStephane Eranian break; 74786ee6e18SStephane Eranian case AGGR_NONE: 7485821522eSJiri Olsa fprintf(stat_config.output, "CPU%*d%s", 749d7470b6aSStephane Eranian csv_output ? 0 : -4, 75012c08a9fSStephane Eranian perf_evsel__cpus(evsel)->map[id], csv_sep); 75186ee6e18SStephane Eranian break; 75232b8af82SJiri Olsa case AGGR_THREAD: 7535821522eSJiri Olsa fprintf(stat_config.output, "%*s-%*d%s", 75432b8af82SJiri Olsa csv_output ? 0 : 16, 75532b8af82SJiri Olsa thread_map__comm(evsel->threads, id), 75632b8af82SJiri Olsa csv_output ? 0 : -8, 75732b8af82SJiri Olsa thread_map__pid(evsel->threads, id), 75832b8af82SJiri Olsa csv_sep); 75932b8af82SJiri Olsa break; 76086ee6e18SStephane Eranian case AGGR_GLOBAL: 761208df99eSJiri Olsa case AGGR_UNSET: 76286ee6e18SStephane Eranian default: 76386ee6e18SStephane Eranian break; 76486ee6e18SStephane Eranian } 76586ee6e18SStephane Eranian } 766d7470b6aSStephane Eranian 767140aeadcSAndi Kleen struct outstate { 768140aeadcSAndi Kleen FILE *fh; 769140aeadcSAndi Kleen bool newline; 770f9483392SAndi Kleen const char *prefix; 77192a61f64SAndi Kleen int nfields; 77244d49a60SAndi Kleen int id, nr; 77344d49a60SAndi Kleen struct perf_evsel *evsel; 774140aeadcSAndi Kleen }; 775140aeadcSAndi Kleen 776140aeadcSAndi Kleen #define METRIC_LEN 35 777140aeadcSAndi Kleen 778140aeadcSAndi Kleen static void new_line_std(void *ctx) 779140aeadcSAndi Kleen { 780140aeadcSAndi Kleen struct outstate *os = ctx; 781140aeadcSAndi Kleen 782140aeadcSAndi Kleen os->newline = true; 783140aeadcSAndi Kleen } 784140aeadcSAndi Kleen 785140aeadcSAndi Kleen static void do_new_line_std(struct outstate *os) 786140aeadcSAndi Kleen { 787140aeadcSAndi Kleen fputc('\n', os->fh); 788f9483392SAndi Kleen fputs(os->prefix, os->fh); 78944d49a60SAndi Kleen aggr_printout(os->evsel, os->id, os->nr); 790140aeadcSAndi Kleen if (stat_config.aggr_mode == AGGR_NONE) 791140aeadcSAndi Kleen fprintf(os->fh, " "); 792140aeadcSAndi Kleen fprintf(os->fh, " "); 793140aeadcSAndi Kleen } 794140aeadcSAndi Kleen 795140aeadcSAndi Kleen static void print_metric_std(void *ctx, const char *color, const char *fmt, 796140aeadcSAndi Kleen const char *unit, double val) 797140aeadcSAndi Kleen { 798140aeadcSAndi Kleen struct outstate *os = ctx; 799140aeadcSAndi Kleen FILE *out = os->fh; 800140aeadcSAndi Kleen int n; 801140aeadcSAndi Kleen bool newline = os->newline; 802140aeadcSAndi Kleen 803140aeadcSAndi Kleen os->newline = false; 804140aeadcSAndi Kleen 805140aeadcSAndi Kleen if (unit == NULL || fmt == NULL) { 806140aeadcSAndi Kleen fprintf(out, "%-*s", METRIC_LEN, ""); 807140aeadcSAndi Kleen return; 808140aeadcSAndi Kleen } 809140aeadcSAndi Kleen 810140aeadcSAndi Kleen if (newline) 811140aeadcSAndi Kleen do_new_line_std(os); 812140aeadcSAndi Kleen 813140aeadcSAndi Kleen n = fprintf(out, " # "); 814140aeadcSAndi Kleen if (color) 815140aeadcSAndi Kleen n += color_fprintf(out, color, fmt, val); 816140aeadcSAndi Kleen else 817140aeadcSAndi Kleen n += fprintf(out, fmt, val); 818140aeadcSAndi Kleen fprintf(out, " %-*s", METRIC_LEN - n - 1, unit); 819140aeadcSAndi Kleen } 820140aeadcSAndi Kleen 82192a61f64SAndi Kleen static void new_line_csv(void *ctx) 82292a61f64SAndi Kleen { 82392a61f64SAndi Kleen struct outstate *os = ctx; 82492a61f64SAndi Kleen int i; 82592a61f64SAndi Kleen 82692a61f64SAndi Kleen fputc('\n', os->fh); 82792a61f64SAndi Kleen if (os->prefix) 82892a61f64SAndi Kleen fprintf(os->fh, "%s%s", os->prefix, csv_sep); 82944d49a60SAndi Kleen aggr_printout(os->evsel, os->id, os->nr); 83092a61f64SAndi Kleen for (i = 0; i < os->nfields; i++) 83192a61f64SAndi Kleen fputs(csv_sep, os->fh); 83292a61f64SAndi Kleen } 83392a61f64SAndi Kleen 83492a61f64SAndi Kleen static void print_metric_csv(void *ctx, 83592a61f64SAndi Kleen const char *color __maybe_unused, 83692a61f64SAndi Kleen const char *fmt, const char *unit, double val) 83792a61f64SAndi Kleen { 83892a61f64SAndi Kleen struct outstate *os = ctx; 83992a61f64SAndi Kleen FILE *out = os->fh; 84092a61f64SAndi Kleen char buf[64], *vals, *ends; 84192a61f64SAndi Kleen 84292a61f64SAndi Kleen if (unit == NULL || fmt == NULL) { 84392a61f64SAndi Kleen fprintf(out, "%s%s%s%s", csv_sep, csv_sep, csv_sep, csv_sep); 84492a61f64SAndi Kleen return; 84592a61f64SAndi Kleen } 84692a61f64SAndi Kleen snprintf(buf, sizeof(buf), fmt, val); 84792a61f64SAndi Kleen vals = buf; 84892a61f64SAndi Kleen while (isspace(*vals)) 84992a61f64SAndi Kleen vals++; 85092a61f64SAndi Kleen ends = vals; 85192a61f64SAndi Kleen while (isdigit(*ends) || *ends == '.') 85292a61f64SAndi Kleen ends++; 85392a61f64SAndi Kleen *ends = 0; 85492a61f64SAndi Kleen while (isspace(*unit)) 85592a61f64SAndi Kleen unit++; 85692a61f64SAndi Kleen fprintf(out, "%s%s%s%s", csv_sep, vals, csv_sep, unit); 85792a61f64SAndi Kleen } 85892a61f64SAndi Kleen 85954b50916SAndi Kleen #define METRIC_ONLY_LEN 20 86054b50916SAndi Kleen 86154b50916SAndi Kleen /* Filter out some columns that don't work well in metrics only mode */ 86254b50916SAndi Kleen 86354b50916SAndi Kleen static bool valid_only_metric(const char *unit) 86454b50916SAndi Kleen { 86554b50916SAndi Kleen if (!unit) 86654b50916SAndi Kleen return false; 86754b50916SAndi Kleen if (strstr(unit, "/sec") || 86854b50916SAndi Kleen strstr(unit, "hz") || 86954b50916SAndi Kleen strstr(unit, "Hz") || 87054b50916SAndi Kleen strstr(unit, "CPUs utilized")) 87154b50916SAndi Kleen return false; 87254b50916SAndi Kleen return true; 87354b50916SAndi Kleen } 87454b50916SAndi Kleen 87554b50916SAndi Kleen static const char *fixunit(char *buf, struct perf_evsel *evsel, 87654b50916SAndi Kleen const char *unit) 87754b50916SAndi Kleen { 87854b50916SAndi Kleen if (!strncmp(unit, "of all", 6)) { 87954b50916SAndi Kleen snprintf(buf, 1024, "%s %s", perf_evsel__name(evsel), 88054b50916SAndi Kleen unit); 88154b50916SAndi Kleen return buf; 88254b50916SAndi Kleen } 88354b50916SAndi Kleen return unit; 88454b50916SAndi Kleen } 88554b50916SAndi Kleen 88654b50916SAndi Kleen static void print_metric_only(void *ctx, const char *color, const char *fmt, 88754b50916SAndi Kleen const char *unit, double val) 88854b50916SAndi Kleen { 88954b50916SAndi Kleen struct outstate *os = ctx; 89054b50916SAndi Kleen FILE *out = os->fh; 89154b50916SAndi Kleen int n; 89254b50916SAndi Kleen char buf[1024]; 89354b50916SAndi Kleen unsigned mlen = METRIC_ONLY_LEN; 89454b50916SAndi Kleen 89554b50916SAndi Kleen if (!valid_only_metric(unit)) 89654b50916SAndi Kleen return; 89754b50916SAndi Kleen unit = fixunit(buf, os->evsel, unit); 89854b50916SAndi Kleen if (color) 89954b50916SAndi Kleen n = color_fprintf(out, color, fmt, val); 90054b50916SAndi Kleen else 90154b50916SAndi Kleen n = fprintf(out, fmt, val); 90254b50916SAndi Kleen if (n > METRIC_ONLY_LEN) 90354b50916SAndi Kleen n = METRIC_ONLY_LEN; 90454b50916SAndi Kleen if (mlen < strlen(unit)) 90554b50916SAndi Kleen mlen = strlen(unit) + 1; 90654b50916SAndi Kleen fprintf(out, "%*s", mlen - n, ""); 90754b50916SAndi Kleen } 90854b50916SAndi Kleen 90954b50916SAndi Kleen static void print_metric_only_csv(void *ctx, const char *color __maybe_unused, 91054b50916SAndi Kleen const char *fmt, 91154b50916SAndi Kleen const char *unit, double val) 91254b50916SAndi Kleen { 91354b50916SAndi Kleen struct outstate *os = ctx; 91454b50916SAndi Kleen FILE *out = os->fh; 91554b50916SAndi Kleen char buf[64], *vals, *ends; 91654b50916SAndi Kleen char tbuf[1024]; 91754b50916SAndi Kleen 91854b50916SAndi Kleen if (!valid_only_metric(unit)) 91954b50916SAndi Kleen return; 92054b50916SAndi Kleen unit = fixunit(tbuf, os->evsel, unit); 92154b50916SAndi Kleen snprintf(buf, sizeof buf, fmt, val); 92254b50916SAndi Kleen vals = buf; 92354b50916SAndi Kleen while (isspace(*vals)) 92454b50916SAndi Kleen vals++; 92554b50916SAndi Kleen ends = vals; 92654b50916SAndi Kleen while (isdigit(*ends) || *ends == '.') 92754b50916SAndi Kleen ends++; 92854b50916SAndi Kleen *ends = 0; 92954b50916SAndi Kleen fprintf(out, "%s%s", vals, csv_sep); 93054b50916SAndi Kleen } 93154b50916SAndi Kleen 93254b50916SAndi Kleen static void new_line_metric(void *ctx __maybe_unused) 93354b50916SAndi Kleen { 93454b50916SAndi Kleen } 93554b50916SAndi Kleen 93654b50916SAndi Kleen static void print_metric_header(void *ctx, const char *color __maybe_unused, 93754b50916SAndi Kleen const char *fmt __maybe_unused, 93854b50916SAndi Kleen const char *unit, double val __maybe_unused) 93954b50916SAndi Kleen { 94054b50916SAndi Kleen struct outstate *os = ctx; 94154b50916SAndi Kleen char tbuf[1024]; 94254b50916SAndi Kleen 94354b50916SAndi Kleen if (!valid_only_metric(unit)) 94454b50916SAndi Kleen return; 94554b50916SAndi Kleen unit = fixunit(tbuf, os->evsel, unit); 94654b50916SAndi Kleen if (csv_output) 94754b50916SAndi Kleen fprintf(os->fh, "%s%s", unit, csv_sep); 94854b50916SAndi Kleen else 94954b50916SAndi Kleen fprintf(os->fh, "%-*s ", METRIC_ONLY_LEN, unit); 95054b50916SAndi Kleen } 95154b50916SAndi Kleen 952da88c7f7SAndi Kleen static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg) 95386ee6e18SStephane Eranian { 9545821522eSJiri Olsa FILE *output = stat_config.output; 95586ee6e18SStephane Eranian double msecs = avg / 1e6; 956410136f5SStephane Eranian const char *fmt_v, *fmt_n; 9574bbe5a61SDavid Ahern char name[25]; 95886ee6e18SStephane Eranian 959410136f5SStephane Eranian fmt_v = csv_output ? "%.6f%s" : "%18.6f%s"; 960410136f5SStephane Eranian fmt_n = csv_output ? "%s" : "%-25s"; 961410136f5SStephane Eranian 962da88c7f7SAndi Kleen aggr_printout(evsel, id, nr); 96386ee6e18SStephane Eranian 9644bbe5a61SDavid Ahern scnprintf(name, sizeof(name), "%s%s", 9654bbe5a61SDavid Ahern perf_evsel__name(evsel), csv_output ? "" : " (msec)"); 966410136f5SStephane Eranian 967410136f5SStephane Eranian fprintf(output, fmt_v, msecs, csv_sep); 968410136f5SStephane Eranian 969410136f5SStephane Eranian if (csv_output) 970410136f5SStephane Eranian fprintf(output, "%s%s", evsel->unit, csv_sep); 971410136f5SStephane Eranian else 972410136f5SStephane Eranian fprintf(output, "%-*s%s", unit_width, evsel->unit, csv_sep); 973410136f5SStephane Eranian 974410136f5SStephane Eranian fprintf(output, fmt_n, name); 975d7470b6aSStephane Eranian 976023695d9SStephane Eranian if (evsel->cgrp) 9774aa9015fSStephane Eranian fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 97842202dd5SIngo Molnar } 97942202dd5SIngo Molnar 98044d49a60SAndi Kleen static int first_shadow_cpu(struct perf_evsel *evsel, int id) 98144d49a60SAndi Kleen { 98244d49a60SAndi Kleen int i; 98344d49a60SAndi Kleen 98444d49a60SAndi Kleen if (!aggr_get_id) 98544d49a60SAndi Kleen return 0; 98644d49a60SAndi Kleen 98744d49a60SAndi Kleen if (stat_config.aggr_mode == AGGR_NONE) 98844d49a60SAndi Kleen return id; 98944d49a60SAndi Kleen 99044d49a60SAndi Kleen if (stat_config.aggr_mode == AGGR_GLOBAL) 99144d49a60SAndi Kleen return 0; 99244d49a60SAndi Kleen 99344d49a60SAndi Kleen for (i = 0; i < perf_evsel__nr_cpus(evsel); i++) { 99444d49a60SAndi Kleen int cpu2 = perf_evsel__cpus(evsel)->map[i]; 99544d49a60SAndi Kleen 99644d49a60SAndi Kleen if (aggr_get_id(evsel_list->cpus, cpu2) == id) 99744d49a60SAndi Kleen return cpu2; 99844d49a60SAndi Kleen } 99944d49a60SAndi Kleen return 0; 100044d49a60SAndi Kleen } 100144d49a60SAndi Kleen 1002556b1fb7SJiri Olsa static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg) 1003556b1fb7SJiri Olsa { 10045821522eSJiri Olsa FILE *output = stat_config.output; 1005556b1fb7SJiri Olsa double sc = evsel->scale; 1006556b1fb7SJiri Olsa const char *fmt; 1007556b1fb7SJiri Olsa 1008556b1fb7SJiri Olsa if (csv_output) { 1009e3b03b6cSAndi Kleen fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s"; 1010556b1fb7SJiri Olsa } else { 1011556b1fb7SJiri Olsa if (big_num) 1012e3b03b6cSAndi Kleen fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s"; 1013556b1fb7SJiri Olsa else 1014e3b03b6cSAndi Kleen fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s"; 1015556b1fb7SJiri Olsa } 1016556b1fb7SJiri Olsa 1017556b1fb7SJiri Olsa aggr_printout(evsel, id, nr); 1018556b1fb7SJiri Olsa 1019556b1fb7SJiri Olsa fprintf(output, fmt, avg, csv_sep); 1020556b1fb7SJiri Olsa 1021556b1fb7SJiri Olsa if (evsel->unit) 1022556b1fb7SJiri Olsa fprintf(output, "%-*s%s", 1023556b1fb7SJiri Olsa csv_output ? 0 : unit_width, 1024556b1fb7SJiri Olsa evsel->unit, csv_sep); 1025556b1fb7SJiri Olsa 1026556b1fb7SJiri Olsa fprintf(output, "%-*s", csv_output ? 0 : 25, perf_evsel__name(evsel)); 1027556b1fb7SJiri Olsa 1028556b1fb7SJiri Olsa if (evsel->cgrp) 1029556b1fb7SJiri Olsa fprintf(output, "%s%s", csv_sep, evsel->cgrp->name); 1030eedfcb4bSAndi Kleen } 1031556b1fb7SJiri Olsa 1032f9483392SAndi Kleen static void printout(int id, int nr, struct perf_evsel *counter, double uval, 1033cb110f47SAndi Kleen char *prefix, u64 run, u64 ena, double noise) 1034eedfcb4bSAndi Kleen { 1035140aeadcSAndi Kleen struct perf_stat_output_ctx out; 1036f9483392SAndi Kleen struct outstate os = { 1037f9483392SAndi Kleen .fh = stat_config.output, 103844d49a60SAndi Kleen .prefix = prefix ? prefix : "", 103944d49a60SAndi Kleen .id = id, 104044d49a60SAndi Kleen .nr = nr, 104144d49a60SAndi Kleen .evsel = counter, 1042f9483392SAndi Kleen }; 1043140aeadcSAndi Kleen print_metric_t pm = print_metric_std; 1044140aeadcSAndi Kleen void (*nl)(void *); 1045556b1fb7SJiri Olsa 104654b50916SAndi Kleen if (metric_only) { 104754b50916SAndi Kleen nl = new_line_metric; 104854b50916SAndi Kleen if (csv_output) 104954b50916SAndi Kleen pm = print_metric_only_csv; 105054b50916SAndi Kleen else 105154b50916SAndi Kleen pm = print_metric_only; 105254b50916SAndi Kleen } else 1053140aeadcSAndi Kleen nl = new_line_std; 1054eedfcb4bSAndi Kleen 105554b50916SAndi Kleen if (csv_output && !metric_only) { 105692a61f64SAndi Kleen static int aggr_fields[] = { 105792a61f64SAndi Kleen [AGGR_GLOBAL] = 0, 105892a61f64SAndi Kleen [AGGR_THREAD] = 1, 105992a61f64SAndi Kleen [AGGR_NONE] = 1, 106092a61f64SAndi Kleen [AGGR_SOCKET] = 2, 106192a61f64SAndi Kleen [AGGR_CORE] = 2, 106292a61f64SAndi Kleen }; 106392a61f64SAndi Kleen 106492a61f64SAndi Kleen pm = print_metric_csv; 106592a61f64SAndi Kleen nl = new_line_csv; 106692a61f64SAndi Kleen os.nfields = 3; 106792a61f64SAndi Kleen os.nfields += aggr_fields[stat_config.aggr_mode]; 106892a61f64SAndi Kleen if (counter->cgrp) 106992a61f64SAndi Kleen os.nfields++; 107092a61f64SAndi Kleen } 1071b002f3bbSAndi Kleen if (run == 0 || ena == 0 || counter->counts->scaled == -1) { 107254b50916SAndi Kleen if (metric_only) { 107354b50916SAndi Kleen pm(&os, NULL, "", "", 0); 107454b50916SAndi Kleen return; 107554b50916SAndi Kleen } 1076cb110f47SAndi Kleen aggr_printout(counter, id, nr); 1077cb110f47SAndi Kleen 1078cb110f47SAndi Kleen fprintf(stat_config.output, "%*s%s", 1079cb110f47SAndi Kleen csv_output ? 0 : 18, 1080cb110f47SAndi Kleen counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, 1081cb110f47SAndi Kleen csv_sep); 1082cb110f47SAndi Kleen 1083cb110f47SAndi Kleen fprintf(stat_config.output, "%-*s%s", 1084cb110f47SAndi Kleen csv_output ? 0 : unit_width, 1085cb110f47SAndi Kleen counter->unit, csv_sep); 1086cb110f47SAndi Kleen 1087cb110f47SAndi Kleen fprintf(stat_config.output, "%*s", 1088cb110f47SAndi Kleen csv_output ? 0 : -25, 1089cb110f47SAndi Kleen perf_evsel__name(counter)); 1090cb110f47SAndi Kleen 1091cb110f47SAndi Kleen if (counter->cgrp) 1092cb110f47SAndi Kleen fprintf(stat_config.output, "%s%s", 1093cb110f47SAndi Kleen csv_sep, counter->cgrp->name); 1094cb110f47SAndi Kleen 109592a61f64SAndi Kleen if (!csv_output) 109692a61f64SAndi Kleen pm(&os, NULL, NULL, "", 0); 109792a61f64SAndi Kleen print_noise(counter, noise); 1098cb110f47SAndi Kleen print_running(run, ena); 109992a61f64SAndi Kleen if (csv_output) 110092a61f64SAndi Kleen pm(&os, NULL, NULL, "", 0); 1101cb110f47SAndi Kleen return; 1102cb110f47SAndi Kleen } 1103cb110f47SAndi Kleen 110454b50916SAndi Kleen if (metric_only) 110554b50916SAndi Kleen /* nothing */; 110654b50916SAndi Kleen else if (nsec_counter(counter)) 1107eedfcb4bSAndi Kleen nsec_printout(id, nr, counter, uval); 1108eedfcb4bSAndi Kleen else 1109eedfcb4bSAndi Kleen abs_printout(id, nr, counter, uval); 1110eedfcb4bSAndi Kleen 1111140aeadcSAndi Kleen out.print_metric = pm; 1112140aeadcSAndi Kleen out.new_line = nl; 1113140aeadcSAndi Kleen out.ctx = &os; 1114140aeadcSAndi Kleen 111554b50916SAndi Kleen if (csv_output && !metric_only) { 111692a61f64SAndi Kleen print_noise(counter, noise); 111792a61f64SAndi Kleen print_running(run, ena); 111892a61f64SAndi Kleen } 111992a61f64SAndi Kleen 1120140aeadcSAndi Kleen perf_stat__print_shadow_stats(counter, uval, 112144d49a60SAndi Kleen first_shadow_cpu(counter, id), 1122140aeadcSAndi Kleen &out); 112354b50916SAndi Kleen if (!csv_output && !metric_only) { 1124cb110f47SAndi Kleen print_noise(counter, noise); 1125cb110f47SAndi Kleen print_running(run, ena); 1126556b1fb7SJiri Olsa } 112792a61f64SAndi Kleen } 1128556b1fb7SJiri Olsa 112944d49a60SAndi Kleen static void aggr_update_shadow(void) 113044d49a60SAndi Kleen { 113144d49a60SAndi Kleen int cpu, s2, id, s; 113244d49a60SAndi Kleen u64 val; 113344d49a60SAndi Kleen struct perf_evsel *counter; 113444d49a60SAndi Kleen 113544d49a60SAndi Kleen for (s = 0; s < aggr_map->nr; s++) { 113644d49a60SAndi Kleen id = aggr_map->map[s]; 1137e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 113844d49a60SAndi Kleen val = 0; 113944d49a60SAndi Kleen for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 114044d49a60SAndi Kleen s2 = aggr_get_id(evsel_list->cpus, cpu); 114144d49a60SAndi Kleen if (s2 != id) 114244d49a60SAndi Kleen continue; 114344d49a60SAndi Kleen val += perf_counts(counter->counts, cpu, 0)->val; 114444d49a60SAndi Kleen } 114544d49a60SAndi Kleen val = val * counter->scale; 114644d49a60SAndi Kleen perf_stat__update_shadow_stats(counter, &val, 114744d49a60SAndi Kleen first_shadow_cpu(counter, id)); 114844d49a60SAndi Kleen } 114944d49a60SAndi Kleen } 115044d49a60SAndi Kleen } 115144d49a60SAndi Kleen 115286ee6e18SStephane Eranian static void print_aggr(char *prefix) 1153d7e7a451SStephane Eranian { 11545821522eSJiri Olsa FILE *output = stat_config.output; 1155d7e7a451SStephane Eranian struct perf_evsel *counter; 1156601083cfSKan Liang int cpu, s, s2, id, nr; 1157410136f5SStephane Eranian double uval; 1158d7e7a451SStephane Eranian u64 ena, run, val; 115954b50916SAndi Kleen bool first; 1160d7e7a451SStephane Eranian 116186ee6e18SStephane Eranian if (!(aggr_map || aggr_get_id)) 1162d7e7a451SStephane Eranian return; 1163d7e7a451SStephane Eranian 116444d49a60SAndi Kleen aggr_update_shadow(); 116544d49a60SAndi Kleen 116654b50916SAndi Kleen /* 116754b50916SAndi Kleen * With metric_only everything is on a single line. 116854b50916SAndi Kleen * Without each counter has its own line. 116954b50916SAndi Kleen */ 117086ee6e18SStephane Eranian for (s = 0; s < aggr_map->nr; s++) { 117154b50916SAndi Kleen if (prefix && metric_only) 117254b50916SAndi Kleen fprintf(output, "%s", prefix); 117354b50916SAndi Kleen 117486ee6e18SStephane Eranian id = aggr_map->map[s]; 117554b50916SAndi Kleen first = true; 1176e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 1177d7e7a451SStephane Eranian val = ena = run = 0; 1178d7e7a451SStephane Eranian nr = 0; 1179d7e7a451SStephane Eranian for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1180601083cfSKan Liang s2 = aggr_get_id(perf_evsel__cpus(counter), cpu); 118186ee6e18SStephane Eranian if (s2 != id) 1182d7e7a451SStephane Eranian continue; 1183a6fa0038SJiri Olsa val += perf_counts(counter->counts, cpu, 0)->val; 1184a6fa0038SJiri Olsa ena += perf_counts(counter->counts, cpu, 0)->ena; 1185a6fa0038SJiri Olsa run += perf_counts(counter->counts, cpu, 0)->run; 1186d7e7a451SStephane Eranian nr++; 1187d7e7a451SStephane Eranian } 118854b50916SAndi Kleen if (first && metric_only) { 118954b50916SAndi Kleen first = false; 119054b50916SAndi Kleen aggr_printout(counter, id, nr); 119154b50916SAndi Kleen } 119254b50916SAndi Kleen if (prefix && !metric_only) 1193d7e7a451SStephane Eranian fprintf(output, "%s", prefix); 1194d7e7a451SStephane Eranian 1195410136f5SStephane Eranian uval = val * counter->scale; 1196cb110f47SAndi Kleen printout(id, nr, counter, uval, prefix, run, ena, 1.0); 119754b50916SAndi Kleen if (!metric_only) 1198d7e7a451SStephane Eranian fputc('\n', output); 1199d7e7a451SStephane Eranian } 120054b50916SAndi Kleen if (metric_only) 120154b50916SAndi Kleen fputc('\n', output); 1202d7e7a451SStephane Eranian } 1203d7e7a451SStephane Eranian } 1204d7e7a451SStephane Eranian 120532b8af82SJiri Olsa static void print_aggr_thread(struct perf_evsel *counter, char *prefix) 120632b8af82SJiri Olsa { 12075821522eSJiri Olsa FILE *output = stat_config.output; 120832b8af82SJiri Olsa int nthreads = thread_map__nr(counter->threads); 120932b8af82SJiri Olsa int ncpus = cpu_map__nr(counter->cpus); 121032b8af82SJiri Olsa int cpu, thread; 121132b8af82SJiri Olsa double uval; 121232b8af82SJiri Olsa 121332b8af82SJiri Olsa for (thread = 0; thread < nthreads; thread++) { 121432b8af82SJiri Olsa u64 ena = 0, run = 0, val = 0; 121532b8af82SJiri Olsa 121632b8af82SJiri Olsa for (cpu = 0; cpu < ncpus; cpu++) { 121732b8af82SJiri Olsa val += perf_counts(counter->counts, cpu, thread)->val; 121832b8af82SJiri Olsa ena += perf_counts(counter->counts, cpu, thread)->ena; 121932b8af82SJiri Olsa run += perf_counts(counter->counts, cpu, thread)->run; 122032b8af82SJiri Olsa } 122132b8af82SJiri Olsa 122232b8af82SJiri Olsa if (prefix) 122332b8af82SJiri Olsa fprintf(output, "%s", prefix); 122432b8af82SJiri Olsa 122532b8af82SJiri Olsa uval = val * counter->scale; 1226cb110f47SAndi Kleen printout(thread, 0, counter, uval, prefix, run, ena, 1.0); 122732b8af82SJiri Olsa fputc('\n', output); 122832b8af82SJiri Olsa } 122932b8af82SJiri Olsa } 123032b8af82SJiri Olsa 123142202dd5SIngo Molnar /* 123242202dd5SIngo Molnar * Print out the results of a single counter: 1233f5b4a9c3SStephane Eranian * aggregated counts in system-wide mode 123442202dd5SIngo Molnar */ 123513370a9bSStephane Eranian static void print_counter_aggr(struct perf_evsel *counter, char *prefix) 123642202dd5SIngo Molnar { 12375821522eSJiri Olsa FILE *output = stat_config.output; 1238581cc8a2SJiri Olsa struct perf_stat_evsel *ps = counter->priv; 123969aad6f1SArnaldo Carvalho de Melo double avg = avg_stats(&ps->res_stats[0]); 1240410136f5SStephane Eranian double uval; 1241d73515c0SAndi Kleen double avg_enabled, avg_running; 1242d73515c0SAndi Kleen 1243d73515c0SAndi Kleen avg_enabled = avg_stats(&ps->res_stats[1]); 1244d73515c0SAndi Kleen avg_running = avg_stats(&ps->res_stats[2]); 124542202dd5SIngo Molnar 124654b50916SAndi Kleen if (prefix && !metric_only) 124713370a9bSStephane Eranian fprintf(output, "%s", prefix); 124813370a9bSStephane Eranian 1249410136f5SStephane Eranian uval = avg * counter->scale; 1250cb110f47SAndi Kleen printout(-1, 0, counter, uval, prefix, avg_running, avg_enabled, avg); 125154b50916SAndi Kleen if (!metric_only) 12524aa9015fSStephane Eranian fprintf(output, "\n"); 125342202dd5SIngo Molnar } 125442202dd5SIngo Molnar 1255f5b4a9c3SStephane Eranian /* 1256f5b4a9c3SStephane Eranian * Print out the results of a single counter: 1257f5b4a9c3SStephane Eranian * does not use aggregated count in system-wide 1258f5b4a9c3SStephane Eranian */ 125913370a9bSStephane Eranian static void print_counter(struct perf_evsel *counter, char *prefix) 1260f5b4a9c3SStephane Eranian { 12615821522eSJiri Olsa FILE *output = stat_config.output; 1262f5b4a9c3SStephane Eranian u64 ena, run, val; 1263410136f5SStephane Eranian double uval; 1264f5b4a9c3SStephane Eranian int cpu; 1265f5b4a9c3SStephane Eranian 12667ae92e74SYan, Zheng for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1267a6fa0038SJiri Olsa val = perf_counts(counter->counts, cpu, 0)->val; 1268a6fa0038SJiri Olsa ena = perf_counts(counter->counts, cpu, 0)->ena; 1269a6fa0038SJiri Olsa run = perf_counts(counter->counts, cpu, 0)->run; 127013370a9bSStephane Eranian 127113370a9bSStephane Eranian if (prefix) 127213370a9bSStephane Eranian fprintf(output, "%s", prefix); 127313370a9bSStephane Eranian 1274410136f5SStephane Eranian uval = val * counter->scale; 1275cb110f47SAndi Kleen printout(cpu, 0, counter, uval, prefix, run, ena, 1.0); 1276f5b4a9c3SStephane Eranian 12774aa9015fSStephane Eranian fputc('\n', output); 1278f5b4a9c3SStephane Eranian } 1279f5b4a9c3SStephane Eranian } 1280f5b4a9c3SStephane Eranian 1281206cab65SAndi Kleen static void print_no_aggr_metric(char *prefix) 1282206cab65SAndi Kleen { 1283206cab65SAndi Kleen int cpu; 1284206cab65SAndi Kleen int nrcpus = 0; 1285206cab65SAndi Kleen struct perf_evsel *counter; 1286206cab65SAndi Kleen u64 ena, run, val; 1287206cab65SAndi Kleen double uval; 1288206cab65SAndi Kleen 1289206cab65SAndi Kleen nrcpus = evsel_list->cpus->nr; 1290206cab65SAndi Kleen for (cpu = 0; cpu < nrcpus; cpu++) { 1291206cab65SAndi Kleen bool first = true; 1292206cab65SAndi Kleen 1293206cab65SAndi Kleen if (prefix) 1294206cab65SAndi Kleen fputs(prefix, stat_config.output); 1295e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 1296206cab65SAndi Kleen if (first) { 1297206cab65SAndi Kleen aggr_printout(counter, cpu, 0); 1298206cab65SAndi Kleen first = false; 1299206cab65SAndi Kleen } 1300206cab65SAndi Kleen val = perf_counts(counter->counts, cpu, 0)->val; 1301206cab65SAndi Kleen ena = perf_counts(counter->counts, cpu, 0)->ena; 1302206cab65SAndi Kleen run = perf_counts(counter->counts, cpu, 0)->run; 1303206cab65SAndi Kleen 1304206cab65SAndi Kleen uval = val * counter->scale; 1305206cab65SAndi Kleen printout(cpu, 0, counter, uval, prefix, run, ena, 1.0); 1306206cab65SAndi Kleen } 1307206cab65SAndi Kleen fputc('\n', stat_config.output); 1308206cab65SAndi Kleen } 1309206cab65SAndi Kleen } 1310206cab65SAndi Kleen 131154b50916SAndi Kleen static int aggr_header_lens[] = { 131254b50916SAndi Kleen [AGGR_CORE] = 18, 131354b50916SAndi Kleen [AGGR_SOCKET] = 12, 1314206cab65SAndi Kleen [AGGR_NONE] = 6, 131554b50916SAndi Kleen [AGGR_THREAD] = 24, 131654b50916SAndi Kleen [AGGR_GLOBAL] = 0, 131754b50916SAndi Kleen }; 131854b50916SAndi Kleen 1319c51fd639SAndi Kleen static const char *aggr_header_csv[] = { 1320c51fd639SAndi Kleen [AGGR_CORE] = "core,cpus,", 1321c51fd639SAndi Kleen [AGGR_SOCKET] = "socket,cpus", 1322c51fd639SAndi Kleen [AGGR_NONE] = "cpu,", 1323c51fd639SAndi Kleen [AGGR_THREAD] = "comm-pid,", 1324c51fd639SAndi Kleen [AGGR_GLOBAL] = "" 1325c51fd639SAndi Kleen }; 1326c51fd639SAndi Kleen 132741c8ca2aSAndi Kleen static void print_metric_headers(const char *prefix, bool no_indent) 132854b50916SAndi Kleen { 132954b50916SAndi Kleen struct perf_stat_output_ctx out; 133054b50916SAndi Kleen struct perf_evsel *counter; 133154b50916SAndi Kleen struct outstate os = { 133254b50916SAndi Kleen .fh = stat_config.output 133354b50916SAndi Kleen }; 133454b50916SAndi Kleen 133554b50916SAndi Kleen if (prefix) 133654b50916SAndi Kleen fprintf(stat_config.output, "%s", prefix); 133754b50916SAndi Kleen 133841c8ca2aSAndi Kleen if (!csv_output && !no_indent) 133954b50916SAndi Kleen fprintf(stat_config.output, "%*s", 134054b50916SAndi Kleen aggr_header_lens[stat_config.aggr_mode], ""); 1341c51fd639SAndi Kleen if (csv_output) { 1342c51fd639SAndi Kleen if (stat_config.interval) 1343c51fd639SAndi Kleen fputs("time,", stat_config.output); 1344c51fd639SAndi Kleen fputs(aggr_header_csv[stat_config.aggr_mode], 1345c51fd639SAndi Kleen stat_config.output); 1346c51fd639SAndi Kleen } 134754b50916SAndi Kleen 134854b50916SAndi Kleen /* Print metrics headers only */ 1349e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) { 135054b50916SAndi Kleen os.evsel = counter; 135154b50916SAndi Kleen out.ctx = &os; 135254b50916SAndi Kleen out.print_metric = print_metric_header; 135354b50916SAndi Kleen out.new_line = new_line_metric; 135454b50916SAndi Kleen os.evsel = counter; 135554b50916SAndi Kleen perf_stat__print_shadow_stats(counter, 0, 135654b50916SAndi Kleen 0, 135754b50916SAndi Kleen &out); 135854b50916SAndi Kleen } 135954b50916SAndi Kleen fputc('\n', stat_config.output); 136054b50916SAndi Kleen } 136154b50916SAndi Kleen 1362d4f63a47SJiri Olsa static void print_interval(char *prefix, struct timespec *ts) 136342202dd5SIngo Molnar { 13645821522eSJiri Olsa FILE *output = stat_config.output; 1365d4f63a47SJiri Olsa static int num_print_interval; 1366d4f63a47SJiri Olsa 1367d4f63a47SJiri Olsa sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); 1368d4f63a47SJiri Olsa 136941c8ca2aSAndi Kleen if (num_print_interval == 0 && !csv_output) { 1370421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 1371d4f63a47SJiri Olsa case AGGR_SOCKET: 137241c8ca2aSAndi Kleen fprintf(output, "# time socket cpus"); 137341c8ca2aSAndi Kleen if (!metric_only) 137441c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1375d4f63a47SJiri Olsa break; 1376d4f63a47SJiri Olsa case AGGR_CORE: 137741c8ca2aSAndi Kleen fprintf(output, "# time core cpus"); 137841c8ca2aSAndi Kleen if (!metric_only) 137941c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1380d4f63a47SJiri Olsa break; 1381d4f63a47SJiri Olsa case AGGR_NONE: 138241c8ca2aSAndi Kleen fprintf(output, "# time CPU"); 138341c8ca2aSAndi Kleen if (!metric_only) 138441c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1385d4f63a47SJiri Olsa break; 138632b8af82SJiri Olsa case AGGR_THREAD: 138741c8ca2aSAndi Kleen fprintf(output, "# time comm-pid"); 138841c8ca2aSAndi Kleen if (!metric_only) 138941c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 139032b8af82SJiri Olsa break; 1391d4f63a47SJiri Olsa case AGGR_GLOBAL: 1392d4f63a47SJiri Olsa default: 139341c8ca2aSAndi Kleen fprintf(output, "# time"); 139441c8ca2aSAndi Kleen if (!metric_only) 139541c8ca2aSAndi Kleen fprintf(output, " counts %*s events\n", unit_width, "unit"); 1396208df99eSJiri Olsa case AGGR_UNSET: 1397208df99eSJiri Olsa break; 1398d4f63a47SJiri Olsa } 1399d4f63a47SJiri Olsa } 1400d4f63a47SJiri Olsa 140141c8ca2aSAndi Kleen if (num_print_interval == 0 && metric_only) 140241c8ca2aSAndi Kleen print_metric_headers(" ", true); 1403d4f63a47SJiri Olsa if (++num_print_interval == 25) 1404d4f63a47SJiri Olsa num_print_interval = 0; 1405d4f63a47SJiri Olsa } 1406d4f63a47SJiri Olsa 1407d4f63a47SJiri Olsa static void print_header(int argc, const char **argv) 1408d4f63a47SJiri Olsa { 14095821522eSJiri Olsa FILE *output = stat_config.output; 141069aad6f1SArnaldo Carvalho de Melo int i; 141142202dd5SIngo Molnar 141286470930SIngo Molnar fflush(stdout); 141386470930SIngo Molnar 1414d7470b6aSStephane Eranian if (!csv_output) { 14154aa9015fSStephane Eranian fprintf(output, "\n"); 14164aa9015fSStephane Eranian fprintf(output, " Performance counter stats for "); 141762d3b617SDavid Ahern if (target.system_wide) 141862d3b617SDavid Ahern fprintf(output, "\'system wide"); 141962d3b617SDavid Ahern else if (target.cpu_list) 142062d3b617SDavid Ahern fprintf(output, "\'CPU(s) %s", target.cpu_list); 1421602ad878SArnaldo Carvalho de Melo else if (!target__has_task(&target)) { 1422ba6039b6SJiri Olsa fprintf(output, "\'%s", argv ? argv[0] : "pipe"); 1423ba6039b6SJiri Olsa for (i = 1; argv && (i < argc); i++) 14244aa9015fSStephane Eranian fprintf(output, " %s", argv[i]); 142520f946b4SNamhyung Kim } else if (target.pid) 142620f946b4SNamhyung Kim fprintf(output, "process id \'%s", target.pid); 1427d6d901c2SZhang, Yanmin else 142820f946b4SNamhyung Kim fprintf(output, "thread id \'%s", target.tid); 142986470930SIngo Molnar 14304aa9015fSStephane Eranian fprintf(output, "\'"); 143142202dd5SIngo Molnar if (run_count > 1) 14324aa9015fSStephane Eranian fprintf(output, " (%d runs)", run_count); 14334aa9015fSStephane Eranian fprintf(output, ":\n\n"); 1434d7470b6aSStephane Eranian } 1435f5b4a9c3SStephane Eranian } 143686470930SIngo Molnar 1437d4f63a47SJiri Olsa static void print_footer(void) 1438d4f63a47SJiri Olsa { 14395821522eSJiri Olsa FILE *output = stat_config.output; 14405821522eSJiri Olsa 1441c3305257SIngo Molnar if (!null_run) 14424aa9015fSStephane Eranian fprintf(output, "\n"); 14434aa9015fSStephane Eranian fprintf(output, " %17.9f seconds time elapsed", 1444506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)/1e9); 1445566747e6SIngo Molnar if (run_count > 1) { 14464aa9015fSStephane Eranian fprintf(output, " "); 1447f99844cbSIngo Molnar print_noise_pct(stddev_stats(&walltime_nsecs_stats), 1448506d4bc8SPeter Zijlstra avg_stats(&walltime_nsecs_stats)); 1449566747e6SIngo Molnar } 14504aa9015fSStephane Eranian fprintf(output, "\n\n"); 145186470930SIngo Molnar } 1452d4f63a47SJiri Olsa 1453d4f63a47SJiri Olsa static void print_counters(struct timespec *ts, int argc, const char **argv) 1454d4f63a47SJiri Olsa { 1455ec0d3d1fSJiri Olsa int interval = stat_config.interval; 1456d4f63a47SJiri Olsa struct perf_evsel *counter; 1457d4f63a47SJiri Olsa char buf[64], *prefix = NULL; 1458d4f63a47SJiri Olsa 1459664c98d4SJiri Olsa /* Do not print anything if we record to the pipe. */ 1460664c98d4SJiri Olsa if (STAT_RECORD && perf_stat.file.is_pipe) 1461664c98d4SJiri Olsa return; 1462664c98d4SJiri Olsa 1463d4f63a47SJiri Olsa if (interval) 1464d4f63a47SJiri Olsa print_interval(prefix = buf, ts); 1465d4f63a47SJiri Olsa else 1466d4f63a47SJiri Olsa print_header(argc, argv); 1467d4f63a47SJiri Olsa 146854b50916SAndi Kleen if (metric_only) { 146954b50916SAndi Kleen static int num_print_iv; 147054b50916SAndi Kleen 147141c8ca2aSAndi Kleen if (num_print_iv == 0 && !interval) 147241c8ca2aSAndi Kleen print_metric_headers(prefix, false); 147354b50916SAndi Kleen if (num_print_iv++ == 25) 147454b50916SAndi Kleen num_print_iv = 0; 147554b50916SAndi Kleen if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) 147654b50916SAndi Kleen fprintf(stat_config.output, "%s", prefix); 147754b50916SAndi Kleen } 147854b50916SAndi Kleen 1479421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 1480d4f63a47SJiri Olsa case AGGR_CORE: 1481d4f63a47SJiri Olsa case AGGR_SOCKET: 1482d4f63a47SJiri Olsa print_aggr(prefix); 1483d4f63a47SJiri Olsa break; 148432b8af82SJiri Olsa case AGGR_THREAD: 1485e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) 148632b8af82SJiri Olsa print_aggr_thread(counter, prefix); 148732b8af82SJiri Olsa break; 1488d4f63a47SJiri Olsa case AGGR_GLOBAL: 1489e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) 1490d4f63a47SJiri Olsa print_counter_aggr(counter, prefix); 149154b50916SAndi Kleen if (metric_only) 149254b50916SAndi Kleen fputc('\n', stat_config.output); 1493d4f63a47SJiri Olsa break; 1494d4f63a47SJiri Olsa case AGGR_NONE: 1495206cab65SAndi Kleen if (metric_only) 1496206cab65SAndi Kleen print_no_aggr_metric(prefix); 1497206cab65SAndi Kleen else { 1498e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) 1499d4f63a47SJiri Olsa print_counter(counter, prefix); 1500206cab65SAndi Kleen } 1501d4f63a47SJiri Olsa break; 1502208df99eSJiri Olsa case AGGR_UNSET: 1503d4f63a47SJiri Olsa default: 1504d4f63a47SJiri Olsa break; 1505d4f63a47SJiri Olsa } 1506d4f63a47SJiri Olsa 1507d4f63a47SJiri Olsa if (!interval && !csv_output) 1508d4f63a47SJiri Olsa print_footer(); 1509d4f63a47SJiri Olsa 15105821522eSJiri Olsa fflush(stat_config.output); 1511d7470b6aSStephane Eranian } 151286470930SIngo Molnar 1513f7b7c26eSPeter Zijlstra static volatile int signr = -1; 1514f7b7c26eSPeter Zijlstra 151586470930SIngo Molnar static void skip_signal(int signo) 151686470930SIngo Molnar { 1517ec0d3d1fSJiri Olsa if ((child_pid == -1) || stat_config.interval) 151860666c63SLiming Wang done = 1; 151960666c63SLiming Wang 1520f7b7c26eSPeter Zijlstra signr = signo; 1521d07f0b12SStephane Eranian /* 1522d07f0b12SStephane Eranian * render child_pid harmless 1523d07f0b12SStephane Eranian * won't send SIGTERM to a random 1524d07f0b12SStephane Eranian * process in case of race condition 1525d07f0b12SStephane Eranian * and fast PID recycling 1526d07f0b12SStephane Eranian */ 1527d07f0b12SStephane Eranian child_pid = -1; 1528f7b7c26eSPeter Zijlstra } 1529f7b7c26eSPeter Zijlstra 1530f7b7c26eSPeter Zijlstra static void sig_atexit(void) 1531f7b7c26eSPeter Zijlstra { 1532d07f0b12SStephane Eranian sigset_t set, oset; 1533d07f0b12SStephane Eranian 1534d07f0b12SStephane Eranian /* 1535d07f0b12SStephane Eranian * avoid race condition with SIGCHLD handler 1536d07f0b12SStephane Eranian * in skip_signal() which is modifying child_pid 1537d07f0b12SStephane Eranian * goal is to avoid send SIGTERM to a random 1538d07f0b12SStephane Eranian * process 1539d07f0b12SStephane Eranian */ 1540d07f0b12SStephane Eranian sigemptyset(&set); 1541d07f0b12SStephane Eranian sigaddset(&set, SIGCHLD); 1542d07f0b12SStephane Eranian sigprocmask(SIG_BLOCK, &set, &oset); 1543d07f0b12SStephane Eranian 1544933da83aSChris Wilson if (child_pid != -1) 1545933da83aSChris Wilson kill(child_pid, SIGTERM); 1546933da83aSChris Wilson 1547d07f0b12SStephane Eranian sigprocmask(SIG_SETMASK, &oset, NULL); 1548d07f0b12SStephane Eranian 1549f7b7c26eSPeter Zijlstra if (signr == -1) 1550f7b7c26eSPeter Zijlstra return; 1551f7b7c26eSPeter Zijlstra 1552f7b7c26eSPeter Zijlstra signal(signr, SIG_DFL); 1553f7b7c26eSPeter Zijlstra kill(getpid(), signr); 155486470930SIngo Molnar } 155586470930SIngo Molnar 15561d037ca1SIrina Tirdea static int stat__set_big_num(const struct option *opt __maybe_unused, 15571d037ca1SIrina Tirdea const char *s __maybe_unused, int unset) 1558d7470b6aSStephane Eranian { 1559d7470b6aSStephane Eranian big_num_opt = unset ? 0 : 1; 1560d7470b6aSStephane Eranian return 0; 1561d7470b6aSStephane Eranian } 1562d7470b6aSStephane Eranian 156344b1e60aSAndi Kleen static int enable_metric_only(const struct option *opt __maybe_unused, 156444b1e60aSAndi Kleen const char *s __maybe_unused, int unset) 156544b1e60aSAndi Kleen { 156644b1e60aSAndi Kleen force_metric_only = true; 156744b1e60aSAndi Kleen metric_only = !unset; 156844b1e60aSAndi Kleen return 0; 156944b1e60aSAndi Kleen } 157044b1e60aSAndi Kleen 1571e0547311SJiri Olsa static const struct option stat_options[] = { 1572e0547311SJiri Olsa OPT_BOOLEAN('T', "transaction", &transaction_run, 1573e0547311SJiri Olsa "hardware transaction statistics"), 1574e0547311SJiri Olsa OPT_CALLBACK('e', "event", &evsel_list, "event", 1575e0547311SJiri Olsa "event selector. use 'perf list' to list available events", 1576e0547311SJiri Olsa parse_events_option), 1577e0547311SJiri Olsa OPT_CALLBACK(0, "filter", &evsel_list, "filter", 1578e0547311SJiri Olsa "event filter", parse_filter), 1579e0547311SJiri Olsa OPT_BOOLEAN('i', "no-inherit", &no_inherit, 1580e0547311SJiri Olsa "child tasks do not inherit counters"), 1581e0547311SJiri Olsa OPT_STRING('p', "pid", &target.pid, "pid", 1582e0547311SJiri Olsa "stat events on existing process id"), 1583e0547311SJiri Olsa OPT_STRING('t', "tid", &target.tid, "tid", 1584e0547311SJiri Olsa "stat events on existing thread id"), 1585e0547311SJiri Olsa OPT_BOOLEAN('a', "all-cpus", &target.system_wide, 1586e0547311SJiri Olsa "system-wide collection from all CPUs"), 1587e0547311SJiri Olsa OPT_BOOLEAN('g', "group", &group, 1588e0547311SJiri Olsa "put the counters into a counter group"), 1589e0547311SJiri Olsa OPT_BOOLEAN('c', "scale", &stat_config.scale, "scale/normalize counters"), 1590e0547311SJiri Olsa OPT_INCR('v', "verbose", &verbose, 1591e0547311SJiri Olsa "be more verbose (show counter open errors, etc)"), 1592e0547311SJiri Olsa OPT_INTEGER('r', "repeat", &run_count, 1593e0547311SJiri Olsa "repeat command and print average + stddev (max: 100, forever: 0)"), 1594e0547311SJiri Olsa OPT_BOOLEAN('n', "null", &null_run, 1595e0547311SJiri Olsa "null run - dont start any counters"), 1596e0547311SJiri Olsa OPT_INCR('d', "detailed", &detailed_run, 1597e0547311SJiri Olsa "detailed run - start a lot of events"), 1598e0547311SJiri Olsa OPT_BOOLEAN('S', "sync", &sync_run, 1599e0547311SJiri Olsa "call sync() before starting a run"), 1600e0547311SJiri Olsa OPT_CALLBACK_NOOPT('B', "big-num", NULL, NULL, 1601e0547311SJiri Olsa "print large numbers with thousands\' separators", 1602e0547311SJiri Olsa stat__set_big_num), 1603e0547311SJiri Olsa OPT_STRING('C', "cpu", &target.cpu_list, "cpu", 1604e0547311SJiri Olsa "list of cpus to monitor in system-wide"), 1605e0547311SJiri Olsa OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode, 1606e0547311SJiri Olsa "disable CPU count aggregation", AGGR_NONE), 1607e0547311SJiri Olsa OPT_STRING('x', "field-separator", &csv_sep, "separator", 1608e0547311SJiri Olsa "print counts with custom separator"), 1609e0547311SJiri Olsa OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 1610e0547311SJiri Olsa "monitor event in cgroup name only", parse_cgroups), 1611e0547311SJiri Olsa OPT_STRING('o', "output", &output_name, "file", "output file name"), 1612e0547311SJiri Olsa OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), 1613e0547311SJiri Olsa OPT_INTEGER(0, "log-fd", &output_fd, 1614e0547311SJiri Olsa "log output to fd, instead of stderr"), 1615e0547311SJiri Olsa OPT_STRING(0, "pre", &pre_cmd, "command", 1616e0547311SJiri Olsa "command to run prior to the measured command"), 1617e0547311SJiri Olsa OPT_STRING(0, "post", &post_cmd, "command", 1618e0547311SJiri Olsa "command to run after to the measured command"), 1619e0547311SJiri Olsa OPT_UINTEGER('I', "interval-print", &stat_config.interval, 1620e0547311SJiri Olsa "print counts at regular interval in ms (>= 10)"), 1621e0547311SJiri Olsa OPT_SET_UINT(0, "per-socket", &stat_config.aggr_mode, 1622e0547311SJiri Olsa "aggregate counts per processor socket", AGGR_SOCKET), 1623e0547311SJiri Olsa OPT_SET_UINT(0, "per-core", &stat_config.aggr_mode, 1624e0547311SJiri Olsa "aggregate counts per physical processor core", AGGR_CORE), 1625e0547311SJiri Olsa OPT_SET_UINT(0, "per-thread", &stat_config.aggr_mode, 1626e0547311SJiri Olsa "aggregate counts per thread", AGGR_THREAD), 1627e0547311SJiri Olsa OPT_UINTEGER('D', "delay", &initial_delay, 1628e0547311SJiri Olsa "ms to wait before starting measurement after program start"), 162944b1e60aSAndi Kleen OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL, 163044b1e60aSAndi Kleen "Only print computed metrics. No raw values", enable_metric_only), 163144b1e60aSAndi Kleen OPT_BOOLEAN(0, "topdown", &topdown_run, 163244b1e60aSAndi Kleen "measure topdown level 1 statistics"), 1633e0547311SJiri Olsa OPT_END() 1634e0547311SJiri Olsa }; 1635e0547311SJiri Olsa 16361fe7a300SJiri Olsa static int perf_stat__get_socket(struct cpu_map *map, int cpu) 16371fe7a300SJiri Olsa { 16381fe7a300SJiri Olsa return cpu_map__get_socket(map, cpu, NULL); 16391fe7a300SJiri Olsa } 16401fe7a300SJiri Olsa 16411fe7a300SJiri Olsa static int perf_stat__get_core(struct cpu_map *map, int cpu) 16421fe7a300SJiri Olsa { 16431fe7a300SJiri Olsa return cpu_map__get_core(map, cpu, NULL); 16441fe7a300SJiri Olsa } 16451fe7a300SJiri Olsa 16461e5a2931SJiri Olsa static int cpu_map__get_max(struct cpu_map *map) 16471e5a2931SJiri Olsa { 16481e5a2931SJiri Olsa int i, max = -1; 16491e5a2931SJiri Olsa 16501e5a2931SJiri Olsa for (i = 0; i < map->nr; i++) { 16511e5a2931SJiri Olsa if (map->map[i] > max) 16521e5a2931SJiri Olsa max = map->map[i]; 16531e5a2931SJiri Olsa } 16541e5a2931SJiri Olsa 16551e5a2931SJiri Olsa return max; 16561e5a2931SJiri Olsa } 16571e5a2931SJiri Olsa 16581e5a2931SJiri Olsa static struct cpu_map *cpus_aggr_map; 16591e5a2931SJiri Olsa 16601e5a2931SJiri Olsa static int perf_stat__get_aggr(aggr_get_id_t get_id, struct cpu_map *map, int idx) 16611e5a2931SJiri Olsa { 16621e5a2931SJiri Olsa int cpu; 16631e5a2931SJiri Olsa 16641e5a2931SJiri Olsa if (idx >= map->nr) 16651e5a2931SJiri Olsa return -1; 16661e5a2931SJiri Olsa 16671e5a2931SJiri Olsa cpu = map->map[idx]; 16681e5a2931SJiri Olsa 16691e5a2931SJiri Olsa if (cpus_aggr_map->map[cpu] == -1) 16701e5a2931SJiri Olsa cpus_aggr_map->map[cpu] = get_id(map, idx); 16711e5a2931SJiri Olsa 16721e5a2931SJiri Olsa return cpus_aggr_map->map[cpu]; 16731e5a2931SJiri Olsa } 16741e5a2931SJiri Olsa 16751e5a2931SJiri Olsa static int perf_stat__get_socket_cached(struct cpu_map *map, int idx) 16761e5a2931SJiri Olsa { 16771e5a2931SJiri Olsa return perf_stat__get_aggr(perf_stat__get_socket, map, idx); 16781e5a2931SJiri Olsa } 16791e5a2931SJiri Olsa 16801e5a2931SJiri Olsa static int perf_stat__get_core_cached(struct cpu_map *map, int idx) 16811e5a2931SJiri Olsa { 16821e5a2931SJiri Olsa return perf_stat__get_aggr(perf_stat__get_core, map, idx); 16831e5a2931SJiri Olsa } 16841e5a2931SJiri Olsa 168586ee6e18SStephane Eranian static int perf_stat_init_aggr_mode(void) 168686ee6e18SStephane Eranian { 16871e5a2931SJiri Olsa int nr; 16881e5a2931SJiri Olsa 1689421a50f3SJiri Olsa switch (stat_config.aggr_mode) { 169086ee6e18SStephane Eranian case AGGR_SOCKET: 169186ee6e18SStephane Eranian if (cpu_map__build_socket_map(evsel_list->cpus, &aggr_map)) { 169286ee6e18SStephane Eranian perror("cannot build socket map"); 169386ee6e18SStephane Eranian return -1; 169486ee6e18SStephane Eranian } 16951e5a2931SJiri Olsa aggr_get_id = perf_stat__get_socket_cached; 169686ee6e18SStephane Eranian break; 169712c08a9fSStephane Eranian case AGGR_CORE: 169812c08a9fSStephane Eranian if (cpu_map__build_core_map(evsel_list->cpus, &aggr_map)) { 169912c08a9fSStephane Eranian perror("cannot build core map"); 170012c08a9fSStephane Eranian return -1; 170112c08a9fSStephane Eranian } 17021e5a2931SJiri Olsa aggr_get_id = perf_stat__get_core_cached; 170312c08a9fSStephane Eranian break; 170486ee6e18SStephane Eranian case AGGR_NONE: 170586ee6e18SStephane Eranian case AGGR_GLOBAL: 170632b8af82SJiri Olsa case AGGR_THREAD: 1707208df99eSJiri Olsa case AGGR_UNSET: 170886ee6e18SStephane Eranian default: 170986ee6e18SStephane Eranian break; 171086ee6e18SStephane Eranian } 17111e5a2931SJiri Olsa 17121e5a2931SJiri Olsa /* 17131e5a2931SJiri Olsa * The evsel_list->cpus is the base we operate on, 17141e5a2931SJiri Olsa * taking the highest cpu number to be the size of 17151e5a2931SJiri Olsa * the aggregation translate cpumap. 17161e5a2931SJiri Olsa */ 17171e5a2931SJiri Olsa nr = cpu_map__get_max(evsel_list->cpus); 17181e5a2931SJiri Olsa cpus_aggr_map = cpu_map__empty_new(nr + 1); 17191e5a2931SJiri Olsa return cpus_aggr_map ? 0 : -ENOMEM; 172086ee6e18SStephane Eranian } 172186ee6e18SStephane Eranian 1722544c2ae7SMasami Hiramatsu static void perf_stat__exit_aggr_mode(void) 1723544c2ae7SMasami Hiramatsu { 1724544c2ae7SMasami Hiramatsu cpu_map__put(aggr_map); 1725544c2ae7SMasami Hiramatsu cpu_map__put(cpus_aggr_map); 1726544c2ae7SMasami Hiramatsu aggr_map = NULL; 1727544c2ae7SMasami Hiramatsu cpus_aggr_map = NULL; 1728544c2ae7SMasami Hiramatsu } 1729544c2ae7SMasami Hiramatsu 173068d702f7SJiri Olsa static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, int idx) 173168d702f7SJiri Olsa { 173268d702f7SJiri Olsa int cpu; 173368d702f7SJiri Olsa 173468d702f7SJiri Olsa if (idx > map->nr) 173568d702f7SJiri Olsa return -1; 173668d702f7SJiri Olsa 173768d702f7SJiri Olsa cpu = map->map[idx]; 173868d702f7SJiri Olsa 173968d702f7SJiri Olsa if (cpu >= env->nr_cpus_online) 174068d702f7SJiri Olsa return -1; 174168d702f7SJiri Olsa 174268d702f7SJiri Olsa return cpu; 174368d702f7SJiri Olsa } 174468d702f7SJiri Olsa 174568d702f7SJiri Olsa static int perf_env__get_socket(struct cpu_map *map, int idx, void *data) 174668d702f7SJiri Olsa { 174768d702f7SJiri Olsa struct perf_env *env = data; 174868d702f7SJiri Olsa int cpu = perf_env__get_cpu(env, map, idx); 174968d702f7SJiri Olsa 175068d702f7SJiri Olsa return cpu == -1 ? -1 : env->cpu[cpu].socket_id; 175168d702f7SJiri Olsa } 175268d702f7SJiri Olsa 175368d702f7SJiri Olsa static int perf_env__get_core(struct cpu_map *map, int idx, void *data) 175468d702f7SJiri Olsa { 175568d702f7SJiri Olsa struct perf_env *env = data; 175668d702f7SJiri Olsa int core = -1, cpu = perf_env__get_cpu(env, map, idx); 175768d702f7SJiri Olsa 175868d702f7SJiri Olsa if (cpu != -1) { 175968d702f7SJiri Olsa int socket_id = env->cpu[cpu].socket_id; 176068d702f7SJiri Olsa 176168d702f7SJiri Olsa /* 176268d702f7SJiri Olsa * Encode socket in upper 16 bits 176368d702f7SJiri Olsa * core_id is relative to socket, and 176468d702f7SJiri Olsa * we need a global id. So we combine 176568d702f7SJiri Olsa * socket + core id. 176668d702f7SJiri Olsa */ 176768d702f7SJiri Olsa core = (socket_id << 16) | (env->cpu[cpu].core_id & 0xffff); 176868d702f7SJiri Olsa } 176968d702f7SJiri Olsa 177068d702f7SJiri Olsa return core; 177168d702f7SJiri Olsa } 177268d702f7SJiri Olsa 177368d702f7SJiri Olsa static int perf_env__build_socket_map(struct perf_env *env, struct cpu_map *cpus, 177468d702f7SJiri Olsa struct cpu_map **sockp) 177568d702f7SJiri Olsa { 177668d702f7SJiri Olsa return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env); 177768d702f7SJiri Olsa } 177868d702f7SJiri Olsa 177968d702f7SJiri Olsa static int perf_env__build_core_map(struct perf_env *env, struct cpu_map *cpus, 178068d702f7SJiri Olsa struct cpu_map **corep) 178168d702f7SJiri Olsa { 178268d702f7SJiri Olsa return cpu_map__build_map(cpus, corep, perf_env__get_core, env); 178368d702f7SJiri Olsa } 178468d702f7SJiri Olsa 178568d702f7SJiri Olsa static int perf_stat__get_socket_file(struct cpu_map *map, int idx) 178668d702f7SJiri Olsa { 178768d702f7SJiri Olsa return perf_env__get_socket(map, idx, &perf_stat.session->header.env); 178868d702f7SJiri Olsa } 178968d702f7SJiri Olsa 179068d702f7SJiri Olsa static int perf_stat__get_core_file(struct cpu_map *map, int idx) 179168d702f7SJiri Olsa { 179268d702f7SJiri Olsa return perf_env__get_core(map, idx, &perf_stat.session->header.env); 179368d702f7SJiri Olsa } 179468d702f7SJiri Olsa 179568d702f7SJiri Olsa static int perf_stat_init_aggr_mode_file(struct perf_stat *st) 179668d702f7SJiri Olsa { 179768d702f7SJiri Olsa struct perf_env *env = &st->session->header.env; 179868d702f7SJiri Olsa 179968d702f7SJiri Olsa switch (stat_config.aggr_mode) { 180068d702f7SJiri Olsa case AGGR_SOCKET: 180168d702f7SJiri Olsa if (perf_env__build_socket_map(env, evsel_list->cpus, &aggr_map)) { 180268d702f7SJiri Olsa perror("cannot build socket map"); 180368d702f7SJiri Olsa return -1; 180468d702f7SJiri Olsa } 180568d702f7SJiri Olsa aggr_get_id = perf_stat__get_socket_file; 180668d702f7SJiri Olsa break; 180768d702f7SJiri Olsa case AGGR_CORE: 180868d702f7SJiri Olsa if (perf_env__build_core_map(env, evsel_list->cpus, &aggr_map)) { 180968d702f7SJiri Olsa perror("cannot build core map"); 181068d702f7SJiri Olsa return -1; 181168d702f7SJiri Olsa } 181268d702f7SJiri Olsa aggr_get_id = perf_stat__get_core_file; 181368d702f7SJiri Olsa break; 181468d702f7SJiri Olsa case AGGR_NONE: 181568d702f7SJiri Olsa case AGGR_GLOBAL: 181668d702f7SJiri Olsa case AGGR_THREAD: 181768d702f7SJiri Olsa case AGGR_UNSET: 181868d702f7SJiri Olsa default: 181968d702f7SJiri Olsa break; 182068d702f7SJiri Olsa } 182168d702f7SJiri Olsa 182268d702f7SJiri Olsa return 0; 182368d702f7SJiri Olsa } 182468d702f7SJiri Olsa 182544b1e60aSAndi Kleen static int topdown_filter_events(const char **attr, char **str, bool use_group) 182644b1e60aSAndi Kleen { 182744b1e60aSAndi Kleen int off = 0; 182844b1e60aSAndi Kleen int i; 182944b1e60aSAndi Kleen int len = 0; 183044b1e60aSAndi Kleen char *s; 183144b1e60aSAndi Kleen 183244b1e60aSAndi Kleen for (i = 0; attr[i]; i++) { 183344b1e60aSAndi Kleen if (pmu_have_event("cpu", attr[i])) { 183444b1e60aSAndi Kleen len += strlen(attr[i]) + 1; 183544b1e60aSAndi Kleen attr[i - off] = attr[i]; 183644b1e60aSAndi Kleen } else 183744b1e60aSAndi Kleen off++; 183844b1e60aSAndi Kleen } 183944b1e60aSAndi Kleen attr[i - off] = NULL; 184044b1e60aSAndi Kleen 184144b1e60aSAndi Kleen *str = malloc(len + 1 + 2); 184244b1e60aSAndi Kleen if (!*str) 184344b1e60aSAndi Kleen return -1; 184444b1e60aSAndi Kleen s = *str; 184544b1e60aSAndi Kleen if (i - off == 0) { 184644b1e60aSAndi Kleen *s = 0; 184744b1e60aSAndi Kleen return 0; 184844b1e60aSAndi Kleen } 184944b1e60aSAndi Kleen if (use_group) 185044b1e60aSAndi Kleen *s++ = '{'; 185144b1e60aSAndi Kleen for (i = 0; attr[i]; i++) { 185244b1e60aSAndi Kleen strcpy(s, attr[i]); 185344b1e60aSAndi Kleen s += strlen(s); 185444b1e60aSAndi Kleen *s++ = ','; 185544b1e60aSAndi Kleen } 185644b1e60aSAndi Kleen if (use_group) { 185744b1e60aSAndi Kleen s[-1] = '}'; 185844b1e60aSAndi Kleen *s = 0; 185944b1e60aSAndi Kleen } else 186044b1e60aSAndi Kleen s[-1] = 0; 186144b1e60aSAndi Kleen return 0; 186244b1e60aSAndi Kleen } 186344b1e60aSAndi Kleen 186444b1e60aSAndi Kleen __weak bool arch_topdown_check_group(bool *warn) 186544b1e60aSAndi Kleen { 186644b1e60aSAndi Kleen *warn = false; 186744b1e60aSAndi Kleen return false; 186844b1e60aSAndi Kleen } 186944b1e60aSAndi Kleen 187044b1e60aSAndi Kleen __weak void arch_topdown_group_warn(void) 187144b1e60aSAndi Kleen { 187244b1e60aSAndi Kleen } 187344b1e60aSAndi Kleen 18742cba3ffbSIngo Molnar /* 18752cba3ffbSIngo Molnar * Add default attributes, if there were no attributes specified or 18762cba3ffbSIngo Molnar * if -d/--detailed, -d -d or -d -d -d is used: 18772cba3ffbSIngo Molnar */ 18782cba3ffbSIngo Molnar static int add_default_attributes(void) 18792cba3ffbSIngo Molnar { 188044b1e60aSAndi Kleen int err; 18819dec4473SAndi Kleen struct perf_event_attr default_attrs0[] = { 1882b070a547SArnaldo Carvalho de Melo 1883b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 1884b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CONTEXT_SWITCHES }, 1885b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_CPU_MIGRATIONS }, 1886b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_PAGE_FAULTS }, 1887b070a547SArnaldo Carvalho de Melo 1888b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES }, 18899dec4473SAndi Kleen }; 18909dec4473SAndi Kleen struct perf_event_attr frontend_attrs[] = { 1891b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 18929dec4473SAndi Kleen }; 18939dec4473SAndi Kleen struct perf_event_attr backend_attrs[] = { 1894b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 18959dec4473SAndi Kleen }; 18969dec4473SAndi Kleen struct perf_event_attr default_attrs1[] = { 1897b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_INSTRUCTIONS }, 1898b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 1899b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_BRANCH_MISSES }, 1900b070a547SArnaldo Carvalho de Melo 1901b070a547SArnaldo Carvalho de Melo }; 1902b070a547SArnaldo Carvalho de Melo 1903b070a547SArnaldo Carvalho de Melo /* 1904b070a547SArnaldo Carvalho de Melo * Detailed stats (-d), covering the L1 and last level data caches: 1905b070a547SArnaldo Carvalho de Melo */ 1906b070a547SArnaldo Carvalho de Melo struct perf_event_attr detailed_attrs[] = { 1907b070a547SArnaldo Carvalho de Melo 1908b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1909b070a547SArnaldo Carvalho de Melo .config = 1910b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 1911b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1912b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1913b070a547SArnaldo Carvalho de Melo 1914b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1915b070a547SArnaldo Carvalho de Melo .config = 1916b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 1917b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1918b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1919b070a547SArnaldo Carvalho de Melo 1920b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1921b070a547SArnaldo Carvalho de Melo .config = 1922b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_LL << 0 | 1923b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1924b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1925b070a547SArnaldo Carvalho de Melo 1926b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1927b070a547SArnaldo Carvalho de Melo .config = 1928b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_LL << 0 | 1929b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1930b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1931b070a547SArnaldo Carvalho de Melo }; 1932b070a547SArnaldo Carvalho de Melo 1933b070a547SArnaldo Carvalho de Melo /* 1934b070a547SArnaldo Carvalho de Melo * Very detailed stats (-d -d), covering the instruction cache and the TLB caches: 1935b070a547SArnaldo Carvalho de Melo */ 1936b070a547SArnaldo Carvalho de Melo struct perf_event_attr very_detailed_attrs[] = { 1937b070a547SArnaldo Carvalho de Melo 1938b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1939b070a547SArnaldo Carvalho de Melo .config = 1940b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1I << 0 | 1941b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1942b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1943b070a547SArnaldo Carvalho de Melo 1944b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1945b070a547SArnaldo Carvalho de Melo .config = 1946b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1I << 0 | 1947b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1948b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1949b070a547SArnaldo Carvalho de Melo 1950b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1951b070a547SArnaldo Carvalho de Melo .config = 1952b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_DTLB << 0 | 1953b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1954b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1955b070a547SArnaldo Carvalho de Melo 1956b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1957b070a547SArnaldo Carvalho de Melo .config = 1958b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_DTLB << 0 | 1959b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1960b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1961b070a547SArnaldo Carvalho de Melo 1962b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1963b070a547SArnaldo Carvalho de Melo .config = 1964b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_ITLB << 0 | 1965b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1966b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1967b070a547SArnaldo Carvalho de Melo 1968b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1969b070a547SArnaldo Carvalho de Melo .config = 1970b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_ITLB << 0 | 1971b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_READ << 8) | 1972b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1973b070a547SArnaldo Carvalho de Melo 1974b070a547SArnaldo Carvalho de Melo }; 1975b070a547SArnaldo Carvalho de Melo 1976b070a547SArnaldo Carvalho de Melo /* 1977b070a547SArnaldo Carvalho de Melo * Very, very detailed stats (-d -d -d), adding prefetch events: 1978b070a547SArnaldo Carvalho de Melo */ 1979b070a547SArnaldo Carvalho de Melo struct perf_event_attr very_very_detailed_attrs[] = { 1980b070a547SArnaldo Carvalho de Melo 1981b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1982b070a547SArnaldo Carvalho de Melo .config = 1983b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 1984b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 1985b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) }, 1986b070a547SArnaldo Carvalho de Melo 1987b070a547SArnaldo Carvalho de Melo { .type = PERF_TYPE_HW_CACHE, 1988b070a547SArnaldo Carvalho de Melo .config = 1989b070a547SArnaldo Carvalho de Melo PERF_COUNT_HW_CACHE_L1D << 0 | 1990b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | 1991b070a547SArnaldo Carvalho de Melo (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) }, 1992b070a547SArnaldo Carvalho de Melo }; 1993b070a547SArnaldo Carvalho de Melo 19942cba3ffbSIngo Molnar /* Set attrs if no event is selected and !null_run: */ 19952cba3ffbSIngo Molnar if (null_run) 19962cba3ffbSIngo Molnar return 0; 19972cba3ffbSIngo Molnar 19984cabc3d1SAndi Kleen if (transaction_run) { 19994cabc3d1SAndi Kleen if (pmu_have_event("cpu", "cycles-ct") && 20004cabc3d1SAndi Kleen pmu_have_event("cpu", "el-start")) 2001a454742cSJiri Olsa err = parse_events(evsel_list, transaction_attrs, NULL); 20024cabc3d1SAndi Kleen else 2003a454742cSJiri Olsa err = parse_events(evsel_list, transaction_limited_attrs, NULL); 2004a454742cSJiri Olsa if (err) { 20054cabc3d1SAndi Kleen fprintf(stderr, "Cannot set up transaction events\n"); 20064cabc3d1SAndi Kleen return -1; 20074cabc3d1SAndi Kleen } 20084cabc3d1SAndi Kleen return 0; 20094cabc3d1SAndi Kleen } 20104cabc3d1SAndi Kleen 201144b1e60aSAndi Kleen if (topdown_run) { 201244b1e60aSAndi Kleen char *str = NULL; 201344b1e60aSAndi Kleen bool warn = false; 201444b1e60aSAndi Kleen 201544b1e60aSAndi Kleen if (stat_config.aggr_mode != AGGR_GLOBAL && 201644b1e60aSAndi Kleen stat_config.aggr_mode != AGGR_CORE) { 201744b1e60aSAndi Kleen pr_err("top down event configuration requires --per-core mode\n"); 201844b1e60aSAndi Kleen return -1; 201944b1e60aSAndi Kleen } 202044b1e60aSAndi Kleen stat_config.aggr_mode = AGGR_CORE; 202144b1e60aSAndi Kleen if (nr_cgroups || !target__has_cpu(&target)) { 202244b1e60aSAndi Kleen pr_err("top down event configuration requires system-wide mode (-a)\n"); 202344b1e60aSAndi Kleen return -1; 202444b1e60aSAndi Kleen } 202544b1e60aSAndi Kleen 202644b1e60aSAndi Kleen if (!force_metric_only) 202744b1e60aSAndi Kleen metric_only = true; 202844b1e60aSAndi Kleen if (topdown_filter_events(topdown_attrs, &str, 202944b1e60aSAndi Kleen arch_topdown_check_group(&warn)) < 0) { 203044b1e60aSAndi Kleen pr_err("Out of memory\n"); 203144b1e60aSAndi Kleen return -1; 203244b1e60aSAndi Kleen } 203344b1e60aSAndi Kleen if (topdown_attrs[0] && str) { 203444b1e60aSAndi Kleen if (warn) 203544b1e60aSAndi Kleen arch_topdown_group_warn(); 203644b1e60aSAndi Kleen err = parse_events(evsel_list, str, NULL); 203744b1e60aSAndi Kleen if (err) { 203844b1e60aSAndi Kleen fprintf(stderr, 203944b1e60aSAndi Kleen "Cannot set up top down events %s: %d\n", 204044b1e60aSAndi Kleen str, err); 204144b1e60aSAndi Kleen free(str); 204244b1e60aSAndi Kleen return -1; 204344b1e60aSAndi Kleen } 204444b1e60aSAndi Kleen } else { 204544b1e60aSAndi Kleen fprintf(stderr, "System does not support topdown\n"); 204644b1e60aSAndi Kleen return -1; 204744b1e60aSAndi Kleen } 204844b1e60aSAndi Kleen free(str); 204944b1e60aSAndi Kleen } 205044b1e60aSAndi Kleen 20512cba3ffbSIngo Molnar if (!evsel_list->nr_entries) { 2052a1f3d567SNamhyung Kim if (target__has_cpu(&target)) 2053a1f3d567SNamhyung Kim default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; 2054a1f3d567SNamhyung Kim 20559dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) 20569dec4473SAndi Kleen return -1; 20579dec4473SAndi Kleen if (pmu_have_event("cpu", "stalled-cycles-frontend")) { 20589dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, 20599dec4473SAndi Kleen frontend_attrs) < 0) 20609dec4473SAndi Kleen return -1; 20619dec4473SAndi Kleen } 20629dec4473SAndi Kleen if (pmu_have_event("cpu", "stalled-cycles-backend")) { 20639dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, 20649dec4473SAndi Kleen backend_attrs) < 0) 20659dec4473SAndi Kleen return -1; 20669dec4473SAndi Kleen } 20679dec4473SAndi Kleen if (perf_evlist__add_default_attrs(evsel_list, default_attrs1) < 0) 20682cba3ffbSIngo Molnar return -1; 20692cba3ffbSIngo Molnar } 20702cba3ffbSIngo Molnar 20712cba3ffbSIngo Molnar /* Detailed events get appended to the event list: */ 20722cba3ffbSIngo Molnar 20732cba3ffbSIngo Molnar if (detailed_run < 1) 20742cba3ffbSIngo Molnar return 0; 20752cba3ffbSIngo Molnar 20762cba3ffbSIngo Molnar /* Append detailed run extra attributes: */ 207779695e1bSArnaldo Carvalho de Melo if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) 20782cba3ffbSIngo Molnar return -1; 20792cba3ffbSIngo Molnar 20802cba3ffbSIngo Molnar if (detailed_run < 2) 20812cba3ffbSIngo Molnar return 0; 20822cba3ffbSIngo Molnar 20832cba3ffbSIngo Molnar /* Append very detailed run extra attributes: */ 208479695e1bSArnaldo Carvalho de Melo if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) 20852cba3ffbSIngo Molnar return -1; 20862cba3ffbSIngo Molnar 20872cba3ffbSIngo Molnar if (detailed_run < 3) 20882cba3ffbSIngo Molnar return 0; 20892cba3ffbSIngo Molnar 20902cba3ffbSIngo Molnar /* Append very, very detailed run extra attributes: */ 209179695e1bSArnaldo Carvalho de Melo return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 20922cba3ffbSIngo Molnar } 20932cba3ffbSIngo Molnar 20948a59f3ccSJiri Olsa static const char * const stat_record_usage[] = { 20954979d0c7SJiri Olsa "perf stat record [<options>]", 20964979d0c7SJiri Olsa NULL, 20974979d0c7SJiri Olsa }; 20984979d0c7SJiri Olsa 20993ba78bd0SJiri Olsa static void init_features(struct perf_session *session) 21003ba78bd0SJiri Olsa { 21013ba78bd0SJiri Olsa int feat; 21023ba78bd0SJiri Olsa 21033ba78bd0SJiri Olsa for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) 21043ba78bd0SJiri Olsa perf_header__set_feat(&session->header, feat); 21053ba78bd0SJiri Olsa 21063ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_BUILD_ID); 21073ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); 21083ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); 21093ba78bd0SJiri Olsa perf_header__clear_feat(&session->header, HEADER_AUXTRACE); 21103ba78bd0SJiri Olsa } 21113ba78bd0SJiri Olsa 21124979d0c7SJiri Olsa static int __cmd_record(int argc, const char **argv) 21134979d0c7SJiri Olsa { 21144979d0c7SJiri Olsa struct perf_session *session; 21154979d0c7SJiri Olsa struct perf_data_file *file = &perf_stat.file; 21164979d0c7SJiri Olsa 21178a59f3ccSJiri Olsa argc = parse_options(argc, argv, stat_options, stat_record_usage, 21184979d0c7SJiri Olsa PARSE_OPT_STOP_AT_NON_OPTION); 21194979d0c7SJiri Olsa 21204979d0c7SJiri Olsa if (output_name) 21214979d0c7SJiri Olsa file->path = output_name; 21224979d0c7SJiri Olsa 2123e9d6db8eSJiri Olsa if (run_count != 1 || forever) { 2124e9d6db8eSJiri Olsa pr_err("Cannot use -r option with perf stat record.\n"); 2125e9d6db8eSJiri Olsa return -1; 2126e9d6db8eSJiri Olsa } 2127e9d6db8eSJiri Olsa 21284979d0c7SJiri Olsa session = perf_session__new(file, false, NULL); 21294979d0c7SJiri Olsa if (session == NULL) { 21304979d0c7SJiri Olsa pr_err("Perf session creation failed.\n"); 21314979d0c7SJiri Olsa return -1; 21324979d0c7SJiri Olsa } 21334979d0c7SJiri Olsa 21343ba78bd0SJiri Olsa init_features(session); 21353ba78bd0SJiri Olsa 21364979d0c7SJiri Olsa session->evlist = evsel_list; 21374979d0c7SJiri Olsa perf_stat.session = session; 21384979d0c7SJiri Olsa perf_stat.record = true; 21394979d0c7SJiri Olsa return argc; 21404979d0c7SJiri Olsa } 21414979d0c7SJiri Olsa 2142a56f9390SJiri Olsa static int process_stat_round_event(struct perf_tool *tool __maybe_unused, 2143a56f9390SJiri Olsa union perf_event *event, 2144a56f9390SJiri Olsa struct perf_session *session) 2145a56f9390SJiri Olsa { 2146e3b03b6cSAndi Kleen struct stat_round_event *stat_round = &event->stat_round; 2147a56f9390SJiri Olsa struct perf_evsel *counter; 2148a56f9390SJiri Olsa struct timespec tsh, *ts = NULL; 2149a56f9390SJiri Olsa const char **argv = session->header.env.cmdline_argv; 2150a56f9390SJiri Olsa int argc = session->header.env.nr_cmdline; 2151a56f9390SJiri Olsa 2152e5cadb93SArnaldo Carvalho de Melo evlist__for_each_entry(evsel_list, counter) 2153a56f9390SJiri Olsa perf_stat_process_counter(&stat_config, counter); 2154a56f9390SJiri Olsa 2155e3b03b6cSAndi Kleen if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) 2156e3b03b6cSAndi Kleen update_stats(&walltime_nsecs_stats, stat_round->time); 2157a56f9390SJiri Olsa 2158e3b03b6cSAndi Kleen if (stat_config.interval && stat_round->time) { 2159e3b03b6cSAndi Kleen tsh.tv_sec = stat_round->time / NSECS_PER_SEC; 2160e3b03b6cSAndi Kleen tsh.tv_nsec = stat_round->time % NSECS_PER_SEC; 2161a56f9390SJiri Olsa ts = &tsh; 2162a56f9390SJiri Olsa } 2163a56f9390SJiri Olsa 2164a56f9390SJiri Olsa print_counters(ts, argc, argv); 2165a56f9390SJiri Olsa return 0; 2166a56f9390SJiri Olsa } 2167a56f9390SJiri Olsa 216862ba18baSJiri Olsa static 216962ba18baSJiri Olsa int process_stat_config_event(struct perf_tool *tool __maybe_unused, 217062ba18baSJiri Olsa union perf_event *event, 217162ba18baSJiri Olsa struct perf_session *session __maybe_unused) 217262ba18baSJiri Olsa { 217368d702f7SJiri Olsa struct perf_stat *st = container_of(tool, struct perf_stat, tool); 217468d702f7SJiri Olsa 217562ba18baSJiri Olsa perf_event__read_stat_config(&stat_config, &event->stat_config); 217668d702f7SJiri Olsa 217789af4e05SJiri Olsa if (cpu_map__empty(st->cpus)) { 217889af4e05SJiri Olsa if (st->aggr_mode != AGGR_UNSET) 217989af4e05SJiri Olsa pr_warning("warning: processing task data, aggregation mode not set\n"); 218089af4e05SJiri Olsa return 0; 218189af4e05SJiri Olsa } 218289af4e05SJiri Olsa 218389af4e05SJiri Olsa if (st->aggr_mode != AGGR_UNSET) 218489af4e05SJiri Olsa stat_config.aggr_mode = st->aggr_mode; 218589af4e05SJiri Olsa 218668d702f7SJiri Olsa if (perf_stat.file.is_pipe) 218768d702f7SJiri Olsa perf_stat_init_aggr_mode(); 218868d702f7SJiri Olsa else 218968d702f7SJiri Olsa perf_stat_init_aggr_mode_file(st); 219068d702f7SJiri Olsa 219162ba18baSJiri Olsa return 0; 219262ba18baSJiri Olsa } 219362ba18baSJiri Olsa 21941975d36eSJiri Olsa static int set_maps(struct perf_stat *st) 21951975d36eSJiri Olsa { 21961975d36eSJiri Olsa if (!st->cpus || !st->threads) 21971975d36eSJiri Olsa return 0; 21981975d36eSJiri Olsa 21991975d36eSJiri Olsa if (WARN_ONCE(st->maps_allocated, "stats double allocation\n")) 22001975d36eSJiri Olsa return -EINVAL; 22011975d36eSJiri Olsa 22021975d36eSJiri Olsa perf_evlist__set_maps(evsel_list, st->cpus, st->threads); 22031975d36eSJiri Olsa 22041975d36eSJiri Olsa if (perf_evlist__alloc_stats(evsel_list, true)) 22051975d36eSJiri Olsa return -ENOMEM; 22061975d36eSJiri Olsa 22071975d36eSJiri Olsa st->maps_allocated = true; 22081975d36eSJiri Olsa return 0; 22091975d36eSJiri Olsa } 22101975d36eSJiri Olsa 22111975d36eSJiri Olsa static 22121975d36eSJiri Olsa int process_thread_map_event(struct perf_tool *tool __maybe_unused, 22131975d36eSJiri Olsa union perf_event *event, 22141975d36eSJiri Olsa struct perf_session *session __maybe_unused) 22151975d36eSJiri Olsa { 22161975d36eSJiri Olsa struct perf_stat *st = container_of(tool, struct perf_stat, tool); 22171975d36eSJiri Olsa 22181975d36eSJiri Olsa if (st->threads) { 22191975d36eSJiri Olsa pr_warning("Extra thread map event, ignoring.\n"); 22201975d36eSJiri Olsa return 0; 22211975d36eSJiri Olsa } 22221975d36eSJiri Olsa 22231975d36eSJiri Olsa st->threads = thread_map__new_event(&event->thread_map); 22241975d36eSJiri Olsa if (!st->threads) 22251975d36eSJiri Olsa return -ENOMEM; 22261975d36eSJiri Olsa 22271975d36eSJiri Olsa return set_maps(st); 22281975d36eSJiri Olsa } 22291975d36eSJiri Olsa 22301975d36eSJiri Olsa static 22311975d36eSJiri Olsa int process_cpu_map_event(struct perf_tool *tool __maybe_unused, 22321975d36eSJiri Olsa union perf_event *event, 22331975d36eSJiri Olsa struct perf_session *session __maybe_unused) 22341975d36eSJiri Olsa { 22351975d36eSJiri Olsa struct perf_stat *st = container_of(tool, struct perf_stat, tool); 22361975d36eSJiri Olsa struct cpu_map *cpus; 22371975d36eSJiri Olsa 22381975d36eSJiri Olsa if (st->cpus) { 22391975d36eSJiri Olsa pr_warning("Extra cpu map event, ignoring.\n"); 22401975d36eSJiri Olsa return 0; 22411975d36eSJiri Olsa } 22421975d36eSJiri Olsa 22431975d36eSJiri Olsa cpus = cpu_map__new_data(&event->cpu_map.data); 22441975d36eSJiri Olsa if (!cpus) 22451975d36eSJiri Olsa return -ENOMEM; 22461975d36eSJiri Olsa 22471975d36eSJiri Olsa st->cpus = cpus; 22481975d36eSJiri Olsa return set_maps(st); 22491975d36eSJiri Olsa } 22501975d36eSJiri Olsa 22518a59f3ccSJiri Olsa static const char * const stat_report_usage[] = { 2252ba6039b6SJiri Olsa "perf stat report [<options>]", 2253ba6039b6SJiri Olsa NULL, 2254ba6039b6SJiri Olsa }; 2255ba6039b6SJiri Olsa 2256ba6039b6SJiri Olsa static struct perf_stat perf_stat = { 2257ba6039b6SJiri Olsa .tool = { 2258ba6039b6SJiri Olsa .attr = perf_event__process_attr, 2259fa6ea781SJiri Olsa .event_update = perf_event__process_event_update, 22601975d36eSJiri Olsa .thread_map = process_thread_map_event, 22611975d36eSJiri Olsa .cpu_map = process_cpu_map_event, 226262ba18baSJiri Olsa .stat_config = process_stat_config_event, 2263a56f9390SJiri Olsa .stat = perf_event__process_stat_event, 2264a56f9390SJiri Olsa .stat_round = process_stat_round_event, 2265ba6039b6SJiri Olsa }, 226689af4e05SJiri Olsa .aggr_mode = AGGR_UNSET, 2267ba6039b6SJiri Olsa }; 2268ba6039b6SJiri Olsa 2269ba6039b6SJiri Olsa static int __cmd_report(int argc, const char **argv) 2270ba6039b6SJiri Olsa { 2271ba6039b6SJiri Olsa struct perf_session *session; 2272ba6039b6SJiri Olsa const struct option options[] = { 2273ba6039b6SJiri Olsa OPT_STRING('i', "input", &input_name, "file", "input file name"), 227489af4e05SJiri Olsa OPT_SET_UINT(0, "per-socket", &perf_stat.aggr_mode, 227589af4e05SJiri Olsa "aggregate counts per processor socket", AGGR_SOCKET), 227689af4e05SJiri Olsa OPT_SET_UINT(0, "per-core", &perf_stat.aggr_mode, 227789af4e05SJiri Olsa "aggregate counts per physical processor core", AGGR_CORE), 227889af4e05SJiri Olsa OPT_SET_UINT('A', "no-aggr", &perf_stat.aggr_mode, 227989af4e05SJiri Olsa "disable CPU count aggregation", AGGR_NONE), 2280ba6039b6SJiri Olsa OPT_END() 2281ba6039b6SJiri Olsa }; 2282ba6039b6SJiri Olsa struct stat st; 2283ba6039b6SJiri Olsa int ret; 2284ba6039b6SJiri Olsa 22858a59f3ccSJiri Olsa argc = parse_options(argc, argv, options, stat_report_usage, 0); 2286ba6039b6SJiri Olsa 2287ba6039b6SJiri Olsa if (!input_name || !strlen(input_name)) { 2288ba6039b6SJiri Olsa if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 2289ba6039b6SJiri Olsa input_name = "-"; 2290ba6039b6SJiri Olsa else 2291ba6039b6SJiri Olsa input_name = "perf.data"; 2292ba6039b6SJiri Olsa } 2293ba6039b6SJiri Olsa 2294ba6039b6SJiri Olsa perf_stat.file.path = input_name; 2295ba6039b6SJiri Olsa perf_stat.file.mode = PERF_DATA_MODE_READ; 2296ba6039b6SJiri Olsa 2297ba6039b6SJiri Olsa session = perf_session__new(&perf_stat.file, false, &perf_stat.tool); 2298ba6039b6SJiri Olsa if (session == NULL) 2299ba6039b6SJiri Olsa return -1; 2300ba6039b6SJiri Olsa 2301ba6039b6SJiri Olsa perf_stat.session = session; 2302ba6039b6SJiri Olsa stat_config.output = stderr; 2303ba6039b6SJiri Olsa evsel_list = session->evlist; 2304ba6039b6SJiri Olsa 2305ba6039b6SJiri Olsa ret = perf_session__process_events(session); 2306ba6039b6SJiri Olsa if (ret) 2307ba6039b6SJiri Olsa return ret; 2308ba6039b6SJiri Olsa 2309ba6039b6SJiri Olsa perf_session__delete(session); 2310ba6039b6SJiri Olsa return 0; 2311ba6039b6SJiri Olsa } 2312ba6039b6SJiri Olsa 23131d037ca1SIrina Tirdea int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 231486470930SIngo Molnar { 2315b070a547SArnaldo Carvalho de Melo const char * const stat_usage[] = { 2316b070a547SArnaldo Carvalho de Melo "perf stat [<options>] [<command>]", 2317b070a547SArnaldo Carvalho de Melo NULL 2318b070a547SArnaldo Carvalho de Melo }; 2319cc03c542SNamhyung Kim int status = -EINVAL, run_idx; 23204aa9015fSStephane Eranian const char *mode; 23215821522eSJiri Olsa FILE *output = stderr; 2322ec0d3d1fSJiri Olsa unsigned int interval; 2323ba6039b6SJiri Olsa const char * const stat_subcommands[] = { "record", "report" }; 232442202dd5SIngo Molnar 23255af52b51SStephane Eranian setlocale(LC_ALL, ""); 23265af52b51SStephane Eranian 2327334fe7a3SNamhyung Kim evsel_list = perf_evlist__new(); 2328361c99a6SArnaldo Carvalho de Melo if (evsel_list == NULL) 2329361c99a6SArnaldo Carvalho de Melo return -ENOMEM; 2330361c99a6SArnaldo Carvalho de Melo 23311669e509SWang Nan parse_events__shrink_config_terms(); 23324979d0c7SJiri Olsa argc = parse_options_subcommand(argc, argv, stat_options, stat_subcommands, 23334979d0c7SJiri Olsa (const char **) stat_usage, 2334a0541234SAnton Blanchard PARSE_OPT_STOP_AT_NON_OPTION); 2335fb4605baSAndi Kleen perf_stat__init_shadow_stats(); 2336d7470b6aSStephane Eranian 23376edb78a2SJiri Olsa if (csv_sep) { 23386edb78a2SJiri Olsa csv_output = true; 23396edb78a2SJiri Olsa if (!strcmp(csv_sep, "\\t")) 23406edb78a2SJiri Olsa csv_sep = "\t"; 23416edb78a2SJiri Olsa } else 23426edb78a2SJiri Olsa csv_sep = DEFAULT_SEPARATOR; 23436edb78a2SJiri Olsa 23444979d0c7SJiri Olsa if (argc && !strncmp(argv[0], "rec", 3)) { 23454979d0c7SJiri Olsa argc = __cmd_record(argc, argv); 23464979d0c7SJiri Olsa if (argc < 0) 23474979d0c7SJiri Olsa return -1; 2348ba6039b6SJiri Olsa } else if (argc && !strncmp(argv[0], "rep", 3)) 2349ba6039b6SJiri Olsa return __cmd_report(argc, argv); 23504979d0c7SJiri Olsa 2351ec0d3d1fSJiri Olsa interval = stat_config.interval; 2352ec0d3d1fSJiri Olsa 23534979d0c7SJiri Olsa /* 23544979d0c7SJiri Olsa * For record command the -o is already taken care of. 23554979d0c7SJiri Olsa */ 23564979d0c7SJiri Olsa if (!STAT_RECORD && output_name && strcmp(output_name, "-")) 23574aa9015fSStephane Eranian output = NULL; 23584aa9015fSStephane Eranian 235956f3bae7SJim Cromie if (output_name && output_fd) { 236056f3bae7SJim Cromie fprintf(stderr, "cannot use both --output and --log-fd\n"); 2361e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "o", 1); 2362e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "log-fd", 0); 2363cc03c542SNamhyung Kim goto out; 236456f3bae7SJim Cromie } 2365fc3e4d07SStephane Eranian 236654b50916SAndi Kleen if (metric_only && stat_config.aggr_mode == AGGR_THREAD) { 236754b50916SAndi Kleen fprintf(stderr, "--metric-only is not supported with --per-thread\n"); 236854b50916SAndi Kleen goto out; 236954b50916SAndi Kleen } 237054b50916SAndi Kleen 237154b50916SAndi Kleen if (metric_only && run_count > 1) { 237254b50916SAndi Kleen fprintf(stderr, "--metric-only is not supported with -r\n"); 237354b50916SAndi Kleen goto out; 237454b50916SAndi Kleen } 237554b50916SAndi Kleen 2376fc3e4d07SStephane Eranian if (output_fd < 0) { 2377fc3e4d07SStephane Eranian fprintf(stderr, "argument to --log-fd must be a > 0\n"); 2378e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "log-fd", 0); 2379cc03c542SNamhyung Kim goto out; 2380fc3e4d07SStephane Eranian } 2381fc3e4d07SStephane Eranian 23824aa9015fSStephane Eranian if (!output) { 23834aa9015fSStephane Eranian struct timespec tm; 23844aa9015fSStephane Eranian mode = append_file ? "a" : "w"; 23854aa9015fSStephane Eranian 23864aa9015fSStephane Eranian output = fopen(output_name, mode); 23874aa9015fSStephane Eranian if (!output) { 23884aa9015fSStephane Eranian perror("failed to create output file"); 2389fceda7feSDavid Ahern return -1; 23904aa9015fSStephane Eranian } 23914aa9015fSStephane Eranian clock_gettime(CLOCK_REALTIME, &tm); 23924aa9015fSStephane Eranian fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); 2393fc3e4d07SStephane Eranian } else if (output_fd > 0) { 239456f3bae7SJim Cromie mode = append_file ? "a" : "w"; 239556f3bae7SJim Cromie output = fdopen(output_fd, mode); 239656f3bae7SJim Cromie if (!output) { 239756f3bae7SJim Cromie perror("Failed opening logfd"); 239856f3bae7SJim Cromie return -errno; 239956f3bae7SJim Cromie } 24004aa9015fSStephane Eranian } 24014aa9015fSStephane Eranian 24025821522eSJiri Olsa stat_config.output = output; 24035821522eSJiri Olsa 2404d7470b6aSStephane Eranian /* 2405d7470b6aSStephane Eranian * let the spreadsheet do the pretty-printing 2406d7470b6aSStephane Eranian */ 2407d7470b6aSStephane Eranian if (csv_output) { 240861a9f324SJim Cromie /* User explicitly passed -B? */ 2409d7470b6aSStephane Eranian if (big_num_opt == 1) { 2410d7470b6aSStephane Eranian fprintf(stderr, "-B option not supported with -x\n"); 2411e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "B", 1); 2412e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "x", 1); 2413cc03c542SNamhyung Kim goto out; 2414d7470b6aSStephane Eranian } else /* Nope, so disable big number formatting */ 2415d7470b6aSStephane Eranian big_num = false; 2416d7470b6aSStephane Eranian } else if (big_num_opt == 0) /* User passed --no-big-num */ 2417d7470b6aSStephane Eranian big_num = false; 2418d7470b6aSStephane Eranian 2419602ad878SArnaldo Carvalho de Melo if (!argc && target__none(&target)) 2420e0547311SJiri Olsa usage_with_options(stat_usage, stat_options); 2421ac3063bdSDavid Ahern 2422a7e191c3SFrederik Deweerdt if (run_count < 0) { 2423cc03c542SNamhyung Kim pr_err("Run count must be a positive number\n"); 2424e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "r", 1); 2425cc03c542SNamhyung Kim goto out; 2426a7e191c3SFrederik Deweerdt } else if (run_count == 0) { 2427a7e191c3SFrederik Deweerdt forever = true; 2428a7e191c3SFrederik Deweerdt run_count = 1; 2429a7e191c3SFrederik Deweerdt } 243086470930SIngo Molnar 2431421a50f3SJiri Olsa if ((stat_config.aggr_mode == AGGR_THREAD) && !target__has_task(&target)) { 243232b8af82SJiri Olsa fprintf(stderr, "The --per-thread option is only available " 243332b8af82SJiri Olsa "when monitoring via -p -t options.\n"); 2434e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "p", 1); 2435e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "t", 1); 243632b8af82SJiri Olsa goto out; 243732b8af82SJiri Olsa } 243832b8af82SJiri Olsa 243932b8af82SJiri Olsa /* 244032b8af82SJiri Olsa * no_aggr, cgroup are for system-wide only 244132b8af82SJiri Olsa * --per-thread is aggregated per thread, we dont mix it with cpu mode 244232b8af82SJiri Olsa */ 2443421a50f3SJiri Olsa if (((stat_config.aggr_mode != AGGR_GLOBAL && 2444421a50f3SJiri Olsa stat_config.aggr_mode != AGGR_THREAD) || nr_cgroups) && 2445602ad878SArnaldo Carvalho de Melo !target__has_cpu(&target)) { 2446023695d9SStephane Eranian fprintf(stderr, "both cgroup and no-aggregation " 2447023695d9SStephane Eranian "modes only available in system-wide mode\n"); 2448023695d9SStephane Eranian 2449e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "G", 1); 2450e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "A", 1); 2451e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "a", 1); 2452cc03c542SNamhyung Kim goto out; 2453d7e7a451SStephane Eranian } 2454d7e7a451SStephane Eranian 24552cba3ffbSIngo Molnar if (add_default_attributes()) 2456c6264defSIngo Molnar goto out; 245786470930SIngo Molnar 2458602ad878SArnaldo Carvalho de Melo target__validate(&target); 24595c98d466SArnaldo Carvalho de Melo 246077a6f014SNamhyung Kim if (perf_evlist__create_maps(evsel_list, &target) < 0) { 2461602ad878SArnaldo Carvalho de Melo if (target__has_task(&target)) { 24625c98d466SArnaldo Carvalho de Melo pr_err("Problems finding threads of monitor\n"); 2463e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "p", 1); 2464e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "t", 1); 2465602ad878SArnaldo Carvalho de Melo } else if (target__has_cpu(&target)) { 246660d567e2SArnaldo Carvalho de Melo perror("failed to parse CPUs map"); 2467e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "C", 1); 2468e0547311SJiri Olsa parse_options_usage(NULL, stat_options, "a", 1); 2469cc03c542SNamhyung Kim } 2470cc03c542SNamhyung Kim goto out; 247160d567e2SArnaldo Carvalho de Melo } 247232b8af82SJiri Olsa 247332b8af82SJiri Olsa /* 247432b8af82SJiri Olsa * Initialize thread_map with comm names, 247532b8af82SJiri Olsa * so we could print it out on output. 247632b8af82SJiri Olsa */ 2477421a50f3SJiri Olsa if (stat_config.aggr_mode == AGGR_THREAD) 247832b8af82SJiri Olsa thread_map__read_comms(evsel_list->threads); 247932b8af82SJiri Olsa 248013370a9bSStephane Eranian if (interval && interval < 100) { 248119afd104SKan Liang if (interval < 10) { 248219afd104SKan Liang pr_err("print interval must be >= 10ms\n"); 2483e0547311SJiri Olsa parse_options_usage(stat_usage, stat_options, "I", 1); 248403ad9747SArnaldo Carvalho de Melo goto out; 248519afd104SKan Liang } else 248619afd104SKan Liang pr_warning("print interval < 100ms. " 248719afd104SKan Liang "The overhead percentage could be high in some cases. " 248819afd104SKan Liang "Please proceed with caution.\n"); 248913370a9bSStephane Eranian } 2490c45c6ea2SStephane Eranian 2491d134ffb9SArnaldo Carvalho de Melo if (perf_evlist__alloc_stats(evsel_list, interval)) 249203ad9747SArnaldo Carvalho de Melo goto out; 2493d6d901c2SZhang, Yanmin 249486ee6e18SStephane Eranian if (perf_stat_init_aggr_mode()) 249503ad9747SArnaldo Carvalho de Melo goto out; 249686ee6e18SStephane Eranian 249786470930SIngo Molnar /* 249886470930SIngo Molnar * We dont want to block the signals - that would cause 249986470930SIngo Molnar * child tasks to inherit that and Ctrl-C would not work. 250086470930SIngo Molnar * What we want is for Ctrl-C to work in the exec()-ed 250186470930SIngo Molnar * task, but being ignored by perf stat itself: 250286470930SIngo Molnar */ 2503f7b7c26eSPeter Zijlstra atexit(sig_atexit); 2504a7e191c3SFrederik Deweerdt if (!forever) 250586470930SIngo Molnar signal(SIGINT, skip_signal); 250613370a9bSStephane Eranian signal(SIGCHLD, skip_signal); 250786470930SIngo Molnar signal(SIGALRM, skip_signal); 250886470930SIngo Molnar signal(SIGABRT, skip_signal); 250986470930SIngo Molnar 251042202dd5SIngo Molnar status = 0; 2511a7e191c3SFrederik Deweerdt for (run_idx = 0; forever || run_idx < run_count; run_idx++) { 251242202dd5SIngo Molnar if (run_count != 1 && verbose) 25134aa9015fSStephane Eranian fprintf(output, "[ perf stat: executing run #%d ... ]\n", 25144aa9015fSStephane Eranian run_idx + 1); 2515f9cef0a9SIngo Molnar 251642202dd5SIngo Molnar status = run_perf_stat(argc, argv); 2517a7e191c3SFrederik Deweerdt if (forever && status != -1) { 2518d4f63a47SJiri Olsa print_counters(NULL, argc, argv); 2519254ecbc7SJiri Olsa perf_stat__reset_stats(); 2520a7e191c3SFrederik Deweerdt } 252142202dd5SIngo Molnar } 252242202dd5SIngo Molnar 2523a7e191c3SFrederik Deweerdt if (!forever && status != -1 && !interval) 2524d4f63a47SJiri Olsa print_counters(NULL, argc, argv); 2525d134ffb9SArnaldo Carvalho de Melo 25264979d0c7SJiri Olsa if (STAT_RECORD) { 25274979d0c7SJiri Olsa /* 25284979d0c7SJiri Olsa * We synthesize the kernel mmap record just so that older tools 25294979d0c7SJiri Olsa * don't emit warnings about not being able to resolve symbols 25304979d0c7SJiri Olsa * due to /proc/sys/kernel/kptr_restrict settings and instear provide 25314979d0c7SJiri Olsa * a saner message about no samples being in the perf.data file. 25324979d0c7SJiri Olsa * 25334979d0c7SJiri Olsa * This also serves to suppress a warning about f_header.data.size == 0 25348b99b1a4SJiri Olsa * in header.c at the moment 'perf stat record' gets introduced, which 25358b99b1a4SJiri Olsa * is not really needed once we start adding the stat specific PERF_RECORD_ 25368b99b1a4SJiri Olsa * records, but the need to suppress the kptr_restrict messages in older 25378b99b1a4SJiri Olsa * tools remain -acme 25384979d0c7SJiri Olsa */ 25394979d0c7SJiri Olsa int fd = perf_data_file__fd(&perf_stat.file); 25404979d0c7SJiri Olsa int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat, 25414979d0c7SJiri Olsa process_synthesized_event, 25424979d0c7SJiri Olsa &perf_stat.session->machines.host); 25434979d0c7SJiri Olsa if (err) { 25444979d0c7SJiri Olsa pr_warning("Couldn't synthesize the kernel mmap record, harmless, " 25454979d0c7SJiri Olsa "older tools may produce warnings about this file\n."); 25464979d0c7SJiri Olsa } 25474979d0c7SJiri Olsa 25487aad0c32SJiri Olsa if (!interval) { 25497aad0c32SJiri Olsa if (WRITE_STAT_ROUND_EVENT(walltime_nsecs_stats.max, FINAL)) 25507aad0c32SJiri Olsa pr_err("failed to write stat round event\n"); 25517aad0c32SJiri Olsa } 25527aad0c32SJiri Olsa 2553664c98d4SJiri Olsa if (!perf_stat.file.is_pipe) { 25544979d0c7SJiri Olsa perf_stat.session->header.data_size += perf_stat.bytes_written; 25554979d0c7SJiri Olsa perf_session__write_header(perf_stat.session, evsel_list, fd, true); 2556664c98d4SJiri Olsa } 25574979d0c7SJiri Olsa 25584979d0c7SJiri Olsa perf_session__delete(perf_stat.session); 25594979d0c7SJiri Olsa } 25604979d0c7SJiri Olsa 2561544c2ae7SMasami Hiramatsu perf_stat__exit_aggr_mode(); 2562d134ffb9SArnaldo Carvalho de Melo perf_evlist__free_stats(evsel_list); 25630015e2e1SArnaldo Carvalho de Melo out: 25640015e2e1SArnaldo Carvalho de Melo perf_evlist__delete(evsel_list); 256542202dd5SIngo Molnar return status; 256686470930SIngo Molnar } 2567