lkml.org 
[lkml]   [2015]   [Oct]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 08/52] perf tools: Add cpu_map event synthesize function
    Date
    Introduce perf_event__synthesize_cpu_map function to
    synthesize struct cpu_map.

    Added generic interface:
    cpu_map_data__alloc
    cpu_map_data__synthesize

    to make the cpu_map synthesizing usable for other events.

    Link: http://lkml.kernel.org/n/tip-miidn8vqsx3udu4ct8103v5f@git.kernel.org
    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    ---
    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(+)
    create mode 100644 tools/perf/tests/cpumap.c

    diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
    index 50de2253cff6..1c0296fc95ea 100644
    --- a/tools/perf/tests/Build
    +++ b/tools/perf/tests/Build
    @@ -33,6 +33,7 @@ perf-y += kmod-path.o
    perf-y += thread-map.o
    perf-y += llvm.o
    perf-y += topology.o
    +perf-y += cpumap.o

    ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
    perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
    diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
    index a59fd320da64..bdccd27868ba 100644
    --- a/tools/perf/tests/builtin-test.c
    +++ b/tools/perf/tests/builtin-test.c
    @@ -170,6 +170,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 000000000000..dc923ec7688f
    --- /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_data_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_data_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_data_cpus *cpus;
    + struct cpu_map_data *data;
    +
    + data = &map->data;
    +
    + TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS);
    +
    + cpus = (struct cpu_map_data_cpus *) 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(void)
    +{
    + 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 2e280a5cd579..c7f3c3211bcf 100644
    --- a/tools/perf/tests/tests.h
    +++ b/tools/perf/tests/tests.h
    @@ -68,6 +68,7 @@ int test__thread_map(void);
    int test__llvm(void);
    int test_session_topology(void);
    int test__thread_map_synthesize(void);
    +int test__cpu_map_synthesize(void);

    #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 c05f4b036069..a04bdabb7ae9 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_data_cpus *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_data_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_data_cpus) + 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_data_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_data_cpus' +
    + * number of cpus * sizeof(u64)
    + *
    + * mask = size of 'struct cpu_map_data_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_data_cpus *) data->data, map);
    + break;
    + case PERF_CPU_MAP__MASK:
    + synthesize_mask((struct cpu_map_data_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 4df6f9c60406..5f5560d039d7 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 */
    --
    2.4.3


    \
     
     \ /
      Last update: 2015-10-25 16:21    [W:4.261 / U:0.340 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site