perf cpu_map: Add cpu_map user level event
authorJiri Olsa <jolsa@kernel.org>
Sun, 25 Oct 2015 14:51:23 +0000 (15:51 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 17 Dec 2015 17:38:17 +0000 (14:38 -0300)
Adding the cpu_map event to pass/store cpu maps as data in
a pipe/perf.data.

We store maps in 2 formats:
  - list of cpus
  - mask of cpus

The format that takes less space is selected transparently in the
following patch.

The interface is made generic, so we could add the cpumap event data
into another event in the following patches.

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-8-git-send-email-jolsa@kernel.org
[ cpu_map_data_cpus -> cpu_map_entries, cpu_map_data_mask -> cpu_map_mask ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/session.c
tools/perf/util/tool.h

index 938f006c758ed0a338519cbde0e4821ec29390c3..719c0781a82a84f756125cd93afd3d35816520f7 100644 (file)
@@ -38,6 +38,7 @@ static const char *perf_event__names[] = {
        [PERF_RECORD_AUXTRACE]                  = "AUXTRACE",
        [PERF_RECORD_AUXTRACE_ERROR]            = "AUXTRACE_ERROR",
        [PERF_RECORD_THREAD_MAP]                = "THREAD_MAP",
+       [PERF_RECORD_CPU_MAP]                   = "CPU_MAP",
 };
 
 const char *perf_event__name(unsigned int id)
index b7ad896d13171f15415002f213c54b7bb790f2ad..1c82a0ebda73b881029e8e0713b0f6dbb6e92b96 100644 (file)
@@ -227,6 +227,7 @@ enum perf_user_event_type { /* above any possible kernel type */
        PERF_RECORD_AUXTRACE                    = 71,
        PERF_RECORD_AUXTRACE_ERROR              = 72,
        PERF_RECORD_THREAD_MAP                  = 73,
+       PERF_RECORD_CPU_MAP                     = 74,
        PERF_RECORD_HEADER_MAX
 };
 
@@ -271,6 +272,32 @@ struct events_stats {
        u32 nr_proc_map_timeout;
 };
 
+enum {
+       PERF_CPU_MAP__CPUS = 0,
+       PERF_CPU_MAP__MASK = 1,
+};
+
+struct cpu_map_entries {
+       u16     nr;
+       u16     cpu[];
+};
+
+struct cpu_map_mask {
+       u16     nr;
+       u16     long_size;
+       unsigned long mask[];
+};
+
+struct cpu_map_data {
+       u16     type;
+       char    data[];
+};
+
+struct cpu_map_event {
+       struct perf_event_header        header;
+       struct cpu_map_data             data;
+};
+
 struct attr_event {
        struct perf_event_header header;
        struct perf_event_attr attr;
@@ -391,6 +418,7 @@ union perf_event {
        struct itrace_start_event       itrace_start;
        struct context_switch_event     context_switch;
        struct thread_map_event         thread_map;
+       struct cpu_map_event            cpu_map;
 };
 
 void perf_event__print_totals(void);
index 36b07b22392dcf0a24bdc8a93318ce97592e4c7e..4350f5e85bf5a51e0e2a5e57448994e6d0eafb0c 100644 (file)
@@ -306,6 +306,15 @@ int process_event_thread_map_stub(struct perf_tool *tool __maybe_unused,
        return 0;
 }
 
+static
+int process_event_cpu_map_stub(struct perf_tool *tool __maybe_unused,
+                              union perf_event *event __maybe_unused,
+                              struct perf_session *session __maybe_unused)
+{
+       dump_printf(": unhandled!\n");
+       return 0;
+}
+
 void perf_tool__fill_defaults(struct perf_tool *tool)
 {
        if (tool->sample == NULL)
@@ -358,6 +367,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
                tool->auxtrace_error = process_event_auxtrace_error_stub;
        if (tool->thread_map == NULL)
                tool->thread_map = process_event_thread_map_stub;
+       if (tool->cpu_map == NULL)
+               tool->cpu_map = process_event_cpu_map_stub;
 }
 
 static void swap_sample_id_all(union perf_event *event, void *data)
@@ -639,6 +650,42 @@ static void perf_event__thread_map_swap(union perf_event *event,
                event->thread_map.entries[i].pid = bswap_64(event->thread_map.entries[i].pid);
 }
 
+static void perf_event__cpu_map_swap(union perf_event *event,
+                                    bool sample_id_all __maybe_unused)
+{
+       struct cpu_map_data *data = &event->cpu_map.data;
+       struct cpu_map_entries *cpus;
+       struct cpu_map_mask *mask;
+       unsigned i;
+
+       data->type = bswap_64(data->type);
+
+       switch (data->type) {
+       case PERF_CPU_MAP__CPUS:
+               cpus = (struct cpu_map_entries *)data->data;
+
+               cpus->nr = bswap_16(cpus->nr);
+
+               for (i = 0; i < cpus->nr; i++)
+                       cpus->cpu[i] = bswap_16(cpus->cpu[i]);
+               break;
+       case PERF_CPU_MAP__MASK:
+               mask = (struct cpu_map_mask *) data->data;
+
+               mask->nr = bswap_16(mask->nr);
+               mask->long_size = bswap_16(mask->long_size);
+
+               switch (mask->long_size) {
+               case 4: mem_bswap_32(&mask->mask, mask->nr); break;
+               case 8: mem_bswap_64(&mask->mask, mask->nr); break;
+               default:
+                       pr_err("cpu_map swap: unsupported long size\n");
+               }
+       default:
+               break;
+       }
+}
+
 typedef void (*perf_event__swap_op)(union perf_event *event,
                                    bool sample_id_all);
 
@@ -667,6 +714,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
        [PERF_RECORD_AUXTRACE]            = perf_event__auxtrace_swap,
        [PERF_RECORD_AUXTRACE_ERROR]      = perf_event__auxtrace_error_swap,
        [PERF_RECORD_THREAD_MAP]          = perf_event__thread_map_swap,
+       [PERF_RECORD_CPU_MAP]             = perf_event__cpu_map_swap,
        [PERF_RECORD_HEADER_MAX]          = NULL,
 };
 
@@ -1205,6 +1253,8 @@ static s64 perf_session__process_user_event(struct perf_session *session,
                return tool->auxtrace_error(tool, event, session);
        case PERF_RECORD_THREAD_MAP:
                return tool->thread_map(tool, event, session);
+       case PERF_RECORD_CPU_MAP:
+               return tool->cpu_map(tool, event, session);
        default:
                return -EINVAL;
        }
index 1af4774960c3b85980f2ee2561d29a5a36cbe89c..9e5925c78519704cfe3c99ee89a2f480f35865f1 100644 (file)
@@ -56,7 +56,8 @@ struct perf_tool {
                        id_index,
                        auxtrace_info,
                        auxtrace_error,
-                       thread_map;
+                       thread_map,
+                       cpu_map;
        event_op3       auxtrace;
        bool            ordered_events;
        bool            ordering_requires_timestamps;