Commit a2408a70 authored by Andi Kleen's avatar Andi Kleen Committed by Arnaldo Carvalho de Melo
Browse files

perf evlist: Maintain evlist->all_cpus



Maintain a cpumap in the evlist that is the union of all the cpus of the
events.

This needs a cpumap merge operation, which is added together with tests.

v2:
Add tests for cpu map merge
Fix handling of duplicates
Rename _update to _merge
Factor out sorting.
Fix handling of NULL maps in merge

v3:
Add comments and empty lines to _merge

Committer testing:

  # perf test "Merge cpu map"
  52: Merge cpu map                                         : Ok
  #

Signed-off-by: default avatarAndi Kleen <ak@linux.intel.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Link: http://lore.kernel.org/lkml/20191121001522.180827-5-andi@firstfloor.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 7074674e
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -286,3 +286,60 @@ int perf_cpu_map__max(struct perf_cpu_map *map)

	return max;
}

/*
 * Merge two cpumaps
 *
 * orig either gets freed and replaced with a new map, or reused
 * with no reference count change (similar to "realloc")
 * other has its reference count increased.
 */

struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
					 struct perf_cpu_map *other)
{
	int *tmp_cpus;
	int tmp_len;
	int i, j, k;
	struct perf_cpu_map *merged;

	if (!orig && !other)
		return NULL;
	if (!orig) {
		perf_cpu_map__get(other);
		return other;
	}
	if (!other)
		return orig;
	if (orig->nr == other->nr &&
	    !memcmp(orig->map, other->map, orig->nr * sizeof(int)))
		return orig;

	tmp_len = orig->nr + other->nr;
	tmp_cpus = malloc(tmp_len * sizeof(int));
	if (!tmp_cpus)
		return NULL;

	/* Standard merge algorithm from wikipedia */
	i = j = k = 0;
	while (i < orig->nr && j < other->nr) {
		if (orig->map[i] <= other->map[j]) {
			if (orig->map[i] == other->map[j])
				j++;
			tmp_cpus[k++] = orig->map[i++];
		} else
			tmp_cpus[k++] = other->map[j++];
	}

	while (i < orig->nr)
		tmp_cpus[k++] = orig->map[i++];

	while (j < other->nr)
		tmp_cpus[k++] = other->map[j++];
	assert(k <= tmp_len);

	merged = cpu_map__trim_new(k, tmp_cpus);
	free(tmp_cpus);
	perf_cpu_map__put(orig);
	return merged;
}
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,

	perf_thread_map__put(evsel->threads);
	evsel->threads = perf_thread_map__get(evlist->threads);
	evlist->all_cpus = perf_cpu_map__merge(evlist->all_cpus, evsel->cpus);
}

static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
+1 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ struct perf_evlist {
	int			 nr_entries;
	bool			 has_user_cpus;
	struct perf_cpu_map	*cpus;
	struct perf_cpu_map	*all_cpus;
	struct perf_thread_map	*threads;
	int			 nr_mmaps;
	size_t			 mmap_len;
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@ LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
						     struct perf_cpu_map *other);
LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
+5 −0
Original line number Diff line number Diff line
@@ -259,6 +259,11 @@ static struct test generic_tests[] = {
		.desc = "Print cpu map",
		.func = test__cpu_map_print,
	},
	{
		.desc = "Merge cpu map",
		.func = test__cpu_map_merge,
	},

	{
		.desc = "Probe SDT events",
		.func = test__sdt_event,
Loading