Commit 5f50e15c authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo

perf cpumap: Refactor cpu_map__build_map()

Turn it into a cpu_aggr_map__new(). Pass helper functions. Refactor
builtin-stat calls to manually pass function pointers. Try to reduce
some copy-paste code.
Reviewed-by: default avatarJames Clark <james.clark@arm.com>
Signed-off-by: default avatarIan Rogers <irogers@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: John Garry <john.garry@huawei.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Riccardo Mancini <rickyman7@gmail.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Vineet Singh <vineet.singh@intel.com>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: zhengjun.xing@intel.com
Link: https://lore.kernel.org/r/20220105061351.120843-19-irogers@google.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent adff2c63
......@@ -1322,6 +1322,17 @@ static struct option stat_options[] = {
OPT_END()
};
static const char *const aggr_mode__string[] = {
[AGGR_CORE] = "core",
[AGGR_DIE] = "die",
[AGGR_GLOBAL] = "global",
[AGGR_NODE] = "node",
[AGGR_NONE] = "none",
[AGGR_SOCKET] = "socket",
[AGGR_THREAD] = "thread",
[AGGR_UNSET] = "unset",
};
static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,
int cpu)
{
......@@ -1394,54 +1405,67 @@ static bool term_percore_set(void)
return false;
}
static int perf_stat_init_aggr_mode(void)
static aggr_cpu_id_get_t aggr_mode__get_aggr(enum aggr_mode aggr_mode)
{
int nr;
switch (aggr_mode) {
case AGGR_SOCKET:
return cpu_map__get_socket_aggr_by_cpu;
case AGGR_DIE:
return cpu_map__get_die_aggr_by_cpu;
case AGGR_CORE:
return cpu_map__get_core_aggr_by_cpu;
case AGGR_NODE:
return cpu_map__get_node_aggr_by_cpu;
case AGGR_NONE:
if (term_percore_set())
return cpu_map__get_core_aggr_by_cpu;
return NULL;
case AGGR_GLOBAL:
case AGGR_THREAD:
case AGGR_UNSET:
default:
return NULL;
}
}
switch (stat_config.aggr_mode) {
static aggr_get_id_t aggr_mode__get_id(enum aggr_mode aggr_mode)
{
switch (aggr_mode) {
case AGGR_SOCKET:
if (cpu_map__build_socket_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build socket map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_socket_cached;
break;
return perf_stat__get_socket_cached;
case AGGR_DIE:
if (cpu_map__build_die_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build die map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_die_cached;
break;
return perf_stat__get_die_cached;
case AGGR_CORE:
if (cpu_map__build_core_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_core_cached;
break;
return perf_stat__get_core_cached;
case AGGR_NODE:
if (cpu_map__build_node_map(evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_node_cached;
break;
return perf_stat__get_node_cached;
case AGGR_NONE:
if (term_percore_set()) {
if (cpu_map__build_core_map(evsel_list->core.cpus,
&stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_core_cached;
return perf_stat__get_core_cached;
}
break;
return NULL;
case AGGR_GLOBAL:
case AGGR_THREAD:
case AGGR_UNSET:
default:
break;
return NULL;
}
}
static int perf_stat_init_aggr_mode(void)
{
int nr;
aggr_cpu_id_get_t get_id = aggr_mode__get_aggr(stat_config.aggr_mode);
if (get_id) {
stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.cpus,
get_id, /*data=*/NULL);
if (!stat_config.aggr_map) {
pr_err("cannot build %s map", aggr_mode__string[stat_config.aggr_mode]);
return -1;
}
stat_config.aggr_get_id = aggr_mode__get_id(stat_config.aggr_mode);
}
/*
......@@ -1533,30 +1557,6 @@ static struct aggr_cpu_id perf_env__get_node_aggr_by_cpu(int cpu, void *data)
return id;
}
static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus,
struct cpu_aggr_map **sockp)
{
return cpu_map__build_map(cpus, sockp, perf_env__get_socket_aggr_by_cpu, env);
}
static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus,
struct cpu_aggr_map **diep)
{
return cpu_map__build_map(cpus, diep, perf_env__get_die_aggr_by_cpu, env);
}
static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus,
struct cpu_aggr_map **corep)
{
return cpu_map__build_map(cpus, corep, perf_env__get_core_aggr_by_cpu, env);
}
static int perf_env__build_node_map(struct perf_env *env, struct perf_cpu_map *cpus,
struct cpu_aggr_map **nodep)
{
return cpu_map__build_map(cpus, nodep, perf_env__get_node_aggr_by_cpu, env);
}
static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,
int cpu)
{
......@@ -1580,47 +1580,60 @@ static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *conf
return perf_env__get_node_aggr_by_cpu(cpu, &perf_stat.session->header.env);
}
static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
static aggr_cpu_id_get_t aggr_mode__get_aggr_file(enum aggr_mode aggr_mode)
{
struct perf_env *env = &st->session->header.env;
switch (aggr_mode) {
case AGGR_SOCKET:
return perf_env__get_socket_aggr_by_cpu;
case AGGR_DIE:
return perf_env__get_die_aggr_by_cpu;
case AGGR_CORE:
return perf_env__get_core_aggr_by_cpu;
case AGGR_NODE:
return perf_env__get_node_aggr_by_cpu;
case AGGR_NONE:
case AGGR_GLOBAL:
case AGGR_THREAD:
case AGGR_UNSET:
default:
return NULL;
}
}
switch (stat_config.aggr_mode) {
static aggr_get_id_t aggr_mode__get_id_file(enum aggr_mode aggr_mode)
{
switch (aggr_mode) {
case AGGR_SOCKET:
if (perf_env__build_socket_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build socket map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_socket_file;
break;
return perf_stat__get_socket_file;
case AGGR_DIE:
if (perf_env__build_die_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build die map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_die_file;
break;
return perf_stat__get_die_file;
case AGGR_CORE:
if (perf_env__build_core_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_core_file;
break;
return perf_stat__get_core_file;
case AGGR_NODE:
if (perf_env__build_node_map(env, evsel_list->core.cpus, &stat_config.aggr_map)) {
perror("cannot build core map");
return -1;
}
stat_config.aggr_get_id = perf_stat__get_node_file;
break;
return perf_stat__get_node_file;
case AGGR_NONE:
case AGGR_GLOBAL:
case AGGR_THREAD:
case AGGR_UNSET:
default:
break;
return NULL;
}
}
static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
{
struct perf_env *env = &st->session->header.env;
aggr_cpu_id_get_t get_id = aggr_mode__get_aggr_file(stat_config.aggr_mode);
if (!get_id)
return 0;
stat_config.aggr_map = cpu_aggr_map__new(evsel_list->core.cpus, get_id, env);
if (!stat_config.aggr_map) {
pr_err("cannot build %s map", aggr_mode__string[stat_config.aggr_mode]);
return -1;
}
stat_config.aggr_get_id = aggr_mode__get_id_file(stat_config.aggr_mode);
return 0;
}
......
......@@ -140,7 +140,7 @@ struct aggr_cpu_id cpu_map__get_socket_aggr_by_cpu(int cpu, void *data __maybe_u
return id;
}
static int cmp_aggr_cpu_id(const void *a_pointer, const void *b_pointer)
static int aggr_cpu_id__cmp(const void *a_pointer, const void *b_pointer)
{
struct aggr_cpu_id *a = (struct aggr_cpu_id *)a_pointer;
struct aggr_cpu_id *b = (struct aggr_cpu_id *)b_pointer;
......@@ -157,37 +157,40 @@ static int cmp_aggr_cpu_id(const void *a_pointer, const void *b_pointer)
return a->thread - b->thread;
}
int cpu_map__build_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **res,
struct aggr_cpu_id (*f)(int cpu, void *data),
void *data)
struct cpu_aggr_map *cpu_aggr_map__new(const struct perf_cpu_map *cpus,
aggr_cpu_id_get_t get_id,
void *data)
{
int nr = cpus->nr;
struct cpu_aggr_map *c = cpu_aggr_map__empty_new(nr);
int cpu, s2;
struct aggr_cpu_id s1;
int cpu, idx;
struct cpu_aggr_map *c = cpu_aggr_map__empty_new(cpus->nr);
if (!c)
return -1;
return NULL;
/* Reset size as it may only be partially filled */
c->nr = 0;
for (cpu = 0; cpu < nr; cpu++) {
s1 = f(cpu, data);
for (s2 = 0; s2 < c->nr; s2++) {
if (aggr_cpu_id__equal(&s1, &c->map[s2]))
perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
bool duplicate = false;
struct aggr_cpu_id cpu_id = get_id(cpu, data);
for (int j = 0; j < c->nr; j++) {
if (aggr_cpu_id__equal(&cpu_id, &c->map[j])) {
duplicate = true;
break;
}
}
if (s2 == c->nr) {
c->map[c->nr] = s1;
if (!duplicate) {
c->map[c->nr] = cpu_id;
c->nr++;
}
}
/* ensure we process id in increasing order */
qsort(c->map, c->nr, sizeof(struct aggr_cpu_id), cmp_aggr_cpu_id);
qsort(c->map, c->nr, sizeof(struct aggr_cpu_id), aggr_cpu_id__cmp);
return c;
*res = c;
return 0;
}
int cpu__get_die_id(int cpu)
......@@ -253,26 +256,6 @@ struct aggr_cpu_id cpu_map__get_node_aggr_by_cpu(int cpu, void *data __maybe_unu
return id;
}
int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **sockp)
{
return cpu_map__build_map(cpus, sockp, cpu_map__get_socket_aggr_by_cpu, NULL);
}
int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **diep)
{
return cpu_map__build_map(cpus, diep, cpu_map__get_die_aggr_by_cpu, NULL);
}
int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **corep)
{
return cpu_map__build_map(cpus, corep, cpu_map__get_core_aggr_by_cpu, NULL);
}
int cpu_map__build_node_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **numap)
{
return cpu_map__build_map(cpus, numap, cpu_map__get_node_aggr_by_cpu, NULL);
}
/* setup simple routines to easily access node numbers given a cpu number */
static int get_max_num(char *path, int *max)
{
......
......@@ -43,10 +43,6 @@ struct aggr_cpu_id cpu_map__get_socket_aggr_by_cpu(int cpu, void *data);
struct aggr_cpu_id cpu_map__get_die_aggr_by_cpu(int cpu, void *data);
struct aggr_cpu_id cpu_map__get_core_aggr_by_cpu(int cpu, void *data);
struct aggr_cpu_id cpu_map__get_node_aggr_by_cpu(int cpu, void *data);
int cpu_map__build_socket_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **sockp);
int cpu_map__build_die_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **diep);
int cpu_map__build_core_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **corep);
int cpu_map__build_node_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **nodep);
const struct perf_cpu_map *cpu_map__online(void); /* thread unsafe */
int cpu__setup_cpunode_map(void);
......@@ -75,10 +71,16 @@ int cpu__get_die_id(int cpu);
*/
int cpu__get_core_id(int cpu);
typedef struct aggr_cpu_id (*aggr_cpu_id_get_t)(int cpu, void *data);
int cpu_map__build_map(struct perf_cpu_map *cpus, struct cpu_aggr_map **res,
struct aggr_cpu_id (*f)(int cpu, void *data),
void *data);
/**
* cpu_aggr_map__new - Create a cpu_aggr_map with an aggr_cpu_id for each cpu in
* cpus. The aggr_cpu_id is created with 'get_id' that may have a data value
* passed to it. The cpu_aggr_map is sorted with duplicate values removed.
*/
struct cpu_aggr_map *cpu_aggr_map__new(const struct perf_cpu_map *cpus,
aggr_cpu_id_get_t get_id,
void *data);
bool cpu_map__has(struct perf_cpu_map *cpus, int cpu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment