diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-05-18 12:08:32 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-05-18 12:35:46 -0400 |
commit | 4f41c013f553957765902fb01475972f0af3e8e7 (patch) | |
tree | ddaa54947cc990094a4b270f2f8b3d6da195044f /kernel | |
parent | ef4f30f54e265c2f6f9ac9eda4db158a4e16050b (diff) |
perf/ftrace: Optimize perf/tracepoint interaction for single events
When we've got but a single event per tracepoint
there is no reason to try and multiplex it so don't.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Tested-by: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/perf_event.c | 15 | ||||
-rw-r--r-- | kernel/trace/trace_event_perf.c | 11 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 4 | ||||
-rw-r--r-- | kernel/trace/trace_syscalls.c | 6 |
4 files changed, 23 insertions, 13 deletions
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index a4fa381db3c2..17ac47f4bce6 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -4468,8 +4468,9 @@ static int swevent_hlist_get(struct perf_event *event) | |||
4468 | #ifdef CONFIG_EVENT_TRACING | 4468 | #ifdef CONFIG_EVENT_TRACING |
4469 | 4469 | ||
4470 | void perf_tp_event(int event_id, u64 addr, u64 count, void *record, | 4470 | void perf_tp_event(int event_id, u64 addr, u64 count, void *record, |
4471 | int entry_size, struct pt_regs *regs) | 4471 | int entry_size, struct pt_regs *regs, void *event) |
4472 | { | 4472 | { |
4473 | const int type = PERF_TYPE_TRACEPOINT; | ||
4473 | struct perf_sample_data data; | 4474 | struct perf_sample_data data; |
4474 | struct perf_raw_record raw = { | 4475 | struct perf_raw_record raw = { |
4475 | .size = entry_size, | 4476 | .size = entry_size, |
@@ -4479,9 +4480,13 @@ void perf_tp_event(int event_id, u64 addr, u64 count, void *record, | |||
4479 | perf_sample_data_init(&data, addr); | 4480 | perf_sample_data_init(&data, addr); |
4480 | data.raw = &raw; | 4481 | data.raw = &raw; |
4481 | 4482 | ||
4482 | /* Trace events already protected against recursion */ | 4483 | if (!event) { |
4483 | do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, | 4484 | do_perf_sw_event(type, event_id, count, 1, &data, regs); |
4484 | &data, regs); | 4485 | return; |
4486 | } | ||
4487 | |||
4488 | if (perf_swevent_match(event, type, event_id, &data, regs)) | ||
4489 | perf_swevent_add(event, count, 1, &data, regs); | ||
4485 | } | 4490 | } |
4486 | EXPORT_SYMBOL_GPL(perf_tp_event); | 4491 | EXPORT_SYMBOL_GPL(perf_tp_event); |
4487 | 4492 | ||
@@ -4514,7 +4519,7 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event) | |||
4514 | !capable(CAP_SYS_ADMIN)) | 4519 | !capable(CAP_SYS_ADMIN)) |
4515 | return ERR_PTR(-EPERM); | 4520 | return ERR_PTR(-EPERM); |
4516 | 4521 | ||
4517 | if (perf_trace_enable(event->attr.config)) | 4522 | if (perf_trace_enable(event->attr.config, event)) |
4518 | return NULL; | 4523 | return NULL; |
4519 | 4524 | ||
4520 | event->destroy = tp_perf_event_destroy; | 4525 | event->destroy = tp_perf_event_destroy; |
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 0565bb42566f..89b780a7c522 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c | |||
@@ -27,13 +27,15 @@ typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)]) | |||
27 | /* Count the events in use (per event id, not per instance) */ | 27 | /* Count the events in use (per event id, not per instance) */ |
28 | static int total_ref_count; | 28 | static int total_ref_count; |
29 | 29 | ||
30 | static int perf_trace_event_enable(struct ftrace_event_call *event) | 30 | static int perf_trace_event_enable(struct ftrace_event_call *event, void *data) |
31 | { | 31 | { |
32 | char *buf; | 32 | char *buf; |
33 | int ret = -ENOMEM; | 33 | int ret = -ENOMEM; |
34 | 34 | ||
35 | if (event->perf_refcount++ > 0) | 35 | if (event->perf_refcount++ > 0) { |
36 | event->perf_data = NULL; | ||
36 | return 0; | 37 | return 0; |
38 | } | ||
37 | 39 | ||
38 | if (!total_ref_count) { | 40 | if (!total_ref_count) { |
39 | buf = (char *)alloc_percpu(perf_trace_t); | 41 | buf = (char *)alloc_percpu(perf_trace_t); |
@@ -51,6 +53,7 @@ static int perf_trace_event_enable(struct ftrace_event_call *event) | |||
51 | 53 | ||
52 | ret = event->perf_event_enable(event); | 54 | ret = event->perf_event_enable(event); |
53 | if (!ret) { | 55 | if (!ret) { |
56 | event->perf_data = data; | ||
54 | total_ref_count++; | 57 | total_ref_count++; |
55 | return 0; | 58 | return 0; |
56 | } | 59 | } |
@@ -68,7 +71,7 @@ fail_buf: | |||
68 | return ret; | 71 | return ret; |
69 | } | 72 | } |
70 | 73 | ||
71 | int perf_trace_enable(int event_id) | 74 | int perf_trace_enable(int event_id, void *data) |
72 | { | 75 | { |
73 | struct ftrace_event_call *event; | 76 | struct ftrace_event_call *event; |
74 | int ret = -EINVAL; | 77 | int ret = -EINVAL; |
@@ -77,7 +80,7 @@ int perf_trace_enable(int event_id) | |||
77 | list_for_each_entry(event, &ftrace_events, list) { | 80 | list_for_each_entry(event, &ftrace_events, list) { |
78 | if (event->id == event_id && event->perf_event_enable && | 81 | if (event->id == event_id && event->perf_event_enable && |
79 | try_module_get(event->mod)) { | 82 | try_module_get(event->mod)) { |
80 | ret = perf_trace_event_enable(event); | 83 | ret = perf_trace_event_enable(event, data); |
81 | break; | 84 | break; |
82 | } | 85 | } |
83 | } | 86 | } |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index a7514326052b..2d7bf4146be8 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -1362,7 +1362,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp, | |||
1362 | for (i = 0; i < tp->nr_args; i++) | 1362 | for (i = 0; i < tp->nr_args; i++) |
1363 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); | 1363 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
1364 | 1364 | ||
1365 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); | 1365 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs, call->perf_data); |
1366 | } | 1366 | } |
1367 | 1367 | ||
1368 | /* Kretprobe profile handler */ | 1368 | /* Kretprobe profile handler */ |
@@ -1395,7 +1395,7 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, | |||
1395 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); | 1395 | call_fetch(&tp->args[i].fetch, regs, data + tp->args[i].offset); |
1396 | 1396 | ||
1397 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, | 1397 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, |
1398 | irq_flags, regs); | 1398 | irq_flags, regs, call->perf_data); |
1399 | } | 1399 | } |
1400 | 1400 | ||
1401 | static int probe_perf_enable(struct ftrace_event_call *call) | 1401 | static int probe_perf_enable(struct ftrace_event_call *call) |
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 4d6d711717f2..9eff1a4b49b9 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -468,7 +468,8 @@ static void perf_syscall_enter(struct pt_regs *regs, long id) | |||
468 | rec->nr = syscall_nr; | 468 | rec->nr = syscall_nr; |
469 | syscall_get_arguments(current, regs, 0, sys_data->nb_args, | 469 | syscall_get_arguments(current, regs, 0, sys_data->nb_args, |
470 | (unsigned long *)&rec->args); | 470 | (unsigned long *)&rec->args); |
471 | perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); | 471 | perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs, |
472 | sys_data->enter_event->perf_data); | ||
472 | } | 473 | } |
473 | 474 | ||
474 | int perf_sysenter_enable(struct ftrace_event_call *call) | 475 | int perf_sysenter_enable(struct ftrace_event_call *call) |
@@ -543,7 +544,8 @@ static void perf_syscall_exit(struct pt_regs *regs, long ret) | |||
543 | rec->nr = syscall_nr; | 544 | rec->nr = syscall_nr; |
544 | rec->ret = syscall_get_return_value(current, regs); | 545 | rec->ret = syscall_get_return_value(current, regs); |
545 | 546 | ||
546 | perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); | 547 | perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs, |
548 | sys_data->exit_event->perf_data); | ||
547 | } | 549 | } |
548 | 550 | ||
549 | int perf_sysexit_enable(struct ftrace_event_call *call) | 551 | int perf_sysexit_enable(struct ftrace_event_call *call) |