162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <errno.h> 362306a36Sopenharmony_ci#include <linux/err.h> 462306a36Sopenharmony_ci#include <inttypes.h> 562306a36Sopenharmony_ci#include <math.h> 662306a36Sopenharmony_ci#include <string.h> 762306a36Sopenharmony_ci#include "counts.h" 862306a36Sopenharmony_ci#include "cpumap.h" 962306a36Sopenharmony_ci#include "debug.h" 1062306a36Sopenharmony_ci#include "header.h" 1162306a36Sopenharmony_ci#include "stat.h" 1262306a36Sopenharmony_ci#include "session.h" 1362306a36Sopenharmony_ci#include "target.h" 1462306a36Sopenharmony_ci#include "evlist.h" 1562306a36Sopenharmony_ci#include "evsel.h" 1662306a36Sopenharmony_ci#include "thread_map.h" 1762306a36Sopenharmony_ci#include "util/hashmap.h" 1862306a36Sopenharmony_ci#include <linux/zalloc.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_civoid update_stats(struct stats *stats, u64 val) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci double delta; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci stats->n++; 2562306a36Sopenharmony_ci delta = val - stats->mean; 2662306a36Sopenharmony_ci stats->mean += delta / stats->n; 2762306a36Sopenharmony_ci stats->M2 += delta*(val - stats->mean); 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (val > stats->max) 3062306a36Sopenharmony_ci stats->max = val; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if (val < stats->min) 3362306a36Sopenharmony_ci stats->min = val; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cidouble avg_stats(struct stats *stats) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci return stats->mean; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * (\Sum n_i^2) - ((\Sum n_i)^2)/n 4562306a36Sopenharmony_ci * s^2 = ------------------------------- 4662306a36Sopenharmony_ci * n - 1 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * http://en.wikipedia.org/wiki/Stddev 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * The std dev of the mean is related to the std dev by: 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * s 5362306a36Sopenharmony_ci * s_mean = ------- 5462306a36Sopenharmony_ci * sqrt(n) 5562306a36Sopenharmony_ci * 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_cidouble stddev_stats(struct stats *stats) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci double variance, variance_mean; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (stats->n < 2) 6262306a36Sopenharmony_ci return 0.0; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci variance = stats->M2 / (stats->n - 1); 6562306a36Sopenharmony_ci variance_mean = variance / stats->n; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci return sqrt(variance_mean); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cidouble rel_stddev_stats(double stddev, double avg) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci double pct = 0.0; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (avg) 7562306a36Sopenharmony_ci pct = 100.0 * stddev/avg; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return pct; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic void evsel__reset_aggr_stats(struct evsel *evsel) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 8362306a36Sopenharmony_ci struct perf_stat_aggr *aggr = ps->aggr; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (aggr) 8662306a36Sopenharmony_ci memset(aggr, 0, sizeof(*aggr) * ps->nr_aggr); 8762306a36Sopenharmony_ci} 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void evsel__reset_stat_priv(struct evsel *evsel) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci init_stats(&ps->res_stats); 9462306a36Sopenharmony_ci evsel__reset_aggr_stats(evsel); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic int evsel__alloc_aggr_stats(struct evsel *evsel, int nr_aggr) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (ps == NULL) 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci ps->nr_aggr = nr_aggr; 10562306a36Sopenharmony_ci ps->aggr = calloc(nr_aggr, sizeof(*ps->aggr)); 10662306a36Sopenharmony_ci if (ps->aggr == NULL) 10762306a36Sopenharmony_ci return -ENOMEM; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci return 0; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ciint evlist__alloc_aggr_stats(struct evlist *evlist, int nr_aggr) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct evsel *evsel; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 11762306a36Sopenharmony_ci if (evsel__alloc_aggr_stats(evsel, nr_aggr) < 0) 11862306a36Sopenharmony_ci return -1; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci return 0; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic int evsel__alloc_stat_priv(struct evsel *evsel, int nr_aggr) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci struct perf_stat_evsel *ps; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci ps = zalloc(sizeof(*ps)); 12862306a36Sopenharmony_ci if (ps == NULL) 12962306a36Sopenharmony_ci return -ENOMEM; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci evsel->stats = ps; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci if (nr_aggr && evsel__alloc_aggr_stats(evsel, nr_aggr) < 0) { 13462306a36Sopenharmony_ci evsel->stats = NULL; 13562306a36Sopenharmony_ci free(ps); 13662306a36Sopenharmony_ci return -ENOMEM; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci evsel__reset_stat_priv(evsel); 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic void evsel__free_stat_priv(struct evsel *evsel) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (ps) { 14862306a36Sopenharmony_ci zfree(&ps->aggr); 14962306a36Sopenharmony_ci zfree(&ps->group_data); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci zfree(&evsel->stats); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic int evsel__alloc_prev_raw_counts(struct evsel *evsel) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci int cpu_map_nr = evsel__nr_cpus(evsel); 15762306a36Sopenharmony_ci int nthreads = perf_thread_map__nr(evsel->core.threads); 15862306a36Sopenharmony_ci struct perf_counts *counts; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci counts = perf_counts__new(cpu_map_nr, nthreads); 16162306a36Sopenharmony_ci if (counts) 16262306a36Sopenharmony_ci evsel->prev_raw_counts = counts; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci return counts ? 0 : -ENOMEM; 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_cistatic void evsel__free_prev_raw_counts(struct evsel *evsel) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci perf_counts__delete(evsel->prev_raw_counts); 17062306a36Sopenharmony_ci evsel->prev_raw_counts = NULL; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_cistatic void evsel__reset_prev_raw_counts(struct evsel *evsel) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci if (evsel->prev_raw_counts) 17662306a36Sopenharmony_ci perf_counts__reset(evsel->prev_raw_counts); 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int evsel__alloc_stats(struct evsel *evsel, int nr_aggr, bool alloc_raw) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci if (evsel__alloc_stat_priv(evsel, nr_aggr) < 0 || 18262306a36Sopenharmony_ci evsel__alloc_counts(evsel) < 0 || 18362306a36Sopenharmony_ci (alloc_raw && evsel__alloc_prev_raw_counts(evsel) < 0)) 18462306a36Sopenharmony_ci return -ENOMEM; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci return 0; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciint evlist__alloc_stats(struct perf_stat_config *config, 19062306a36Sopenharmony_ci struct evlist *evlist, bool alloc_raw) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci struct evsel *evsel; 19362306a36Sopenharmony_ci int nr_aggr = 0; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (config && config->aggr_map) 19662306a36Sopenharmony_ci nr_aggr = config->aggr_map->nr; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 19962306a36Sopenharmony_ci if (evsel__alloc_stats(evsel, nr_aggr, alloc_raw)) 20062306a36Sopenharmony_ci goto out_free; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci return 0; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ciout_free: 20662306a36Sopenharmony_ci evlist__free_stats(evlist); 20762306a36Sopenharmony_ci return -1; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_civoid evlist__free_stats(struct evlist *evlist) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct evsel *evsel; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 21562306a36Sopenharmony_ci evsel__free_stat_priv(evsel); 21662306a36Sopenharmony_ci evsel__free_counts(evsel); 21762306a36Sopenharmony_ci evsel__free_prev_raw_counts(evsel); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_civoid evlist__reset_stats(struct evlist *evlist) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct evsel *evsel; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 22662306a36Sopenharmony_ci evsel__reset_stat_priv(evsel); 22762306a36Sopenharmony_ci evsel__reset_counts(evsel); 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_civoid evlist__reset_aggr_stats(struct evlist *evlist) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct evsel *evsel; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) 23662306a36Sopenharmony_ci evsel__reset_aggr_stats(evsel); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_civoid evlist__reset_prev_raw_counts(struct evlist *evlist) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci struct evsel *evsel; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) 24462306a36Sopenharmony_ci evsel__reset_prev_raw_counts(evsel); 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic void evsel__copy_prev_raw_counts(struct evsel *evsel) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci int idx, nthreads = perf_thread_map__nr(evsel->core.threads); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci for (int thread = 0; thread < nthreads; thread++) { 25262306a36Sopenharmony_ci perf_cpu_map__for_each_idx(idx, evsel__cpus(evsel)) { 25362306a36Sopenharmony_ci *perf_counts(evsel->counts, idx, thread) = 25462306a36Sopenharmony_ci *perf_counts(evsel->prev_raw_counts, idx, thread); 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci } 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_civoid evlist__copy_prev_raw_counts(struct evlist *evlist) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci struct evsel *evsel; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) 26462306a36Sopenharmony_ci evsel__copy_prev_raw_counts(evsel); 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic void evsel__copy_res_stats(struct evsel *evsel) 26862306a36Sopenharmony_ci{ 26962306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* 27262306a36Sopenharmony_ci * For GLOBAL aggregation mode, it updates the counts for each run 27362306a36Sopenharmony_ci * in the evsel->stats.res_stats. See perf_stat_process_counter(). 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ci *ps->aggr[0].counts.values = avg_stats(&ps->res_stats); 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_civoid evlist__copy_res_stats(struct perf_stat_config *config, struct evlist *evlist) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci struct evsel *evsel; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci if (config->aggr_mode != AGGR_GLOBAL) 28362306a36Sopenharmony_ci return; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) 28662306a36Sopenharmony_ci evsel__copy_res_stats(evsel); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic size_t pkg_id_hash(long __key, void *ctx __maybe_unused) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci uint64_t *key = (uint64_t *) __key; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci return *key & 0xffffffff; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic bool pkg_id_equal(long __key1, long __key2, void *ctx __maybe_unused) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci uint64_t *key1 = (uint64_t *) __key1; 29962306a36Sopenharmony_ci uint64_t *key2 = (uint64_t *) __key2; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci return *key1 == *key2; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic int check_per_pkg(struct evsel *counter, struct perf_counts_values *vals, 30562306a36Sopenharmony_ci int cpu_map_idx, bool *skip) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct hashmap *mask = counter->per_pkg_mask; 30862306a36Sopenharmony_ci struct perf_cpu_map *cpus = evsel__cpus(counter); 30962306a36Sopenharmony_ci struct perf_cpu cpu = perf_cpu_map__cpu(cpus, cpu_map_idx); 31062306a36Sopenharmony_ci int s, d, ret = 0; 31162306a36Sopenharmony_ci uint64_t *key; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci *skip = false; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci if (!counter->per_pkg) 31662306a36Sopenharmony_ci return 0; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci if (perf_cpu_map__empty(cpus)) 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (!mask) { 32262306a36Sopenharmony_ci mask = hashmap__new(pkg_id_hash, pkg_id_equal, NULL); 32362306a36Sopenharmony_ci if (IS_ERR(mask)) 32462306a36Sopenharmony_ci return -ENOMEM; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci counter->per_pkg_mask = mask; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* 33062306a36Sopenharmony_ci * we do not consider an event that has not run as a good 33162306a36Sopenharmony_ci * instance to mark a package as used (skip=1). Otherwise 33262306a36Sopenharmony_ci * we may run into a situation where the first CPU in a package 33362306a36Sopenharmony_ci * is not running anything, yet the second is, and this function 33462306a36Sopenharmony_ci * would mark the package as used after the first CPU and would 33562306a36Sopenharmony_ci * not read the values from the second CPU. 33662306a36Sopenharmony_ci */ 33762306a36Sopenharmony_ci if (!(vals->run && vals->ena)) 33862306a36Sopenharmony_ci return 0; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci s = cpu__get_socket_id(cpu); 34162306a36Sopenharmony_ci if (s < 0) 34262306a36Sopenharmony_ci return -1; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * On multi-die system, die_id > 0. On no-die system, die_id = 0. 34662306a36Sopenharmony_ci * We use hashmap(socket, die) to check the used socket+die pair. 34762306a36Sopenharmony_ci */ 34862306a36Sopenharmony_ci d = cpu__get_die_id(cpu); 34962306a36Sopenharmony_ci if (d < 0) 35062306a36Sopenharmony_ci return -1; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci key = malloc(sizeof(*key)); 35362306a36Sopenharmony_ci if (!key) 35462306a36Sopenharmony_ci return -ENOMEM; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci *key = (uint64_t)d << 32 | s; 35762306a36Sopenharmony_ci if (hashmap__find(mask, key, NULL)) { 35862306a36Sopenharmony_ci *skip = true; 35962306a36Sopenharmony_ci free(key); 36062306a36Sopenharmony_ci } else 36162306a36Sopenharmony_ci ret = hashmap__add(mask, key, 1); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return ret; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic bool evsel__count_has_error(struct evsel *evsel, 36762306a36Sopenharmony_ci struct perf_counts_values *count, 36862306a36Sopenharmony_ci struct perf_stat_config *config) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci /* the evsel was failed already */ 37162306a36Sopenharmony_ci if (evsel->err || evsel->counts->scaled == -1) 37262306a36Sopenharmony_ci return true; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci /* this is meaningful for CPU aggregation modes only */ 37562306a36Sopenharmony_ci if (config->aggr_mode == AGGR_GLOBAL) 37662306a36Sopenharmony_ci return false; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* it's considered ok when it actually ran */ 37962306a36Sopenharmony_ci if (count->ena != 0 && count->run != 0) 38062306a36Sopenharmony_ci return false; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci return true; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic int 38662306a36Sopenharmony_ciprocess_counter_values(struct perf_stat_config *config, struct evsel *evsel, 38762306a36Sopenharmony_ci int cpu_map_idx, int thread, 38862306a36Sopenharmony_ci struct perf_counts_values *count) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 39162306a36Sopenharmony_ci static struct perf_counts_values zero; 39262306a36Sopenharmony_ci bool skip = false; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (check_per_pkg(evsel, count, cpu_map_idx, &skip)) { 39562306a36Sopenharmony_ci pr_err("failed to read per-pkg counter\n"); 39662306a36Sopenharmony_ci return -1; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if (skip) 40062306a36Sopenharmony_ci count = &zero; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci if (!evsel->snapshot) 40362306a36Sopenharmony_ci evsel__compute_deltas(evsel, cpu_map_idx, thread, count); 40462306a36Sopenharmony_ci perf_counts_values__scale(count, config->scale, NULL); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci if (config->aggr_mode == AGGR_THREAD) { 40762306a36Sopenharmony_ci struct perf_counts_values *aggr_counts = &ps->aggr[thread].counts; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * Skip value 0 when enabling --per-thread globally, 41162306a36Sopenharmony_ci * otherwise too many 0 output. 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_ci if (count->val == 0 && config->system_wide) 41462306a36Sopenharmony_ci return 0; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci ps->aggr[thread].nr++; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci aggr_counts->val += count->val; 41962306a36Sopenharmony_ci aggr_counts->ena += count->ena; 42062306a36Sopenharmony_ci aggr_counts->run += count->run; 42162306a36Sopenharmony_ci return 0; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci if (ps->aggr) { 42562306a36Sopenharmony_ci struct perf_cpu cpu = perf_cpu_map__cpu(evsel->core.cpus, cpu_map_idx); 42662306a36Sopenharmony_ci struct aggr_cpu_id aggr_id = config->aggr_get_id(config, cpu); 42762306a36Sopenharmony_ci struct perf_stat_aggr *ps_aggr; 42862306a36Sopenharmony_ci int i; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci for (i = 0; i < ps->nr_aggr; i++) { 43162306a36Sopenharmony_ci if (!aggr_cpu_id__equal(&aggr_id, &config->aggr_map->map[i])) 43262306a36Sopenharmony_ci continue; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci ps_aggr = &ps->aggr[i]; 43562306a36Sopenharmony_ci ps_aggr->nr++; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* 43862306a36Sopenharmony_ci * When any result is bad, make them all to give consistent output 43962306a36Sopenharmony_ci * in interval mode. But per-task counters can have 0 enabled time 44062306a36Sopenharmony_ci * when some tasks are idle. 44162306a36Sopenharmony_ci */ 44262306a36Sopenharmony_ci if (evsel__count_has_error(evsel, count, config) && !ps_aggr->failed) { 44362306a36Sopenharmony_ci ps_aggr->counts.val = 0; 44462306a36Sopenharmony_ci ps_aggr->counts.ena = 0; 44562306a36Sopenharmony_ci ps_aggr->counts.run = 0; 44662306a36Sopenharmony_ci ps_aggr->failed = true; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci if (!ps_aggr->failed) { 45062306a36Sopenharmony_ci ps_aggr->counts.val += count->val; 45162306a36Sopenharmony_ci ps_aggr->counts.ena += count->ena; 45262306a36Sopenharmony_ci ps_aggr->counts.run += count->run; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci break; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return 0; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic int process_counter_maps(struct perf_stat_config *config, 46262306a36Sopenharmony_ci struct evsel *counter) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci int nthreads = perf_thread_map__nr(counter->core.threads); 46562306a36Sopenharmony_ci int ncpus = evsel__nr_cpus(counter); 46662306a36Sopenharmony_ci int idx, thread; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci for (thread = 0; thread < nthreads; thread++) { 46962306a36Sopenharmony_ci for (idx = 0; idx < ncpus; idx++) { 47062306a36Sopenharmony_ci if (process_counter_values(config, counter, idx, thread, 47162306a36Sopenharmony_ci perf_counts(counter->counts, idx, thread))) 47262306a36Sopenharmony_ci return -1; 47362306a36Sopenharmony_ci } 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci return 0; 47762306a36Sopenharmony_ci} 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ciint perf_stat_process_counter(struct perf_stat_config *config, 48062306a36Sopenharmony_ci struct evsel *counter) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci struct perf_stat_evsel *ps = counter->stats; 48362306a36Sopenharmony_ci u64 *count; 48462306a36Sopenharmony_ci int ret; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci if (counter->per_pkg) 48762306a36Sopenharmony_ci evsel__zero_per_pkg(counter); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci ret = process_counter_maps(config, counter); 49062306a36Sopenharmony_ci if (ret) 49162306a36Sopenharmony_ci return ret; 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci if (config->aggr_mode != AGGR_GLOBAL) 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* 49762306a36Sopenharmony_ci * GLOBAL aggregation mode only has a single aggr counts, 49862306a36Sopenharmony_ci * so we can use ps->aggr[0] as the actual output. 49962306a36Sopenharmony_ci */ 50062306a36Sopenharmony_ci count = ps->aggr[0].counts.values; 50162306a36Sopenharmony_ci update_stats(&ps->res_stats, *count); 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci if (verbose > 0) { 50462306a36Sopenharmony_ci fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 50562306a36Sopenharmony_ci evsel__name(counter), count[0], count[1], count[2]); 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci return 0; 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic int evsel__merge_aggr_counters(struct evsel *evsel, struct evsel *alias) 51262306a36Sopenharmony_ci{ 51362306a36Sopenharmony_ci struct perf_stat_evsel *ps_a = evsel->stats; 51462306a36Sopenharmony_ci struct perf_stat_evsel *ps_b = alias->stats; 51562306a36Sopenharmony_ci int i; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci if (ps_a->aggr == NULL && ps_b->aggr == NULL) 51862306a36Sopenharmony_ci return 0; 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci if (ps_a->nr_aggr != ps_b->nr_aggr) { 52162306a36Sopenharmony_ci pr_err("Unmatched aggregation mode between aliases\n"); 52262306a36Sopenharmony_ci return -1; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci for (i = 0; i < ps_a->nr_aggr; i++) { 52662306a36Sopenharmony_ci struct perf_counts_values *aggr_counts_a = &ps_a->aggr[i].counts; 52762306a36Sopenharmony_ci struct perf_counts_values *aggr_counts_b = &ps_b->aggr[i].counts; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci /* NB: don't increase aggr.nr for aliases */ 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci aggr_counts_a->val += aggr_counts_b->val; 53262306a36Sopenharmony_ci aggr_counts_a->ena += aggr_counts_b->ena; 53362306a36Sopenharmony_ci aggr_counts_a->run += aggr_counts_b->run; 53462306a36Sopenharmony_ci } 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci return 0; 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci/* events should have the same name, scale, unit, cgroup but on different PMUs */ 53962306a36Sopenharmony_cistatic bool evsel__is_alias(struct evsel *evsel_a, struct evsel *evsel_b) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci if (strcmp(evsel__name(evsel_a), evsel__name(evsel_b))) 54262306a36Sopenharmony_ci return false; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (evsel_a->scale != evsel_b->scale) 54562306a36Sopenharmony_ci return false; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci if (evsel_a->cgrp != evsel_b->cgrp) 54862306a36Sopenharmony_ci return false; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci if (strcmp(evsel_a->unit, evsel_b->unit)) 55162306a36Sopenharmony_ci return false; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (evsel__is_clock(evsel_a) != evsel__is_clock(evsel_b)) 55462306a36Sopenharmony_ci return false; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci return !!strcmp(evsel_a->pmu_name, evsel_b->pmu_name); 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_cistatic void evsel__merge_aliases(struct evsel *evsel) 56062306a36Sopenharmony_ci{ 56162306a36Sopenharmony_ci struct evlist *evlist = evsel->evlist; 56262306a36Sopenharmony_ci struct evsel *alias; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci alias = list_prepare_entry(evsel, &(evlist->core.entries), core.node); 56562306a36Sopenharmony_ci list_for_each_entry_continue(alias, &evlist->core.entries, core.node) { 56662306a36Sopenharmony_ci /* Merge the same events on different PMUs. */ 56762306a36Sopenharmony_ci if (evsel__is_alias(evsel, alias)) { 56862306a36Sopenharmony_ci evsel__merge_aggr_counters(evsel, alias); 56962306a36Sopenharmony_ci alias->merged_stat = true; 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci } 57262306a36Sopenharmony_ci} 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic bool evsel__should_merge_hybrid(const struct evsel *evsel, 57562306a36Sopenharmony_ci const struct perf_stat_config *config) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci return config->hybrid_merge && evsel__is_hybrid(evsel); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic void evsel__merge_stats(struct evsel *evsel, struct perf_stat_config *config) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci /* this evsel is already merged */ 58362306a36Sopenharmony_ci if (evsel->merged_stat) 58462306a36Sopenharmony_ci return; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci if (evsel->auto_merge_stats || evsel__should_merge_hybrid(evsel, config)) 58762306a36Sopenharmony_ci evsel__merge_aliases(evsel); 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci/* merge the same uncore and hybrid events if requested */ 59162306a36Sopenharmony_civoid perf_stat_merge_counters(struct perf_stat_config *config, struct evlist *evlist) 59262306a36Sopenharmony_ci{ 59362306a36Sopenharmony_ci struct evsel *evsel; 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci if (config->no_merge) 59662306a36Sopenharmony_ci return; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) 59962306a36Sopenharmony_ci evsel__merge_stats(evsel, config); 60062306a36Sopenharmony_ci} 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_cistatic void evsel__update_percore_stats(struct evsel *evsel, struct aggr_cpu_id *core_id) 60362306a36Sopenharmony_ci{ 60462306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 60562306a36Sopenharmony_ci struct perf_counts_values counts = { 0, }; 60662306a36Sopenharmony_ci struct aggr_cpu_id id; 60762306a36Sopenharmony_ci struct perf_cpu cpu; 60862306a36Sopenharmony_ci int idx; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* collect per-core counts */ 61162306a36Sopenharmony_ci perf_cpu_map__for_each_cpu(cpu, idx, evsel->core.cpus) { 61262306a36Sopenharmony_ci struct perf_stat_aggr *aggr = &ps->aggr[idx]; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci id = aggr_cpu_id__core(cpu, NULL); 61562306a36Sopenharmony_ci if (!aggr_cpu_id__equal(core_id, &id)) 61662306a36Sopenharmony_ci continue; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci counts.val += aggr->counts.val; 61962306a36Sopenharmony_ci counts.ena += aggr->counts.ena; 62062306a36Sopenharmony_ci counts.run += aggr->counts.run; 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci /* update aggregated per-core counts for each CPU */ 62462306a36Sopenharmony_ci perf_cpu_map__for_each_cpu(cpu, idx, evsel->core.cpus) { 62562306a36Sopenharmony_ci struct perf_stat_aggr *aggr = &ps->aggr[idx]; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci id = aggr_cpu_id__core(cpu, NULL); 62862306a36Sopenharmony_ci if (!aggr_cpu_id__equal(core_id, &id)) 62962306a36Sopenharmony_ci continue; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci aggr->counts.val = counts.val; 63262306a36Sopenharmony_ci aggr->counts.ena = counts.ena; 63362306a36Sopenharmony_ci aggr->counts.run = counts.run; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci aggr->used = true; 63662306a36Sopenharmony_ci } 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci/* we have an aggr_map for cpu, but want to aggregate the counters per-core */ 64062306a36Sopenharmony_cistatic void evsel__process_percore(struct evsel *evsel) 64162306a36Sopenharmony_ci{ 64262306a36Sopenharmony_ci struct perf_stat_evsel *ps = evsel->stats; 64362306a36Sopenharmony_ci struct aggr_cpu_id core_id; 64462306a36Sopenharmony_ci struct perf_cpu cpu; 64562306a36Sopenharmony_ci int idx; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (!evsel->percore) 64862306a36Sopenharmony_ci return; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci perf_cpu_map__for_each_cpu(cpu, idx, evsel->core.cpus) { 65162306a36Sopenharmony_ci struct perf_stat_aggr *aggr = &ps->aggr[idx]; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (aggr->used) 65462306a36Sopenharmony_ci continue; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci core_id = aggr_cpu_id__core(cpu, NULL); 65762306a36Sopenharmony_ci evsel__update_percore_stats(evsel, &core_id); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci} 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci/* process cpu stats on per-core events */ 66262306a36Sopenharmony_civoid perf_stat_process_percore(struct perf_stat_config *config, struct evlist *evlist) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci struct evsel *evsel; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci if (config->aggr_mode != AGGR_NONE) 66762306a36Sopenharmony_ci return; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci evlist__for_each_entry(evlist, evsel) 67062306a36Sopenharmony_ci evsel__process_percore(evsel); 67162306a36Sopenharmony_ci} 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ciint perf_event__process_stat_event(struct perf_session *session, 67462306a36Sopenharmony_ci union perf_event *event) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci struct perf_counts_values count, *ptr; 67762306a36Sopenharmony_ci struct perf_record_stat *st = &event->stat; 67862306a36Sopenharmony_ci struct evsel *counter; 67962306a36Sopenharmony_ci int cpu_map_idx; 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci count.val = st->val; 68262306a36Sopenharmony_ci count.ena = st->ena; 68362306a36Sopenharmony_ci count.run = st->run; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci counter = evlist__id2evsel(session->evlist, st->id); 68662306a36Sopenharmony_ci if (!counter) { 68762306a36Sopenharmony_ci pr_err("Failed to resolve counter for stat event.\n"); 68862306a36Sopenharmony_ci return -EINVAL; 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci cpu_map_idx = perf_cpu_map__idx(evsel__cpus(counter), (struct perf_cpu){.cpu = st->cpu}); 69162306a36Sopenharmony_ci if (cpu_map_idx == -1) { 69262306a36Sopenharmony_ci pr_err("Invalid CPU %d for event %s.\n", st->cpu, evsel__name(counter)); 69362306a36Sopenharmony_ci return -EINVAL; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci ptr = perf_counts(counter->counts, cpu_map_idx, st->thread); 69662306a36Sopenharmony_ci if (ptr == NULL) { 69762306a36Sopenharmony_ci pr_err("Failed to find perf count for CPU %d thread %d on event %s.\n", 69862306a36Sopenharmony_ci st->cpu, st->thread, evsel__name(counter)); 69962306a36Sopenharmony_ci return -EINVAL; 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci *ptr = count; 70262306a36Sopenharmony_ci counter->supported = true; 70362306a36Sopenharmony_ci return 0; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cisize_t perf_event__fprintf_stat(union perf_event *event, FILE *fp) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci struct perf_record_stat *st = (struct perf_record_stat *)event; 70962306a36Sopenharmony_ci size_t ret; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci ret = fprintf(fp, "\n... id %" PRI_lu64 ", cpu %d, thread %d\n", 71262306a36Sopenharmony_ci st->id, st->cpu, st->thread); 71362306a36Sopenharmony_ci ret += fprintf(fp, "... value %" PRI_lu64 ", enabled %" PRI_lu64 ", running %" PRI_lu64 "\n", 71462306a36Sopenharmony_ci st->val, st->ena, st->run); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci return ret; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cisize_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct perf_record_stat_round *rd = (struct perf_record_stat_round *)event; 72262306a36Sopenharmony_ci size_t ret; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci ret = fprintf(fp, "\n... time %" PRI_lu64 ", type %s\n", rd->time, 72562306a36Sopenharmony_ci rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL"); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci return ret; 72862306a36Sopenharmony_ci} 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_cisize_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp) 73162306a36Sopenharmony_ci{ 73262306a36Sopenharmony_ci struct perf_stat_config sc = {}; 73362306a36Sopenharmony_ci size_t ret; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci perf_event__read_stat_config(&sc, &event->stat_config); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci ret = fprintf(fp, "\n"); 73862306a36Sopenharmony_ci ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode); 73962306a36Sopenharmony_ci ret += fprintf(fp, "... scale %d\n", sc.scale); 74062306a36Sopenharmony_ci ret += fprintf(fp, "... interval %u\n", sc.interval); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci return ret; 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ciint create_perf_stat_counter(struct evsel *evsel, 74662306a36Sopenharmony_ci struct perf_stat_config *config, 74762306a36Sopenharmony_ci struct target *target, 74862306a36Sopenharmony_ci int cpu_map_idx) 74962306a36Sopenharmony_ci{ 75062306a36Sopenharmony_ci struct perf_event_attr *attr = &evsel->core.attr; 75162306a36Sopenharmony_ci struct evsel *leader = evsel__leader(evsel); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 75462306a36Sopenharmony_ci PERF_FORMAT_TOTAL_TIME_RUNNING; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci /* 75762306a36Sopenharmony_ci * The event is part of non trivial group, let's enable 75862306a36Sopenharmony_ci * the group read (for leader) and ID retrieval for all 75962306a36Sopenharmony_ci * members. 76062306a36Sopenharmony_ci */ 76162306a36Sopenharmony_ci if (leader->core.nr_members > 1) 76262306a36Sopenharmony_ci attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci attr->inherit = !config->no_inherit && list_empty(&evsel->bpf_counter_list); 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci /* 76762306a36Sopenharmony_ci * Some events get initialized with sample_(period/type) set, 76862306a36Sopenharmony_ci * like tracepoints. Clear it up for counting. 76962306a36Sopenharmony_ci */ 77062306a36Sopenharmony_ci attr->sample_period = 0; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci if (config->identifier) 77362306a36Sopenharmony_ci attr->sample_type = PERF_SAMPLE_IDENTIFIER; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci if (config->all_user) { 77662306a36Sopenharmony_ci attr->exclude_kernel = 1; 77762306a36Sopenharmony_ci attr->exclude_user = 0; 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci if (config->all_kernel) { 78162306a36Sopenharmony_ci attr->exclude_kernel = 0; 78262306a36Sopenharmony_ci attr->exclude_user = 1; 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* 78662306a36Sopenharmony_ci * Disabling all counters initially, they will be enabled 78762306a36Sopenharmony_ci * either manually by us or by kernel via enable_on_exec 78862306a36Sopenharmony_ci * set later. 78962306a36Sopenharmony_ci */ 79062306a36Sopenharmony_ci if (evsel__is_group_leader(evsel)) { 79162306a36Sopenharmony_ci attr->disabled = 1; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci if (target__enable_on_exec(target)) 79462306a36Sopenharmony_ci attr->enable_on_exec = 1; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci if (target__has_cpu(target) && !target__has_per_thread(target)) 79862306a36Sopenharmony_ci return evsel__open_per_cpu(evsel, evsel__cpus(evsel), cpu_map_idx); 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci return evsel__open_per_thread(evsel, evsel->core.threads); 80162306a36Sopenharmony_ci} 802