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: James Clark <james.clark@arm.com> Signed-off-by: Ian 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.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
adff2c6343
Коммит
5f50e15c15
|
@ -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 (stat_config.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 cpu_map__get_socket_aggr_by_cpu;
|
||||
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 cpu_map__get_die_aggr_by_cpu;
|
||||
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 cpu_map__get_core_aggr_by_cpu;
|
||||
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 cpu_map__get_node_aggr_by_cpu;
|
||||
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;
|
||||
}
|
||||
break;
|
||||
if (term_percore_set())
|
||||
return cpu_map__get_core_aggr_by_cpu;
|
||||
|
||||
return NULL;
|
||||
case AGGR_GLOBAL:
|
||||
case AGGR_THREAD:
|
||||
case AGGR_UNSET:
|
||||
default:
|
||||
break;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static aggr_get_id_t aggr_mode__get_id(enum aggr_mode aggr_mode)
|
||||
{
|
||||
switch (aggr_mode) {
|
||||
case AGGR_SOCKET:
|
||||
return perf_stat__get_socket_cached;
|
||||
case AGGR_DIE:
|
||||
return perf_stat__get_die_cached;
|
||||
case AGGR_CORE:
|
||||
return perf_stat__get_core_cached;
|
||||
case AGGR_NODE:
|
||||
return perf_stat__get_node_cached;
|
||||
case AGGR_NONE:
|
||||
if (term_percore_set()) {
|
||||
return perf_stat__get_core_cached;
|
||||
}
|
||||
return NULL;
|
||||
case AGGR_GLOBAL:
|
||||
case AGGR_THREAD:
|
||||
case AGGR_UNSET:
|
||||
default:
|
||||
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 (stat_config.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_env__get_socket_aggr_by_cpu;
|
||||
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_env__get_die_aggr_by_cpu;
|
||||
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_env__get_core_aggr_by_cpu;
|
||||
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_env__get_node_aggr_by_cpu;
|
||||
case AGGR_NONE:
|
||||
case AGGR_GLOBAL:
|
||||
case AGGR_THREAD:
|
||||
case AGGR_UNSET:
|
||||
default:
|
||||
break;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static aggr_get_id_t aggr_mode__get_id_file(enum aggr_mode aggr_mode)
|
||||
{
|
||||
switch (aggr_mode) {
|
||||
case AGGR_SOCKET:
|
||||
return perf_stat__get_socket_file;
|
||||
case AGGR_DIE:
|
||||
return perf_stat__get_die_file;
|
||||
case AGGR_CORE:
|
||||
return perf_stat__get_core_file;
|
||||
case AGGR_NODE:
|
||||
return perf_stat__get_node_file;
|
||||
case AGGR_NONE:
|
||||
case AGGR_GLOBAL:
|
||||
case AGGR_THREAD:
|
||||
case AGGR_UNSET:
|
||||
default:
|
||||
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);
|
||||
|
||||
*res = c;
|
||||
return 0;
|
||||
/* ensure we process id in increasing order */
|
||||
qsort(c->map, c->nr, sizeof(struct aggr_cpu_id), aggr_cpu_id__cmp);
|
||||
|
||||
return c;
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче