aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2008-11-11 01:14:25 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-11 04:29:12 -0500
commit15e6cb3673ea6277999642802406a764b49391b0 (patch)
treed0a46a918caa64d5fb1ed37be3e026b30e94fe77 /kernel/trace/trace.c
parentcaf4b323b02a16c92fba449952ac6515ddc76d7a (diff)
tracing: add a tracer to catch execution time of kernel functions
Impact: add new tracing plugin which can trace full (entry+exit) function calls This tracer uses the low level function return ftrace plugin to measure the execution time of the kernel functions. The first field is the caller of the function, the second is the measured function, and the last one is the execution time in nanoseconds. - v3: - HAVE_FUNCTION_RET_TRACER have been added. Each arch that support ftrace return should enable it. - ftrace_return_stub becomes ftrace_stub. - CONFIG_FUNCTION_RET_TRACER depends now on CONFIG_FUNCTION_TRACER - Return traces printing can be used for other tracers on trace.c - Adapt to the new tracing API (no more ctrl_update callback) - Correct the check of "disabled" during insertion. - Minor changes... Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c65
1 files changed, 57 insertions, 8 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 216bbe7547a4..a3f7ae9cd8e1 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -244,13 +244,6 @@ unsigned long nsecs_to_usecs(unsigned long nsecs)
244 return nsecs / 1000; 244 return nsecs / 1000;
245} 245}
246 246
247/*
248 * TRACE_ITER_SYM_MASK masks the options in trace_flags that
249 * control the output of kernel symbols.
250 */
251#define TRACE_ITER_SYM_MASK \
252 (TRACE_ITER_PRINT_PARENT|TRACE_ITER_SYM_OFFSET|TRACE_ITER_SYM_ADDR)
253
254/* These must match the bit postions in trace_iterator_flags */ 247/* These must match the bit postions in trace_iterator_flags */
255static const char *trace_options[] = { 248static const char *trace_options[] = {
256 "print-parent", 249 "print-parent",
@@ -810,6 +803,35 @@ trace_function(struct trace_array *tr, struct trace_array_cpu *data,
810 ring_buffer_unlock_commit(tr->buffer, event, irq_flags); 803 ring_buffer_unlock_commit(tr->buffer, event, irq_flags);
811} 804}
812 805
806#ifdef CONFIG_FUNCTION_RET_TRACER
807static void __trace_function_return(struct trace_array *tr,
808 struct trace_array_cpu *data,
809 struct ftrace_retfunc *trace,
810 unsigned long flags,
811 int pc)
812{
813 struct ring_buffer_event *event;
814 struct ftrace_ret_entry *entry;
815 unsigned long irq_flags;
816
817 if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
818 return;
819
820 event = ring_buffer_lock_reserve(global_trace.buffer, sizeof(*entry),
821 &irq_flags);
822 if (!event)
823 return;
824 entry = ring_buffer_event_data(event);
825 tracing_generic_entry_update(&entry->ent, flags, pc);
826 entry->ent.type = TRACE_FN_RET;
827 entry->ip = trace->func;
828 entry->parent_ip = trace->ret;
829 entry->rettime = trace->rettime;
830 entry->calltime = trace->calltime;
831 ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags);
832}
833#endif
834
813void 835void
814ftrace(struct trace_array *tr, struct trace_array_cpu *data, 836ftrace(struct trace_array *tr, struct trace_array_cpu *data,
815 unsigned long ip, unsigned long parent_ip, unsigned long flags, 837 unsigned long ip, unsigned long parent_ip, unsigned long flags,
@@ -1038,6 +1060,29 @@ function_trace_call(unsigned long ip, unsigned long parent_ip)
1038 raw_local_irq_restore(flags); 1060 raw_local_irq_restore(flags);
1039} 1061}
1040 1062
1063#ifdef CONFIG_FUNCTION_RET_TRACER
1064void trace_function_return(struct ftrace_retfunc *trace)
1065{
1066 struct trace_array *tr = &global_trace;
1067 struct trace_array_cpu *data;
1068 unsigned long flags;
1069 long disabled;
1070 int cpu;
1071 int pc;
1072
1073 raw_local_irq_save(flags);
1074 cpu = raw_smp_processor_id();
1075 data = tr->data[cpu];
1076 disabled = atomic_inc_return(&data->disabled);
1077 if (likely(disabled == 1)) {
1078 pc = preempt_count();
1079 __trace_function_return(tr, data, trace, flags, pc);
1080 }
1081 atomic_dec(&data->disabled);
1082 raw_local_irq_restore(flags);
1083}
1084#endif /* CONFIG_FUNCTION_RET_TRACER */
1085
1041static struct ftrace_ops trace_ops __read_mostly = 1086static struct ftrace_ops trace_ops __read_mostly =
1042{ 1087{
1043 .func = function_trace_call, 1088 .func = function_trace_call,
@@ -1285,7 +1330,7 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt,
1285# define IP_FMT "%016lx" 1330# define IP_FMT "%016lx"
1286#endif 1331#endif
1287 1332
1288static int 1333int
1289seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) 1334seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
1290{ 1335{
1291 int ret; 1336 int ret;
@@ -1738,6 +1783,10 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
1738 trace_seq_print_cont(s, iter); 1783 trace_seq_print_cont(s, iter);
1739 break; 1784 break;
1740 } 1785 }
1786 case TRACE_FN_RET: {
1787 return print_return_function(iter);
1788 break;
1789 }
1741 } 1790 }
1742 return TRACE_TYPE_HANDLED; 1791 return TRACE_TYPE_HANDLED;
1743} 1792}