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

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.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent adff2c63
Loading
Loading
Loading
Loading
+100 −87
Original line number Diff line number Diff line
@@ -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;
		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;
	}
		stat_config.aggr_get_id = perf_stat__get_node_cached;
		break;
}

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()) {
			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 (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;
		return perf_env__get_node_aggr_by_cpu;
	case AGGR_NONE:
	case AGGR_GLOBAL:
	case AGGR_THREAD:
	case AGGR_UNSET:
	default:
		return NULL;
	}
		stat_config.aggr_get_id = perf_stat__get_node_file;
		break;
}

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:
		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;
}

+21 −38
Original line number Diff line number Diff line
@@ -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),
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)
{
+9 −7
Original line number Diff line number Diff line
@@ -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,9 +71,15 @@ 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),
/**
 * 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);