[PATCH 2/5] perf,tools: check and re-organize evsel cpu maps

From: kan . liang
Date: Tue Mar 03 2015 - 11:04:13 EST


From: Kan Liang <kan.liang@xxxxxxxxx>

With the patch 1/5, it's possible to group read events from different
pmus. "-C" can be used to set cpu list. The cpu list may be incompatible
with pmu's cpumask.
This patch checks the event's cpu maps, and discard the incompatible cpu
maps.
event's cpu maps is saved in evsel->cpus during option parse. Then the
evlist's cpu maps is created in perf_evlist__create_maps. So the cpu
maps can be check and re-organized in perf_evlist__create_maps.
Only cpu_list need to check the cpu maps.

Signed-off-by: Kan Liang <kan.liang@xxxxxxxxx>
---
tools/perf/builtin-top.c | 6 ++--
tools/perf/util/evlist.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5fb8723..f40d1d6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1218,9 +1218,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
if (target__none(target))
target->system_wide = true;

- if (perf_evlist__create_maps(top.evlist, target) < 0)
- usage_with_options(top_usage, options);
-
if (!top.evlist->nr_entries &&
perf_evlist__add_default(top.evlist) < 0) {
ui__error("Not enough memory for event selector list\n");
@@ -1229,6 +1226,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)

symbol_conf.nr_events = top.evlist->nr_entries;

+ if (perf_evlist__create_maps(top.evlist, target) < 0)
+ usage_with_options(top_usage, options);
+
if (top.delay_secs < 1)
top.delay_secs = 1;

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8d0b623..3c6115c 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1026,6 +1026,74 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
return perf_evlist__mmap_per_cpu(evlist, &mp);
}

+static int cmp_ids(const void *a, const void *b)
+{
+ return *(int *)a - *(int *)b;
+}
+
+/*
+ * Check evsel cpu map according to pmu cpumask and input
+ * Only available cpu can be stored in evsel->cpus->map.
+ */
+static int perf_evlist__check_evsel_cpus(struct perf_evlist *evlist)
+{
+ const struct cpu_map *cpus = evlist->cpus;
+ const int ncpus = cpu_map__nr(evlist->cpus);
+ struct perf_evsel *evsel;
+ int i, j, cpu_nr, tmp;
+
+ /* ensure we process id in increasing order */
+ qsort(evlist->cpus->map, evlist->cpus->nr, sizeof(int), cmp_ids);
+
+ evlist__for_each(evlist, evsel) {
+ if (!evsel->cpus)
+ continue;
+
+ cpu_nr = 0;
+ j = 0;
+ for (i = 0; i < cpu_map__nr(evsel->cpus);) {
+
+ if (j >= ncpus) {
+ evsel->cpus->map[i++] = -1;
+ continue;
+ }
+ for (; j < ncpus; j++) {
+ if (cpus->map[j] < evsel->cpus->map[i])
+ continue;
+ if (cpus->map[j] == evsel->cpus->map[i]) {
+ cpu_nr++;
+ j++;
+ i++;
+ } else
+ evsel->cpus->map[i++] = -1;
+ break;
+ }
+ }
+
+ if (cpu_nr == cpu_map__nr(evsel->cpus))
+ continue;
+ if (cpu_nr == 0) {
+ perror("failed to create CPUs map, please check cpumask");
+ return -1;
+ }
+
+ tmp = 0;
+ for (i = 0; i < cpu_nr; i++) {
+ if (evsel->cpus->map[i] == -1) {
+ while (evsel->cpus->map[tmp] == -1) {
+ tmp++;
+ BUG_ON(tmp >= cpu_map__nr(evsel->cpus));
+ }
+ evsel->cpus->map[i] = evsel->cpus->map[tmp];
+ evsel->cpus->map[tmp] = -1;
+ }
+ tmp++;
+ }
+ evsel->cpus->nr = cpu_nr;
+ }
+ return 0;
+}
+
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
{
evlist->threads = thread_map__new_str(target->pid, target->tid,
@@ -1042,6 +1110,10 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
if (evlist->cpus == NULL)
goto out_delete_threads;

+ if (target->cpu_list &&
+ (perf_evlist__check_evsel_cpus(evlist) < 0))
+ goto out_delete_threads;
+
return 0;

out_delete_threads:
--
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/