From: Ingo Molnar Date: Mon, 24 Nov 2008 16:46:24 +0000 (+0100) Subject: Merge branches 'tracing/branch-tracer', 'tracing/fastboot', 'tracing/ftrace', 'tracin... X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=6f893fb2e89287a4d755f928c3cda9d18440355c;p=linux-beck.git Merge branches 'tracing/branch-tracer', 'tracing/fastboot', 'tracing/ftrace', 'tracing/function-return-tracer', 'tracing/power-tracer', 'tracing/powerpc', 'tracing/ring-buffer', 'tracing/stack-tracer' and 'tracing/urgent' into tracing/core --- 6f893fb2e89287a4d755f928c3cda9d18440355c diff --cc include/linux/ftrace.h index f7ba4ea5e128,f7ba4ea5e128,13e9cfc09928,938ca1942641,f7ba4ea5e128,703eb53cfa2b,f7ba4ea5e128,f7ba4ea5e128,703eb53cfa2b..7854d87b97b2 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@@@@@@@@@ -253,11 -253,11 -253,12 -253,11 -253,11 -181,6 -253,11 -253,11 -181,6 +253,12 @@@@@@@@@@ static inline void __ftrace_enabled_res #endif #ifdef CONFIG_TRACING + +extern int ftrace_dump_on_oops; + + + +extern void tracing_start(void); + +extern void tracing_stop(void); ++ ++++++extern void ftrace_off_permanent(void); + + extern void ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3); @@@@@@@@@@ -288,8 -288,8 -289,9 -288,8 -288,8 -211,6 -288,8 -288,8 -211,6 +289,9 @@@@@@@@@@ ftrace_special(unsigned long arg1, unsi static inline int ftrace_printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 0))); + +static inline void tracing_start(void) { } + +static inline void tracing_stop(void) { } ++ ++++++static inline void ftrace_off_permanent(void) { } static inline int ftrace_printk(const char *fmt, ...) { @@@@@@@@@@ -310,26 -310,26 -312,26 -310,34 -310,26 -229,25 -310,26 -310,26 -229,25 +312,34 @@@@@@@@@@ ftrace_init_module(struct module *mod #endif - -struct boot_trace { - - pid_t caller; - - char func[KSYM_NAME_LEN]; - - int result; - - unsigned long long duration; /* usecs */ - - ktime_t calltime; - - ktime_t rettime; + +/* + + * Structure that defines a return function trace. + + */ + +struct ftrace_retfunc { + + unsigned long ret; /* Return address */ + + unsigned long func; /* Current function */ + + unsigned long long calltime; + + unsigned long long rettime; + + /* Number of functions that overran the depth limit for current task */ + + unsigned long overrun; }; - -#ifdef CONFIG_BOOT_TRACER - -extern void trace_boot(struct boot_trace *it, initcall_t fn); - -extern void start_boot_trace(void); - -extern void stop_boot_trace(void); - -#else - -static inline void trace_boot(struct boot_trace *it, initcall_t fn) { } - -static inline void start_boot_trace(void) { } - -static inline void stop_boot_trace(void) { } - -#endif + +#ifdef CONFIG_FUNCTION_RET_TRACER +++ +++++#define FTRACE_RETFUNC_DEPTH 50 +++ +++++#define FTRACE_RETSTACK_ALLOC_SIZE 32 + +/* Type of a callback handler of tracing return function */ + +typedef void (*trace_function_return_t)(struct ftrace_retfunc *); + +extern int register_ftrace_return(trace_function_return_t func); + +/* The current handler in use */ + +extern trace_function_return_t ftrace_function_return; + +extern void unregister_ftrace_return(void); +++ + ++ +++ +++++extern void ftrace_retfunc_init_task(struct task_struct *t); +++ +++++extern void ftrace_retfunc_exit_task(struct task_struct *t); +++ +++++#else +++ +++++static inline void ftrace_retfunc_init_task(struct task_struct *t) { } +++ +++++static inline void ftrace_retfunc_exit_task(struct task_struct *t) { } + +#endif #endif /* _LINUX_FTRACE_H */ diff --cc kernel/trace/Kconfig index 61e8cca6ff45,b8378fad29a3,b8378fad29a3,b8378fad29a3,b8378fad29a3,33dbefd471e8,b8378fad29a3,87fc34a1bb91,33dbefd471e8..9cbf7761f498 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@@@@@@@@@ -158,59 -158,44 -158,44 -158,44 -158,44 -138,6 -158,44 -161,44 -138,6 +161,59 @@@@@@@@@@ config BOOT_TRACE selected, because the self-tests are an initcall as well and that would invalidate the boot trace. ) + +config TRACE_BRANCH_PROFILING + + bool "Trace likely/unlikely profiler" + + depends on DEBUG_KERNEL + + select TRACING + + help + + This tracer profiles all the the likely and unlikely macros + + in the kernel. It will display the results in: + + ---- -- /debugfs/tracing/profile_likely ---- -- /debugfs/tracing/profile_unlikely ++++++++ /debugfs/tracing/profile_annotated_branch + + + + Note: this will add a significant overhead, only turn this + + on if you need to profile the system's use of these macros. + + + + Say N if unsure. + + ++++++++config PROFILE_ALL_BRANCHES ++++++++ bool "Profile all if conditionals" ++++++++ depends on TRACE_BRANCH_PROFILING ++++++++ help ++++++++ This tracer profiles all branch conditions. Every if () ++++++++ taken in the kernel is recorded whether it hit or miss. ++++++++ The results will be displayed in: ++++++++ ++++++++ /debugfs/tracing/profile_branch ++++++++ ++++++++ This configuration, when enabled, will impose a great overhead ++++++++ on the system. This should only be enabled when the system ++++++++ is to be analyzed ++++++++ ++++++++ Say N if unsure. ++++++++ + +config TRACING_BRANCHES + + bool + + help + + Selected by tracers that will trace the likely and unlikely + + conditions. This prevents the tracers themselves from being + + profiled. Profiling the tracing infrastructure can only happen + + when the likelys and unlikelys are not being traced. + + + +config BRANCH_TRACER + + bool "Trace likely/unlikely instances" + + depends on TRACE_BRANCH_PROFILING + + select TRACING_BRANCHES + + help + + This traces the events of likely and unlikely condition + + calls in the kernel. The difference between this and the + + "Trace likely/unlikely profiler" is that this is not a + + histogram of the callers, but actually places the calling + + events into a running trace buffer to see when and where the + + events happened, as well as their results. + + + + Say N if unsure. + + config STACK_TRACER bool "Trace max stack" depends on HAVE_FUNCTION_TRACER diff --cc kernel/trace/trace.c index 4ee6f0375222,4ee6f0375222,0dbfb23ced97,4ee6f0375222,4ee6f0375222,d86e3252f300,4ee6f0375222,48d1536f1ca4,d86e3252f300..a45b59e53fbc --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@@@@@@@@@ -272,9 -272,9 -272,9 -272,9 -272,9 -213,6 -272,9 -273,11 -213,6 +273,11 @@@@@@@@@@ static const char *trace_options[] = "stacktrace", "sched-tree", "ftrace_printk", + + "ftrace_preempt", + + "branch", + + "annotate", +++++++ + "userstacktrace", +++++++ + "sym-userobj", NULL }; @@@@@@@@@@ -657,76 -657,76 -657,91 -657,76 -657,76 -581,6 -657,76 -682,76 -581,6 +682,91 @@@@@@@@@@ static void trace_init_cmdlines(void cmdline_idx = 0; } + +static int trace_stop_count; + +static DEFINE_SPINLOCK(tracing_start_lock); + + ++ ++++++/** ++ ++++++ * ftrace_off_permanent - disable all ftrace code permanently ++ ++++++ * ++ ++++++ * This should only be called when a serious anomally has ++ ++++++ * been detected. This will turn off the function tracing, ++ ++++++ * ring buffers, and other tracing utilites. It takes no ++ ++++++ * locks and can be called from any context. ++ ++++++ */ ++ ++++++void ftrace_off_permanent(void) ++ ++++++{ ++ ++++++ tracing_disabled = 1; ++ ++++++ ftrace_stop(); ++ ++++++ tracing_off_permanent(); ++ ++++++} ++ ++++++ + +/** + + * tracing_start - quick start of the tracer + + * + + * If tracing is enabled but was stopped by tracing_stop, + + * this will start the tracer back up. + + */ + +void tracing_start(void) + +{ + + struct ring_buffer *buffer; + + unsigned long flags; + + + + if (tracing_disabled) + + return; + + + + spin_lock_irqsave(&tracing_start_lock, flags); + + if (--trace_stop_count) + + goto out; + + + + if (trace_stop_count < 0) { + + /* Someone screwed up their debugging */ + + WARN_ON_ONCE(1); + + trace_stop_count = 0; + + goto out; + + } + + + + + + buffer = global_trace.buffer; + + if (buffer) + + ring_buffer_record_enable(buffer); + + + + buffer = max_tr.buffer; + + if (buffer) + + ring_buffer_record_enable(buffer); + + + + ftrace_start(); + + out: + + spin_unlock_irqrestore(&tracing_start_lock, flags); + +} + + + +/** + + * tracing_stop - quick stop of the tracer + + * + + * Light weight way to stop tracing. Use in conjunction with + + * tracing_start. + + */ + +void tracing_stop(void) + +{ + + struct ring_buffer *buffer; + + unsigned long flags; + + + + ftrace_stop(); + + spin_lock_irqsave(&tracing_start_lock, flags); + + if (trace_stop_count++) + + goto out; + + + + buffer = global_trace.buffer; + + if (buffer) + + ring_buffer_record_disable(buffer); + + + + buffer = max_tr.buffer; + + if (buffer) + + ring_buffer_record_disable(buffer); + + + + out: + + spin_unlock_irqrestore(&tracing_start_lock, flags); + +} + + void trace_stop_cmdline_recording(void); static void trace_save_cmdline(struct task_struct *tsk) @@@@@@@@@@ -1690,18 -1690,18 -1705,18 -1690,18 -1690,18 -1448,6 -1690,18 -1829,27 -1448,6 +1844,27 @@@@@@@@@@ print_lat_fmt(struct trace_iterator *it trace_seq_print_cont(s, iter); break; } + + case TRACE_BRANCH: { + + struct trace_branch *field; + + + + trace_assign_type(field, entry); + + + + trace_seq_printf(s, "[%s] %s:%s:%d\n", + + field->correct ? " ok " : " MISS ", + + field->func, + + field->file, + + field->line); + + break; + + } +++++++ + case TRACE_USER_STACK: { +++++++ + struct userstack_entry *field; +++++++ + +++++++ + trace_assign_type(field, entry); +++++++ + +++++++ + seq_print_userip_objs(field, s, sym_flags); +++++++ + trace_seq_putc(s, '\n'); +++++++ + break; +++++++ + } default: trace_seq_printf(s, "Unknown type %d\n", entry->type); } @@@@@@@@@@ -1837,22 -1837,22 -1852,22 -1837,22 -1837,22 -1581,6 -1837,22 -1985,35 -1581,6 +2000,35 @@@@@@@@@@ static enum print_line_t print_trace_fm trace_seq_print_cont(s, iter); break; } + + case TRACE_FN_RET: { + + return print_return_function(iter); + + break; + + } + + case TRACE_BRANCH: { + + struct trace_branch *field; + + + + trace_assign_type(field, entry); + + + + trace_seq_printf(s, "[%s] %s:%s:%d\n", + + field->correct ? " ok " : " MISS ", + + field->func, + + field->file, + + field->line); + + break; + + } +++++++ + case TRACE_USER_STACK: { +++++++ + struct userstack_entry *field; +++++++ + +++++++ + trace_assign_type(field, entry); +++++++ + +++++++ + ret = seq_print_userip_objs(field, s, sym_flags); +++++++ + if (!ret) +++++++ + return TRACE_TYPE_PARTIAL_LINE; +++++++ + ret = trace_seq_putc(s, '\n'); +++++++ + if (!ret) +++++++ + return TRACE_TYPE_PARTIAL_LINE; +++++++ + break; +++++++ + } } return TRACE_TYPE_HANDLED; }