Merge remote-tracking branch 'acme/perf-tools' into perf-tools-next
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 10 Mar 2023 21:43:17 +0000 (18:43 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 10 Mar 2023 21:43:17 +0000 (18:43 -0300)
To pick up perf-tools fixes just merged upstream.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1  2 
tools/perf/builtin-stat.c
tools/perf/util/stat.c
tools/perf/util/stat.h

index d70b1ec8859445bedc9ea59f6d1a9f53290e76a3,fa7c40956d0fa957c95b8755db61d83e0ee1cc4b..cfc75517e143982c89f5fb7c6fed8fddb7c2218a
  
  static void print_counters(struct timespec *ts, int argc, const char **argv);
  
 -/* Default events used for perf stat -T */
 -static const char *transaction_attrs = {
 -      "task-clock,"
 -      "{"
 -      "instructions,"
 -      "cycles,"
 -      "cpu/cycles-t/,"
 -      "cpu/tx-start/,"
 -      "cpu/el-start/,"
 -      "cpu/cycles-ct/"
 -      "}"
 -};
 -
 -/* More limited version when the CPU does not have all events. */
 -static const char * transaction_limited_attrs = {
 -      "task-clock,"
 -      "{"
 -      "instructions,"
 -      "cycles,"
 -      "cpu/cycles-t/,"
 -      "cpu/tx-start/"
 -      "}"
 -};
 -
 -static const char * topdown_attrs[] = {
 -      "topdown-total-slots",
 -      "topdown-slots-retired",
 -      "topdown-recovery-bubbles",
 -      "topdown-fetch-bubbles",
 -      "topdown-slots-issued",
 -      NULL,
 -};
 -
 -static const char *topdown_metric_attrs[] = {
 -      "slots",
 -      "topdown-retiring",
 -      "topdown-bad-spec",
 -      "topdown-fe-bound",
 -      "topdown-be-bound",
 -      NULL,
 -};
 -
 -static const char *topdown_metric_L2_attrs[] = {
 -      "slots",
 -      "topdown-retiring",
 -      "topdown-bad-spec",
 -      "topdown-fe-bound",
 -      "topdown-be-bound",
 -      "topdown-heavy-ops",
 -      "topdown-br-mispredict",
 -      "topdown-fetch-lat",
 -      "topdown-mem-bound",
 -      NULL,
 -};
 -
 -#define TOPDOWN_MAX_LEVEL                     2
 -
 -static const char *smi_cost_attrs = {
 -      "{"
 -      "msr/aperf/,"
 -      "msr/smi/,"
 -      "cycles"
 -      "}"
 -};
 -
  static struct evlist  *evsel_list;
  static bool all_counters_use_bpf = true;
  
@@@ -424,6 -489,7 +424,6 @@@ static void process_counters(void
  
        perf_stat_merge_counters(&stat_config, evsel_list);
        perf_stat_process_percore(&stat_config, evsel_list);
 -      perf_stat_process_shadow_stats(&stat_config, evsel_list);
  }
  
  static void process_interval(void)
        clock_gettime(CLOCK_MONOTONIC, &ts);
        diff_timespec(&rs, &ts, &ref_time);
  
 -      perf_stat__reset_shadow_per_stat(&rt_stat);
        evlist__reset_aggr_stats(evsel_list);
  
        if (read_counters(&rs) == 0)
@@@ -472,12 -539,7 +472,7 @@@ static int enable_counters(void
                        return err;
        }
  
-       /*
-        * We need to enable counters only if:
-        * - we don't have tracee (attaching to task or cpu)
-        * - we have initial delay configured
-        */
-       if (!target__none(&target)) {
+       if (!target__enable_on_exec(&target)) {
                if (!all_counters_use_bpf)
                        evlist__enable(evsel_list);
        }
@@@ -847,7 -909,7 +842,7 @@@ try_again_reset
                        return err;
        }
  
-       if (stat_config.initial_delay) {
+       if (target.initial_delay) {
                pr_info(EVLIST_DISABLED_MSG);
        } else {
                err = enable_counters();
        if (forks)
                evlist__start_workload(evsel_list);
  
-       if (stat_config.initial_delay > 0) {
-               usleep(stat_config.initial_delay * USEC_PER_MSEC);
+       if (target.initial_delay > 0) {
+               usleep(target.initial_delay * USEC_PER_MSEC);
                err = enable_counters();
                if (err)
                        return -1;
                evlist__copy_prev_raw_counts(evsel_list);
                evlist__reset_prev_raw_counts(evsel_list);
                evlist__reset_aggr_stats(evsel_list);
 -              perf_stat__reset_shadow_per_stat(&rt_stat);
        } else {
                update_stats(&walltime_nsecs_stats, t1 - t0);
                update_rusage_stats(&ru_stats, &stat_config.ru_data);
@@@ -1180,7 -1243,7 +1175,7 @@@ static struct option stat_options[] = 
                     "aggregate counts per thread", AGGR_THREAD),
        OPT_SET_UINT(0, "per-node", &stat_config.aggr_mode,
                     "aggregate counts per numa node", AGGR_NODE),
-       OPT_INTEGER('D', "delay", &stat_config.initial_delay,
+       OPT_INTEGER('D', "delay", &target.initial_delay,
                    "ms to wait before starting measurement after program start (-1: start with events disabled)"),
        OPT_CALLBACK_NOOPT(0, "metric-only", &stat_config.metric_only, NULL,
                        "Only print computed metrics. No raw values", enable_metric_only),
                       "don't group metric events, impacts multiplexing"),
        OPT_BOOLEAN(0, "metric-no-merge", &stat_config.metric_no_merge,
                       "don't try to share events between metrics in a group"),
 +      OPT_BOOLEAN(0, "metric-no-threshold", &stat_config.metric_no_threshold,
 +                     "don't try to share events between metrics in a group  "),
        OPT_BOOLEAN(0, "topdown", &topdown_run,
                        "measure top-down statistics"),
        OPT_UINTEGER(0, "td-level", &stat_config.topdown_level,
@@@ -1655,6 -1716,7 +1650,6 @@@ static int perf_stat_init_aggr_mode_fil
   */
  static int add_default_attributes(void)
  {
 -      int err;
        struct perf_event_attr default_attrs0[] = {
  
    { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK            },
                return 0;
  
        if (transaction_run) {
 -              struct parse_events_error errinfo;
                /* Handle -T as -M transaction. Once platform specific metrics
                 * support has been added to the json files, all architectures
                 * will use this approach. To determine transaction support
                 * on an architecture test for such a metric name.
                 */
 -              if (metricgroup__has_metric("transaction")) {
 -                      return metricgroup__parse_groups(evsel_list, "transaction",
 -                                                       stat_config.metric_no_group,
 -                                                       stat_config.metric_no_merge,
 -                                                       stat_config.user_requested_cpu_list,
 -                                                       stat_config.system_wide,
 -                                                       &stat_config.metric_events);
 -              }
 -
 -              parse_events_error__init(&errinfo);
 -              if (pmu_have_event("cpu", "cycles-ct") &&
 -                  pmu_have_event("cpu", "el-start"))
 -                      err = parse_events(evsel_list, transaction_attrs,
 -                                         &errinfo);
 -              else
 -                      err = parse_events(evsel_list,
 -                                         transaction_limited_attrs,
 -                                         &errinfo);
 -              if (err) {
 -                      fprintf(stderr, "Cannot set up transaction events\n");
 -                      parse_events_error__print(&errinfo, transaction_attrs);
 +              if (!metricgroup__has_metric("transaction")) {
 +                      pr_err("Missing transaction metrics");
 +                      return -1;
                }
 -              parse_events_error__exit(&errinfo);
 -              return err ? -1 : 0;
 +              return metricgroup__parse_groups(evsel_list, "transaction",
 +                                              stat_config.metric_no_group,
 +                                              stat_config.metric_no_merge,
 +                                              stat_config.metric_no_threshold,
 +                                              stat_config.user_requested_cpu_list,
 +                                              stat_config.system_wide,
 +                                              &stat_config.metric_events);
        }
  
        if (smi_cost) {
 -              struct parse_events_error errinfo;
                int smi;
  
                if (sysfs__read_int(FREEZE_ON_SMI_PATH, &smi) < 0) {
 -                      fprintf(stderr, "freeze_on_smi is not supported.\n");
 +                      pr_err("freeze_on_smi is not supported.");
                        return -1;
                }
  
                        smi_reset = true;
                }
  
 -              if (!pmu_have_event("msr", "aperf") ||
 -                  !pmu_have_event("msr", "smi")) {
 -                      fprintf(stderr, "To measure SMI cost, it needs "
 -                              "msr/aperf/, msr/smi/ and cpu/cycles/ support\n");
 +              if (!metricgroup__has_metric("smi")) {
 +                      pr_err("Missing smi metrics");
                        return -1;
                }
 +
                if (!force_metric_only)
                        stat_config.metric_only = true;
  
 -              parse_events_error__init(&errinfo);
 -              err = parse_events(evsel_list, smi_cost_attrs, &errinfo);
 -              if (err) {
 -                      parse_events_error__print(&errinfo, smi_cost_attrs);
 -                      fprintf(stderr, "Cannot set up SMI cost events\n");
 -              }
 -              parse_events_error__exit(&errinfo);
 -              return err ? -1 : 0;
 +              return metricgroup__parse_groups(evsel_list, "smi",
 +                                              stat_config.metric_no_group,
 +                                              stat_config.metric_no_merge,
 +                                              stat_config.metric_no_threshold,
 +                                              stat_config.user_requested_cpu_list,
 +                                              stat_config.system_wide,
 +                                              &stat_config.metric_events);
        }
  
        if (topdown_run) {
 -              const char **metric_attrs = topdown_metric_attrs;
 -              unsigned int max_level = 1;
 -              char *str = NULL;
 -              bool warn = false;
 -              const char *pmu_name = arch_get_topdown_pmu_name(evsel_list, true);
 +              unsigned int max_level = metricgroups__topdown_max_level();
 +              char str[] = "TopdownL1";
  
                if (!force_metric_only)
                        stat_config.metric_only = true;
  
 -              if (pmu_have_event(pmu_name, topdown_metric_L2_attrs[5])) {
 -                      metric_attrs = topdown_metric_L2_attrs;
 -                      max_level = 2;
 +              if (!max_level) {
 +                      pr_err("Topdown requested but the topdown metric groups aren't present.\n"
 +                              "(See perf list the metric groups have names like TopdownL1)");
 +                      return -1;
                }
 -
                if (stat_config.topdown_level > max_level) {
                        pr_err("Invalid top-down metrics level. The max level is %u.\n", max_level);
                        return -1;
                } else if (!stat_config.topdown_level)
 -                      stat_config.topdown_level = max_level;
 -
 -              if (topdown_filter_events(metric_attrs, &str, 1, pmu_name) < 0) {
 -                      pr_err("Out of memory\n");
 -                      return -1;
 -              }
 -
 -              if (metric_attrs[0] && str) {
 -                      if (!stat_config.interval && !stat_config.metric_only) {
 -                              fprintf(stat_config.output,
 -                                      "Topdown accuracy may decrease when measuring long periods.\n"
 -                                      "Please print the result regularly, e.g. -I1000\n");
 -                      }
 -                      goto setup_metrics;
 -              }
 -
 -              zfree(&str);
 -
 -              if (stat_config.aggr_mode != AGGR_GLOBAL &&
 -                  stat_config.aggr_mode != AGGR_CORE) {
 -                      pr_err("top down event configuration requires --per-core mode\n");
 -                      return -1;
 -              }
 -              stat_config.aggr_mode = AGGR_CORE;
 -              if (nr_cgroups || !target__has_cpu(&target)) {
 -                      pr_err("top down event configuration requires system-wide mode (-a)\n");
 -                      return -1;
 -              }
 +                      stat_config.topdown_level = 1;
  
 -              if (topdown_filter_events(topdown_attrs, &str,
 -                              arch_topdown_check_group(&warn),
 -                              pmu_name) < 0) {
 -                      pr_err("Out of memory\n");
 -                      return -1;
 +              if (!stat_config.interval && !stat_config.metric_only) {
 +                      fprintf(stat_config.output,
 +                              "Topdown accuracy may decrease when measuring long periods.\n"
 +                              "Please print the result regularly, e.g. -I1000\n");
                }
 -
 -              if (topdown_attrs[0] && str) {
 -                      struct parse_events_error errinfo;
 -                      if (warn)
 -                              arch_topdown_group_warn();
 -setup_metrics:
 -                      parse_events_error__init(&errinfo);
 -                      err = parse_events(evsel_list, str, &errinfo);
 -                      if (err) {
 -                              fprintf(stderr,
 -                                      "Cannot set up top down events %s: %d\n",
 -                                      str, err);
 -                              parse_events_error__print(&errinfo, str);
 -                              parse_events_error__exit(&errinfo);
 -                              free(str);
 -                              return -1;
 -                      }
 -                      parse_events_error__exit(&errinfo);
 -              } else {
 -                      fprintf(stderr, "System does not support topdown\n");
 +              str[8] = stat_config.topdown_level + '0';
 +              if (metricgroup__parse_groups(evsel_list, str,
 +                                              /*metric_no_group=*/false,
 +                                              /*metric_no_merge=*/false,
 +                                              /*metric_no_threshold=*/true,
 +                                              stat_config.user_requested_cpu_list,
 +                                              stat_config.system_wide,
 +                                              &stat_config.metric_events) < 0)
                        return -1;
 -              }
 -              free(str);
        }
  
        if (!stat_config.topdown_level)
 -              stat_config.topdown_level = TOPDOWN_MAX_LEVEL;
 +              stat_config.topdown_level = 1;
  
        if (!evsel_list->core.nr_entries) {
 +              /* No events so add defaults. */
                if (target__has_cpu(&target))
                        default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
  
                }
                if (evlist__add_default_attrs(evsel_list, default_attrs1) < 0)
                        return -1;
 +              /*
 +               * Add TopdownL1 metrics if they exist. To minimize
 +               * multiplexing, don't request threshold computation.
 +               */
 +              if (metricgroup__has_metric("TopdownL1") &&
 +                  metricgroup__parse_groups(evsel_list, "TopdownL1",
 +                                          /*metric_no_group=*/false,
 +                                          /*metric_no_merge=*/false,
 +                                          /*metric_no_threshold=*/true,
 +                                          stat_config.user_requested_cpu_list,
 +                                          stat_config.system_wide,
 +                                          &stat_config.metric_events) < 0)
 +                      return -1;
                /* Platform specific attrs */
                if (evlist__add_default_attrs(evsel_list, default_null_attrs) < 0)
                        return -1;
@@@ -2129,6 -2239,8 +2124,6 @@@ static int __cmd_report(int argc, cons
                        input_name = "perf.data";
        }
  
 -      perf_stat__init_shadow_stats();
 -
        perf_stat.data.path = input_name;
        perf_stat.data.mode = PERF_DATA_MODE_READ;
  
@@@ -2402,12 -2514,12 +2397,12 @@@ int cmd_stat(int argc, const char **arg
                metricgroup__parse_groups(evsel_list, metrics,
                                        stat_config.metric_no_group,
                                        stat_config.metric_no_merge,
 +                                      stat_config.metric_no_threshold,
                                        stat_config.user_requested_cpu_list,
                                        stat_config.system_wide,
                                        &stat_config.metric_events);
                zfree(&metrics);
        }
 -      perf_stat__init_shadow_stats();
  
        if (add_default_attributes())
                goto out;
diff --combined tools/perf/util/stat.c
index 4abfd87c5352a25010f6304cde0e104cf04f0b18,a07473703c6dd65fe2f8ba1295704aa45d6dd4ae..0f7b8a8cdea6367ded8d1dcd2ec180efa1135230
@@@ -77,6 -77,55 +77,6 @@@ double rel_stddev_stats(double stddev, 
        return pct;
  }
  
 -bool __perf_stat_evsel__is(struct evsel *evsel, enum perf_stat_evsel_id id)
 -{
 -      struct perf_stat_evsel *ps = evsel->stats;
 -
 -      return ps->id == id;
 -}
 -
 -#define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
 -static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
 -      ID(NONE,                x),
 -      ID(CYCLES_IN_TX,        cpu/cycles-t/),
 -      ID(TRANSACTION_START,   cpu/tx-start/),
 -      ID(ELISION_START,       cpu/el-start/),
 -      ID(CYCLES_IN_TX_CP,     cpu/cycles-ct/),
 -      ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
 -      ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
 -      ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
 -      ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
 -      ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
 -      ID(TOPDOWN_RETIRING, topdown-retiring),
 -      ID(TOPDOWN_BAD_SPEC, topdown-bad-spec),
 -      ID(TOPDOWN_FE_BOUND, topdown-fe-bound),
 -      ID(TOPDOWN_BE_BOUND, topdown-be-bound),
 -      ID(TOPDOWN_HEAVY_OPS, topdown-heavy-ops),
 -      ID(TOPDOWN_BR_MISPREDICT, topdown-br-mispredict),
 -      ID(TOPDOWN_FETCH_LAT, topdown-fetch-lat),
 -      ID(TOPDOWN_MEM_BOUND, topdown-mem-bound),
 -      ID(SMI_NUM, msr/smi/),
 -      ID(APERF, msr/aperf/),
 -};
 -#undef ID
 -
 -static void perf_stat_evsel_id_init(struct evsel *evsel)
 -{
 -      struct perf_stat_evsel *ps = evsel->stats;
 -      int i;
 -
 -      /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
 -
 -      for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
 -              if (!strcmp(evsel__name(evsel), id_str[i]) ||
 -                  (strstr(evsel__name(evsel), id_str[i]) && evsel->pmu_name
 -                   && strstr(evsel__name(evsel), evsel->pmu_name))) {
 -                      ps->id = i;
 -                      break;
 -              }
 -      }
 -}
 -
  static void evsel__reset_aggr_stats(struct evsel *evsel)
  {
        struct perf_stat_evsel *ps = evsel->stats;
@@@ -136,6 -185,7 +136,6 @@@ static int evsel__alloc_stat_priv(struc
                return -ENOMEM;
        }
  
 -      perf_stat_evsel_id_init(evsel);
        evsel__reset_stat_priv(evsel);
        return 0;
  }
@@@ -648,6 -698,30 +648,6 @@@ void perf_stat_process_percore(struct p
                evsel__process_percore(evsel);
  }
  
 -static void evsel__update_shadow_stats(struct evsel *evsel)
 -{
 -      struct perf_stat_evsel *ps = evsel->stats;
 -      int i;
 -
 -      if (ps->aggr == NULL)
 -              return;
 -
 -      for (i = 0; i < ps->nr_aggr; i++) {
 -              struct perf_counts_values *aggr_counts = &ps->aggr[i].counts;
 -
 -              perf_stat__update_shadow_stats(evsel, aggr_counts->val, i, &rt_stat);
 -      }
 -}
 -
 -void perf_stat_process_shadow_stats(struct perf_stat_config *config __maybe_unused,
 -                                  struct evlist *evlist)
 -{
 -      struct evsel *evsel;
 -
 -      evlist__for_each_entry(evlist, evsel)
 -              evsel__update_shadow_stats(evsel);
 -}
 -
  int perf_event__process_stat_event(struct perf_session *session,
                                   union perf_event *event)
  {
@@@ -768,11 -842,7 +768,7 @@@ int create_perf_stat_counter(struct evs
        if (evsel__is_group_leader(evsel)) {
                attr->disabled = 1;
  
-               /*
-                * In case of initial_delay we enable tracee
-                * events manually.
-                */
-               if (target__none(target) && !config->initial_delay)
+               if (target__enable_on_exec(target))
                        attr->enable_on_exec = 1;
        }
  
diff --combined tools/perf/util/stat.h
index 41204547b76bce90c43b0de2c4dce3dbac149d3c,bf1794ebc916d56d25de420d811cd33e01141545..e35e188237c81dbe75ddaed86f560c8aed6ca11b
@@@ -19,6 -19,30 +19,6 @@@ struct stats 
        u64 max, min;
  };
  
 -enum perf_stat_evsel_id {
 -      PERF_STAT_EVSEL_ID__NONE = 0,
 -      PERF_STAT_EVSEL_ID__CYCLES_IN_TX,
 -      PERF_STAT_EVSEL_ID__TRANSACTION_START,
 -      PERF_STAT_EVSEL_ID__ELISION_START,
 -      PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_TOTAL_SLOTS,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_ISSUED,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_RETIRED,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_BUBBLES,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_RECOVERY_BUBBLES,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_RETIRING,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_BAD_SPEC,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_FE_BOUND,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_BE_BOUND,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_HEAVY_OPS,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_BR_MISPREDICT,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_LAT,
 -      PERF_STAT_EVSEL_ID__TOPDOWN_MEM_BOUND,
 -      PERF_STAT_EVSEL_ID__SMI_NUM,
 -      PERF_STAT_EVSEL_ID__APERF,
 -      PERF_STAT_EVSEL_ID__MAX,
 -};
 -
  /* hold aggregated event info */
  struct perf_stat_aggr {
        /* aggregated values */
@@@ -35,6 -59,8 +35,6 @@@
  struct perf_stat_evsel {
        /* used for repeated runs */
        struct stats             res_stats;
 -      /* evsel id for quick check */
 -      enum perf_stat_evsel_id  id;
        /* number of allocated 'aggr' */
        int                      nr_aggr;
        /* aggregated event values */
@@@ -55,6 -81,55 +55,6 @@@ enum aggr_mode 
        AGGR_MAX
  };
  
 -enum {
 -      CTX_BIT_USER    = 1 << 0,
 -      CTX_BIT_KERNEL  = 1 << 1,
 -      CTX_BIT_HV      = 1 << 2,
 -      CTX_BIT_HOST    = 1 << 3,
 -      CTX_BIT_IDLE    = 1 << 4,
 -      CTX_BIT_MAX     = 1 << 5,
 -};
 -
 -#define NUM_CTX CTX_BIT_MAX
 -
 -enum stat_type {
 -      STAT_NONE = 0,
 -      STAT_NSECS,
 -      STAT_CYCLES,
 -      STAT_STALLED_CYCLES_FRONT,
 -      STAT_STALLED_CYCLES_BACK,
 -      STAT_BRANCHES,
 -      STAT_CACHEREFS,
 -      STAT_L1_DCACHE,
 -      STAT_L1_ICACHE,
 -      STAT_LL_CACHE,
 -      STAT_ITLB_CACHE,
 -      STAT_DTLB_CACHE,
 -      STAT_CYCLES_IN_TX,
 -      STAT_TRANSACTION,
 -      STAT_ELISION,
 -      STAT_TOPDOWN_TOTAL_SLOTS,
 -      STAT_TOPDOWN_SLOTS_ISSUED,
 -      STAT_TOPDOWN_SLOTS_RETIRED,
 -      STAT_TOPDOWN_FETCH_BUBBLES,
 -      STAT_TOPDOWN_RECOVERY_BUBBLES,
 -      STAT_TOPDOWN_RETIRING,
 -      STAT_TOPDOWN_BAD_SPEC,
 -      STAT_TOPDOWN_FE_BOUND,
 -      STAT_TOPDOWN_BE_BOUND,
 -      STAT_TOPDOWN_HEAVY_OPS,
 -      STAT_TOPDOWN_BR_MISPREDICT,
 -      STAT_TOPDOWN_FETCH_LAT,
 -      STAT_TOPDOWN_MEM_BOUND,
 -      STAT_SMI_NUM,
 -      STAT_APERF,
 -      STAT_MAX
 -};
 -
 -struct runtime_stat {
 -      struct rblist value_list;
 -};
 -
  struct rusage_stats {
        struct stats ru_utime_usec_stat;
        struct stats ru_stime_usec_stat;
@@@ -84,7 -159,6 +84,7 @@@ struct perf_stat_config 
        bool                     no_csv_summary;
        bool                     metric_no_group;
        bool                     metric_no_merge;
 +      bool                     metric_no_threshold;
        bool                     stop_read_counter;
        bool                     iostat_run;
        char                     *user_requested_cpu_list;
        FILE                    *output;
        unsigned int             interval;
        unsigned int             timeout;
-       int                      initial_delay;
        unsigned int             unit_width;
        unsigned int             metric_only_len;
        int                      times;
@@@ -149,6 -222,12 +148,6 @@@ static inline void update_rusage_stats(
  struct evsel;
  struct evlist;
  
 -bool __perf_stat_evsel__is(struct evsel *evsel, enum perf_stat_evsel_id id);
 -
 -#define perf_stat_evsel__is(evsel, id) \
 -      __perf_stat_evsel__is(evsel, PERF_STAT_EVSEL_ID__ ## id)
 -
 -extern struct runtime_stat rt_stat;
  extern struct stats walltime_nsecs_stats;
  extern struct rusage_stats ru_stats;
  
@@@ -157,7 -236,13 +156,7 @@@ typedef void (*print_metric_t)(struct p
                               const char *fmt, double val);
  typedef void (*new_line_t)(struct perf_stat_config *config, void *ctx);
  
 -void runtime_stat__init(struct runtime_stat *st);
 -void runtime_stat__exit(struct runtime_stat *st);
 -void perf_stat__init_shadow_stats(void);
  void perf_stat__reset_shadow_stats(void);
 -void perf_stat__reset_shadow_per_stat(struct runtime_stat *st);
 -void perf_stat__update_shadow_stats(struct evsel *counter, u64 count,
 -                                  int map_idx, struct runtime_stat *st);
  struct perf_stat_output_ctx {
        void *ctx;
        print_metric_t print_metric;
  
  void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                   struct evsel *evsel,
 -                                 double avg, int map_idx,
 +                                 double avg, int aggr_idx,
                                   struct perf_stat_output_ctx *out,
 -                                 struct rblist *metric_events,
 -                                 struct runtime_stat *st);
 +                                 struct rblist *metric_events);
  
  int evlist__alloc_stats(struct perf_stat_config *config,
                        struct evlist *evlist, bool alloc_raw);
@@@ -186,6 -272,7 +185,6 @@@ int perf_stat_process_counter(struct pe
                              struct evsel *counter);
  void perf_stat_merge_counters(struct perf_stat_config *config, struct evlist *evlist);
  void perf_stat_process_percore(struct perf_stat_config *config, struct evlist *evlist);
 -void perf_stat_process_shadow_stats(struct perf_stat_config *config, struct evlist *evlist);
  
  struct perf_tool;
  union perf_event;
@@@ -207,5 -294,5 +206,5 @@@ void evlist__print_counters(struct evli
                            struct target *_target, struct timespec *ts, int argc, const char **argv);
  
  struct metric_expr;
 -double test_generic_metric(struct metric_expr *mexp, int map_idx, struct runtime_stat *st);
 +double test_generic_metric(struct metric_expr *mexp, int aggr_idx);
  #endif