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) |
