提交 0286039f 编写于 作者: A Adrian Hunter 提交者: Arnaldo Carvalho de Melo

perf tools: Add new PERF_RECORD_SWITCH event

Support processing of PERF_RECORD_SWITCH events and
PERF_RECORD_SWITCH_CPU_WIDE events. There is a single
tools callback for them both so that the tool must
check the event type before using the extra members
in PERF_RECORD_SWITCH_CPU_WIDE.

There is still no way to select the events, though.
That is added in a subsequest patch.
Signed-off-by: NAdrian Hunter <adrian.hunter@intel.com>
Acked-by: NPeter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: NJiri Olsa <jolsa@redhat.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1437471846-26995-3-git-send-email-adrian.hunter@intel.comSigned-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
上级 45ac1403
...@@ -561,6 +561,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -561,6 +561,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
.lost = perf_event__repipe, .lost = perf_event__repipe,
.aux = perf_event__repipe, .aux = perf_event__repipe,
.itrace_start = perf_event__repipe, .itrace_start = perf_event__repipe,
.context_switch = perf_event__repipe,
.read = perf_event__repipe_sample, .read = perf_event__repipe_sample,
.throttle = perf_event__repipe, .throttle = perf_event__repipe,
.unthrottle = perf_event__repipe, .unthrottle = perf_event__repipe,
......
...@@ -26,6 +26,8 @@ static const char *perf_event__names[] = { ...@@ -26,6 +26,8 @@ static const char *perf_event__names[] = {
[PERF_RECORD_AUX] = "AUX", [PERF_RECORD_AUX] = "AUX",
[PERF_RECORD_ITRACE_START] = "ITRACE_START", [PERF_RECORD_ITRACE_START] = "ITRACE_START",
[PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES", [PERF_RECORD_LOST_SAMPLES] = "LOST_SAMPLES",
[PERF_RECORD_SWITCH] = "SWITCH",
[PERF_RECORD_SWITCH_CPU_WIDE] = "SWITCH_CPU_WIDE",
[PERF_RECORD_HEADER_ATTR] = "ATTR", [PERF_RECORD_HEADER_ATTR] = "ATTR",
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE", [PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
...@@ -749,6 +751,14 @@ int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused, ...@@ -749,6 +751,14 @@ int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused,
return machine__process_lost_samples_event(machine, event, sample); return machine__process_lost_samples_event(machine, event, sample);
} }
int perf_event__process_switch(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
return machine__process_switch_event(machine, event);
}
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
{ {
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
...@@ -827,6 +837,20 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp) ...@@ -827,6 +837,20 @@ size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
event->itrace_start.pid, event->itrace_start.tid); event->itrace_start.pid, event->itrace_start.tid);
} }
size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
{
bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
const char *in_out = out ? "OUT" : "IN ";
if (event->header.type == PERF_RECORD_SWITCH)
return fprintf(fp, " %s\n", in_out);
return fprintf(fp, " %s %s pid/tid: %5u/%-5u\n",
in_out, out ? "next" : "prev",
event->context_switch.next_prev_pid,
event->context_switch.next_prev_tid);
}
size_t perf_event__fprintf(union perf_event *event, FILE *fp) size_t perf_event__fprintf(union perf_event *event, FILE *fp)
{ {
size_t ret = fprintf(fp, "PERF_RECORD_%s", size_t ret = fprintf(fp, "PERF_RECORD_%s",
...@@ -852,6 +876,10 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp) ...@@ -852,6 +876,10 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
case PERF_RECORD_ITRACE_START: case PERF_RECORD_ITRACE_START:
ret += perf_event__fprintf_itrace_start(event, fp); ret += perf_event__fprintf_itrace_start(event, fp);
break; break;
case PERF_RECORD_SWITCH:
case PERF_RECORD_SWITCH_CPU_WIDE:
ret += perf_event__fprintf_switch(event, fp);
break;
default: default:
ret += fprintf(fp, "\n"); ret += fprintf(fp, "\n");
} }
......
...@@ -348,6 +348,12 @@ struct itrace_start_event { ...@@ -348,6 +348,12 @@ struct itrace_start_event {
u32 pid, tid; u32 pid, tid;
}; };
struct context_switch_event {
struct perf_event_header header;
u32 next_prev_pid;
u32 next_prev_tid;
};
union perf_event { union perf_event {
struct perf_event_header header; struct perf_event_header header;
struct mmap_event mmap; struct mmap_event mmap;
...@@ -369,6 +375,7 @@ union perf_event { ...@@ -369,6 +375,7 @@ union perf_event {
struct auxtrace_error_event auxtrace_error; struct auxtrace_error_event auxtrace_error;
struct aux_event aux; struct aux_event aux;
struct itrace_start_event itrace_start; struct itrace_start_event itrace_start;
struct context_switch_event context_switch;
}; };
void perf_event__print_totals(void); void perf_event__print_totals(void);
...@@ -418,6 +425,10 @@ int perf_event__process_itrace_start(struct perf_tool *tool, ...@@ -418,6 +425,10 @@ int perf_event__process_itrace_start(struct perf_tool *tool,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
struct machine *machine); struct machine *machine);
int perf_event__process_switch(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
int perf_event__process_mmap(struct perf_tool *tool, int perf_event__process_mmap(struct perf_tool *tool,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
...@@ -480,6 +491,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); ...@@ -480,6 +491,7 @@ size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp); size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp); size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp);
size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp);
size_t perf_event__fprintf(union perf_event *event, FILE *fp); size_t perf_event__fprintf(union perf_event *event, FILE *fp);
u64 kallsyms__get_function_start(const char *kallsyms_filename, u64 kallsyms__get_function_start(const char *kallsyms_filename,
......
...@@ -1127,6 +1127,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, ...@@ -1127,6 +1127,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
PRINT_ATTRf(mmap2, p_unsigned); PRINT_ATTRf(mmap2, p_unsigned);
PRINT_ATTRf(comm_exec, p_unsigned); PRINT_ATTRf(comm_exec, p_unsigned);
PRINT_ATTRf(use_clockid, p_unsigned); PRINT_ATTRf(use_clockid, p_unsigned);
PRINT_ATTRf(context_switch, p_unsigned);
PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
PRINT_ATTRf(bp_type, p_unsigned); PRINT_ATTRf(bp_type, p_unsigned);
......
...@@ -550,6 +550,14 @@ int machine__process_itrace_start_event(struct machine *machine __maybe_unused, ...@@ -550,6 +550,14 @@ int machine__process_itrace_start_event(struct machine *machine __maybe_unused,
return 0; return 0;
} }
int machine__process_switch_event(struct machine *machine __maybe_unused,
union perf_event *event)
{
if (dump_trace)
perf_event__fprintf_switch(event, stdout);
return 0;
}
struct map *machine__findnew_module_map(struct machine *machine, u64 start, struct map *machine__findnew_module_map(struct machine *machine, u64 start,
const char *filename) const char *filename)
{ {
...@@ -1451,6 +1459,9 @@ int machine__process_event(struct machine *machine, union perf_event *event, ...@@ -1451,6 +1459,9 @@ int machine__process_event(struct machine *machine, union perf_event *event,
ret = machine__process_itrace_start_event(machine, event); break; ret = machine__process_itrace_start_event(machine, event); break;
case PERF_RECORD_LOST_SAMPLES: case PERF_RECORD_LOST_SAMPLES:
ret = machine__process_lost_samples_event(machine, event, sample); break; ret = machine__process_lost_samples_event(machine, event, sample); break;
case PERF_RECORD_SWITCH:
case PERF_RECORD_SWITCH_CPU_WIDE:
ret = machine__process_switch_event(machine, event); break;
default: default:
ret = -1; ret = -1;
break; break;
......
...@@ -87,6 +87,8 @@ int machine__process_aux_event(struct machine *machine, ...@@ -87,6 +87,8 @@ int machine__process_aux_event(struct machine *machine,
union perf_event *event); union perf_event *event);
int machine__process_itrace_start_event(struct machine *machine, int machine__process_itrace_start_event(struct machine *machine,
union perf_event *event); union perf_event *event);
int machine__process_switch_event(struct machine *machine __maybe_unused,
union perf_event *event);
int machine__process_mmap_event(struct machine *machine, union perf_event *event, int machine__process_mmap_event(struct machine *machine, union perf_event *event,
struct perf_sample *sample); struct perf_sample *sample);
int machine__process_mmap2_event(struct machine *machine, union perf_event *event, int machine__process_mmap2_event(struct machine *machine, union perf_event *event,
......
...@@ -333,6 +333,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) ...@@ -333,6 +333,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->aux = perf_event__process_aux; tool->aux = perf_event__process_aux;
if (tool->itrace_start == NULL) if (tool->itrace_start == NULL)
tool->itrace_start = perf_event__process_itrace_start; tool->itrace_start = perf_event__process_itrace_start;
if (tool->context_switch == NULL)
tool->context_switch = perf_event__process_switch;
if (tool->read == NULL) if (tool->read == NULL)
tool->read = process_event_sample_stub; tool->read = process_event_sample_stub;
if (tool->throttle == NULL) if (tool->throttle == NULL)
...@@ -471,6 +473,19 @@ static void perf_event__itrace_start_swap(union perf_event *event, ...@@ -471,6 +473,19 @@ static void perf_event__itrace_start_swap(union perf_event *event,
swap_sample_id_all(event, &event->itrace_start + 1); swap_sample_id_all(event, &event->itrace_start + 1);
} }
static void perf_event__switch_swap(union perf_event *event, bool sample_id_all)
{
if (event->header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
event->context_switch.next_prev_pid =
bswap_32(event->context_switch.next_prev_pid);
event->context_switch.next_prev_tid =
bswap_32(event->context_switch.next_prev_tid);
}
if (sample_id_all)
swap_sample_id_all(event, &event->context_switch + 1);
}
static void perf_event__throttle_swap(union perf_event *event, static void perf_event__throttle_swap(union perf_event *event,
bool sample_id_all) bool sample_id_all)
{ {
...@@ -633,6 +648,8 @@ static perf_event__swap_op perf_event__swap_ops[] = { ...@@ -633,6 +648,8 @@ static perf_event__swap_op perf_event__swap_ops[] = {
[PERF_RECORD_AUX] = perf_event__aux_swap, [PERF_RECORD_AUX] = perf_event__aux_swap,
[PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap, [PERF_RECORD_ITRACE_START] = perf_event__itrace_start_swap,
[PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap, [PERF_RECORD_LOST_SAMPLES] = perf_event__all64_swap,
[PERF_RECORD_SWITCH] = perf_event__switch_swap,
[PERF_RECORD_SWITCH_CPU_WIDE] = perf_event__switch_swap,
[PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap,
[PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
...@@ -1094,6 +1111,9 @@ static int machines__deliver_event(struct machines *machines, ...@@ -1094,6 +1111,9 @@ static int machines__deliver_event(struct machines *machines,
return tool->aux(tool, event, sample, machine); return tool->aux(tool, event, sample, machine);
case PERF_RECORD_ITRACE_START: case PERF_RECORD_ITRACE_START:
return tool->itrace_start(tool, event, sample, machine); return tool->itrace_start(tool, event, sample, machine);
case PERF_RECORD_SWITCH:
case PERF_RECORD_SWITCH_CPU_WIDE:
return tool->context_switch(tool, event, sample, machine);
default: default:
++evlist->stats.nr_unknown_events; ++evlist->stats.nr_unknown_events;
return -1; return -1;
......
...@@ -46,6 +46,7 @@ struct perf_tool { ...@@ -46,6 +46,7 @@ struct perf_tool {
lost_samples, lost_samples,
aux, aux,
itrace_start, itrace_start,
context_switch,
throttle, throttle,
unthrottle; unthrottle;
event_attr_op attr; event_attr_op attr;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册