Display cpu map in standard list form.
(perf report -D output on perf stat data).

before:
  0x590 [0x18]: PERF_RECORD_CPU_MAP nr: 4 cpus: 0, 1, 2, 3

after:
  0x590 [0x18]: PERF_RECORD_CPU_MAP: 0-3

Adding automated testcase.

Link: http://lkml.kernel.org/n/tip-zwt9oh6xqts2yrb2qk5eh...@git.kernel.org
Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
 tools/perf/tests/builtin-test.c |  4 +++
 tools/perf/tests/cpumap.c       | 24 ++++++++++++++++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/util/cpumap.c        | 54 ++++++++++++++++++++++++++++++++++++-----
 tools/perf/util/cpumap.h        |  1 +
 tools/perf/util/event.c         |  2 +-
 6 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 5781c1640eae..07c14e9f6546 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -214,6 +214,10 @@ static struct test generic_tests[] = {
                .func = test__backward_ring_buffer,
        },
        {
+               .desc = "Test cpu map print",
+               .func = test__cpu_map_print,
+       },
+       {
                .func = NULL,
        },
 };
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 4cb6418a8ffc..c9ec5f83e42c 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -86,3 +86,27 @@ int test__cpu_map_synthesize(int subtest __maybe_unused)
        cpu_map__put(cpus);
        return 0;
 }
+
+static int cpu_map_print(const char *str)
+{
+       struct cpu_map *map = cpu_map__new(str);
+       char buf[100];
+
+       if (!map)
+               return -1;
+
+       cpu_map__snprint(map, buf, sizeof(buf));
+       return !strcmp(buf, str);
+}
+
+int test__cpu_map_print(int subtest __maybe_unused)
+{
+       TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1"));
+       TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,5"));
+       TEST_ASSERT_VAL("failed to convert map", 
cpu_map_print("1,3,5,7,9,11,13,15,17,19,21-40"));
+       TEST_ASSERT_VAL("failed to convert map", cpu_map_print("2-5"));
+       TEST_ASSERT_VAL("failed to convert map", 
cpu_map_print("1,3-6,8-10,24,35-37"));
+       TEST_ASSERT_VAL("failed to convert map", 
cpu_map_print("1,3-6,8-10,24,35-37"));
+       TEST_ASSERT_VAL("failed to convert map", 
cpu_map_print("1-10,12-20,22-30,32-40"));
+       return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index c57e72c826d2..52f969570c97 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -87,6 +87,7 @@ int test__synthesize_stat_round(int subtest);
 int test__event_update(int subtest);
 int test__event_times(int subtest);
 int test__backward_ring_buffer(int subtest);
+int test__cpu_map_print(int subtest);
 
 #if defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 02d801670f30..15f83acac1b8 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -236,13 +236,12 @@ struct cpu_map *cpu_map__new_data(struct cpu_map_data 
*data)
 
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
 {
-       int i;
-       size_t printed = fprintf(fp, "%d cpu%s: ",
-                                map->nr, map->nr > 1 ? "s" : "");
-       for (i = 0; i < map->nr; ++i)
-               printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]);
+#define BUFSIZE 1024
+       char buf[BUFSIZE];
 
-       return printed + fprintf(fp, "\n");
+       cpu_map__snprint(map, buf, sizeof(buf));
+       return fprintf(fp, "%s\n", buf);
+#undef BUFSIZE
 }
 
 struct cpu_map *cpu_map__dummy_new(void)
@@ -599,3 +598,46 @@ bool cpu_map__has(struct cpu_map *cpus, int cpu)
 
        return false;
 }
+
+size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size)
+{
+       int i, cpu, start = -1;
+       bool first = true;
+       size_t ret = 0;
+
+#define COMMA first ? "" : ","
+
+       for (i = 0; i < map->nr + 1; i++) {
+               bool last = i == map->nr;
+
+               cpu = last ? INT_MAX : map->map[i];
+
+               if (start == -1) {
+                       start = i;
+                       if (last) {
+                               ret += snprintf(buf + ret, size - ret,
+                                               "%s%d", COMMA,
+                                               map->map[i]);
+                       }
+               } else if (((i - start) != (cpu - map->map[start])) || last) {
+                       int end = i - 1;
+
+                       if (start == end) {
+                               ret += snprintf(buf + ret, size - ret,
+                                               "%s%d", COMMA,
+                                               map->map[start]);
+                       } else {
+                               ret += snprintf(buf + ret, size - ret,
+                                               "%s%d-%d", COMMA,
+                                               map->map[start], map->map[end]);
+                       }
+                       first = false;
+                       start = i;
+               }
+       }
+
+#undef COMMA
+
+       pr_debug("cpumask list: %s\n", buf);
+       return ret;
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 1a0a35073ce1..206dc550354a 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -19,6 +19,7 @@ struct cpu_map *cpu_map__empty_new(int nr);
 struct cpu_map *cpu_map__dummy_new(void);
 struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
 struct cpu_map *cpu_map__read(FILE *file);
+size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
 int cpu_map__get_socket_id(int cpu);
 int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9b141f12329e..e20438b784be 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1092,7 +1092,7 @@ size_t perf_event__fprintf_cpu_map(union perf_event 
*event, FILE *fp)
        struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
        size_t ret;
 
-       ret = fprintf(fp, " nr: ");
+       ret = fprintf(fp, ": ");
 
        if (cpus)
                ret += cpu_map__fprintf(cpus, fp);
-- 
2.4.11

Reply via email to