Commit 6640b6c2 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

perf cpu_map: Add cpu_map user level event

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: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarKan 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent ec7fa596
......@@ -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)
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment