lkml.org 
[lkml]   [2015]   [Dec]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:perf/core] perf cpu_map: Add cpu_map event synthesize function
    Commit-ID:  6c872901af07c41745f1abf5ceac9b3b4d9cdbb6
    Gitweb: http://git.kernel.org/tip/6c872901af07c41745f1abf5ceac9b3b4d9cdbb6
    Author: Jiri Olsa <jolsa@kernel.org>
    AuthorDate: Sun, 25 Oct 2015 15:51:24 +0100
    Committer: Arnaldo Carvalho de Melo <acme@redhat.com>
    CommitDate: Thu, 17 Dec 2015 14:38:18 -0300

    perf cpu_map: Add cpu_map event synthesize function

    Introduce the perf_event__synthesize_cpu_map function to synthesize a
    struct cpu_map.

    Added generic interface:
    cpu_map_data__alloc
    cpu_map_data__synthesize

    to make the cpu_map synthesizing usable for other events.

    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    Tested-by: Kan Liang <kan.liang@intel.com>
    Cc: David Ahern <dsahern@gmail.com>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Link: http://lkml.kernel.org/r/1445784728-21732-9-git-send-email-jolsa@kernel.org
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
    ---
    tools/perf/tests/Build | 1 +
    tools/perf/tests/builtin-test.c | 4 ++
    tools/perf/tests/cpumap.c | 71 ++++++++++++++++++++++
    tools/perf/tests/tests.h | 1 +
    tools/perf/util/event.c | 131 ++++++++++++++++++++++++++++++++++++++++
    tools/perf/util/event.h | 8 +++
    6 files changed, 216 insertions(+)

    diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
    index f23fb7e..7abad28 100644
    --- a/tools/perf/tests/Build
    +++ b/tools/perf/tests/Build
    @@ -34,6 +34,7 @@ perf-y += thread-map.o
    perf-y += llvm.o llvm-src-base.o llvm-src-kbuild.o llvm-src-prologue.o
    perf-y += bpf.o
    perf-y += topology.o
    +perf-y += cpumap.o

    $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
    $(call rule_mkdir)
    diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
    index 745bdb0..0c3fe28 100644
    --- a/tools/perf/tests/builtin-test.c
    +++ b/tools/perf/tests/builtin-test.c
    @@ -184,6 +184,10 @@ static struct test generic_tests[] = {
    .func = test__thread_map_synthesize,
    },
    {
    + .desc = "Test cpu map synthesize",
    + .func = test__cpu_map_synthesize,
    + },
    + {
    .func = NULL,
    },
    };
    diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
    new file mode 100644
    index 0000000..7154805
    --- /dev/null
    +++ b/tools/perf/tests/cpumap.c
    @@ -0,0 +1,71 @@
    +#include "tests.h"
    +#include "cpumap.h"
    +
    +static int process_event_mask(struct perf_tool *tool __maybe_unused,
    + union perf_event *event,
    + struct perf_sample *sample __maybe_unused,
    + struct machine *machine __maybe_unused)
    +{
    + struct cpu_map_event *map = &event->cpu_map;
    + struct cpu_map_mask *mask;
    + struct cpu_map_data *data;
    + int i;
    +
    + data = &map->data;
    +
    + TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK);
    +
    + mask = (struct cpu_map_mask *)data->data;
    +
    + TEST_ASSERT_VAL("wrong nr", mask->nr == 1);
    +
    + for (i = 0; i < 20; i++) {
    + TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask));
    + }
    +
    + return 0;
    +}
    +
    +static int process_event_cpus(struct perf_tool *tool __maybe_unused,
    + union perf_event *event,
    + struct perf_sample *sample __maybe_unused,
    + struct machine *machine __maybe_unused)
    +{
    + struct cpu_map_event *map = &event->cpu_map;
    + struct cpu_map_entries *cpus;
    + struct cpu_map_data *data;
    +
    + data = &map->data;
    +
    + TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS);
    +
    + cpus = (struct cpu_map_entries *)data->data;
    +
    + TEST_ASSERT_VAL("wrong nr", cpus->nr == 2);
    + TEST_ASSERT_VAL("wrong cpu", cpus->cpu[0] == 1);
    + TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] == 256);
    + return 0;
    +}
    +
    +
    +int test__cpu_map_synthesize(int subtest __maybe_unused)
    +{
    + struct cpu_map *cpus;
    +
    + /* This one is better stores in mask. */
    + cpus = cpu_map__new("0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19");
    +
    + TEST_ASSERT_VAL("failed to synthesize map",
    + !perf_event__synthesize_cpu_map(NULL, cpus, process_event_mask, NULL));
    +
    + cpu_map__put(cpus);
    +
    + /* This one is better stores in cpu values. */
    + cpus = cpu_map__new("1,256");
    +
    + TEST_ASSERT_VAL("failed to synthesize map",
    + !perf_event__synthesize_cpu_map(NULL, cpus, process_event_cpus, NULL));
    +
    + cpu_map__put(cpus);
    + return 0;
    +}
    diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
    index 3fe52cc..f85160f 100644
    --- a/tools/perf/tests/tests.h
    +++ b/tools/perf/tests/tests.h
    @@ -80,6 +80,7 @@ const char *test__bpf_subtest_get_desc(int subtest);
    int test__bpf_subtest_get_nr(void);
    int test_session_topology(int subtest);
    int test__thread_map_synthesize(int subtest);
    +int test__cpu_map_synthesize(int subtest);

    #if defined(__arm__) || defined(__aarch64__)
    #ifdef HAVE_DWARF_UNWIND_SUPPORT
    diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
    index 719c078..15d6466 100644
    --- a/tools/perf/util/event.c
    +++ b/tools/perf/util/event.c
    @@ -737,6 +737,137 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
    return err;
    }

    +static void synthesize_cpus(struct cpu_map_entries *cpus,
    + struct cpu_map *map)
    +{
    + int i;
    +
    + cpus->nr = map->nr;
    +
    + for (i = 0; i < map->nr; i++)
    + cpus->cpu[i] = map->map[i];
    +}
    +
    +static void synthesize_mask(struct cpu_map_mask *mask,
    + struct cpu_map *map, int max)
    +{
    + int i;
    +
    + mask->nr = BITS_TO_LONGS(max);
    + mask->long_size = sizeof(long);
    +
    + for (i = 0; i < map->nr; i++)
    + set_bit(map->map[i], mask->mask);
    +}
    +
    +static size_t cpus_size(struct cpu_map *map)
    +{
    + return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
    +}
    +
    +static size_t mask_size(struct cpu_map *map, int *max)
    +{
    + int i;
    +
    + *max = 0;
    +
    + for (i = 0; i < map->nr; i++) {
    + /* bit possition of the cpu is + 1 */
    + int bit = map->map[i] + 1;
    +
    + if (bit > *max)
    + *max = bit;
    + }
    +
    + return sizeof(struct cpu_map_mask) + BITS_TO_LONGS(*max) * sizeof(long);
    +}
    +
    +void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max)
    +{
    + size_t size_cpus, size_mask;
    + bool is_dummy = cpu_map__empty(map);
    +
    + /*
    + * Both array and mask data have variable size based
    + * on the number of cpus and their actual values.
    + * The size of the 'struct cpu_map_data' is:
    + *
    + * array = size of 'struct cpu_map_entries' +
    + * number of cpus * sizeof(u64)
    + *
    + * mask = size of 'struct cpu_map_mask' +
    + * maximum cpu bit converted to size of longs
    + *
    + * and finaly + the size of 'struct cpu_map_data'.
    + */
    + size_cpus = cpus_size(map);
    + size_mask = mask_size(map, max);
    +
    + if (is_dummy || (size_cpus < size_mask)) {
    + *size += size_cpus;
    + *type = PERF_CPU_MAP__CPUS;
    + } else {
    + *size += size_mask;
    + *type = PERF_CPU_MAP__MASK;
    + }
    +
    + *size += sizeof(struct cpu_map_data);
    + return zalloc(*size);
    +}
    +
    +void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
    + u16 type, int max)
    +{
    + data->type = type;
    +
    + switch (type) {
    + case PERF_CPU_MAP__CPUS:
    + synthesize_cpus((struct cpu_map_entries *) data->data, map);
    + break;
    + case PERF_CPU_MAP__MASK:
    + synthesize_mask((struct cpu_map_mask *) data->data, map, max);
    + default:
    + break;
    + };
    +}
    +
    +static struct cpu_map_event* cpu_map_event__new(struct cpu_map *map)
    +{
    + size_t size = sizeof(struct cpu_map_event);
    + struct cpu_map_event *event;
    + int max;
    + u16 type;
    +
    + event = cpu_map_data__alloc(map, &size, &type, &max);
    + if (!event)
    + return NULL;
    +
    + event->header.type = PERF_RECORD_CPU_MAP;
    + event->header.size = size;
    + event->data.type = type;
    +
    + cpu_map_data__synthesize(&event->data, map, type, max);
    + return event;
    +}
    +
    +int perf_event__synthesize_cpu_map(struct perf_tool *tool,
    + struct cpu_map *map,
    + perf_event__handler_t process,
    + struct machine *machine)
    +{
    + struct cpu_map_event *event;
    + int err;
    +
    + event = cpu_map_event__new(map);
    + if (!event)
    + return -ENOMEM;
    +
    + err = process(tool, (union perf_event *) event, NULL, machine);
    +
    + free(event);
    + return err;
    +}
    +
    size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
    {
    const char *s;
    diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
    index 1c82a0e..de18ee0 100644
    --- a/tools/perf/util/event.h
    +++ b/tools/perf/util/event.h
    @@ -425,6 +425,7 @@ void perf_event__print_totals(void);

    struct perf_tool;
    struct thread_map;
    +struct cpu_map;

    typedef int (*perf_event__handler_t)(struct perf_tool *tool,
    union perf_event *event,
    @@ -440,6 +441,10 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
    struct thread_map *threads,
    perf_event__handler_t process,
    struct machine *machine);
    +int perf_event__synthesize_cpu_map(struct perf_tool *tool,
    + struct cpu_map *cpus,
    + perf_event__handler_t process,
    + struct machine *machine);
    int perf_event__synthesize_threads(struct perf_tool *tool,
    perf_event__handler_t process,
    struct machine *machine, bool mmap_data,
    @@ -550,4 +555,7 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp);
    u64 kallsyms__get_function_start(const char *kallsyms_filename,
    const char *symbol_name);

    +void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
    +void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
    + u16 type, int max);
    #endif /* __PERF_RECORD_H */

    \
     
     \ /
      Last update: 2015-12-18 10:41    [W:4.855 / U:0.176 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site