diff options
| author | Jamie Gennis <jgennis@google.com> | 2012-11-21 20:14:09 -0800 | 
|---|---|---|
| committer | Arve Hjønnevåg <arve@android.com> | 2013-07-01 14:16:22 -0700 | 
| commit | 5b79789291da99a918f7b375f4c5cf9eb7417758 (patch) | |
| tree | 055e29e60323490d3fe7244508139e8f7c533851 /kernel | |
| parent | 7533724d29d13cde4f8b839ec066c5941a6674c8 (diff) | |
| download | olio-linux-3.10-5b79789291da99a918f7b375f4c5cf9eb7417758.tar.xz olio-linux-3.10-5b79789291da99a918f7b375f4c5cf9eb7417758.zip | |
trace: add non-hierarchical function_graph option
Add the 'funcgraph-flat' option to the function_graph tracer to use the default
trace printing format rather than the hierarchical formatting normally used.
Change-Id: If2900bfb86e6f8f51379f56da4f6fabafa630909
Signed-off-by: Jamie Gennis <jgennis@google.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/trace_functions_graph.c | 43 | ||||
| -rw-r--r-- | kernel/trace/trace_output.c | 164 | 
2 files changed, 176 insertions, 31 deletions
| diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 8388bc99f2e..28dd40c2c42 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c @@ -46,6 +46,8 @@ struct fgraph_data {  #define TRACE_GRAPH_PRINT_DURATION	0x10  #define TRACE_GRAPH_PRINT_ABS_TIME	0x20  #define TRACE_GRAPH_PRINT_IRQS		0x40 +#define TRACE_GRAPH_PRINT_FLAT		0x80 +  static unsigned int max_depth; @@ -64,6 +66,8 @@ static struct tracer_opt trace_opts[] = {  	{ TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },  	/* Display interrupts */  	{ TRACER_OPT(funcgraph-irqs, TRACE_GRAPH_PRINT_IRQS) }, +	/* Use standard trace formatting rather than hierarchical */ +	{ TRACER_OPT(funcgraph-flat, TRACE_GRAPH_PRINT_FLAT) },  	{ } /* Empty entry */  }; @@ -1234,6 +1238,9 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)  	int cpu = iter->cpu;  	int ret; +	if (flags & TRACE_GRAPH_PRINT_FLAT) +		return TRACE_TYPE_UNHANDLED; +  	if (data && per_cpu_ptr(data->cpu_data, cpu)->ignore) {  		per_cpu_ptr(data->cpu_data, cpu)->ignore = 0;  		return TRACE_TYPE_HANDLED; @@ -1291,13 +1298,6 @@ print_graph_function(struct trace_iterator *iter)  	return print_graph_function_flags(iter, tracer_flags.val);  } -static enum print_line_t -print_graph_function_event(struct trace_iterator *iter, int flags, -			   struct trace_event *event) -{ -	return print_graph_function(iter); -} -  static void print_lat_header(struct seq_file *s, u32 flags)  {  	static const char spaces[] = "                "	/* 16 spaces */ @@ -1364,6 +1364,11 @@ void print_graph_headers_flags(struct seq_file *s, u32 flags)  {  	struct trace_iterator *iter = s->private; +	if (flags & TRACE_GRAPH_PRINT_FLAT) { +		trace_default_header(s); +		return; +	} +  	if (!(trace_flags & TRACE_ITER_CONTEXT_INFO))  		return; @@ -1434,20 +1439,6 @@ static int func_graph_set_flag(u32 old_flags, u32 bit, int set)  	return 0;  } -static struct trace_event_functions graph_functions = { -	.trace		= print_graph_function_event, -}; - -static struct trace_event graph_trace_entry_event = { -	.type		= TRACE_GRAPH_ENT, -	.funcs		= &graph_functions, -}; - -static struct trace_event graph_trace_ret_event = { -	.type		= TRACE_GRAPH_RET, -	.funcs		= &graph_functions -}; -  static struct tracer graph_trace __read_mostly = {  	.name		= "function_graph",  	.open		= graph_trace_open, @@ -1523,16 +1514,6 @@ static __init int init_graph_trace(void)  {  	max_bytes_for_cpu = snprintf(NULL, 0, "%d", nr_cpu_ids - 1); -	if (!register_ftrace_event(&graph_trace_entry_event)) { -		pr_warning("Warning: could not register graph trace events\n"); -		return 1; -	} - -	if (!register_ftrace_event(&graph_trace_ret_event)) { -		pr_warning("Warning: could not register graph trace events\n"); -		return 1; -	} -  	return register_tracer(&graph_trace);  } diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c index 31994d2845e..a68e5e34c00 100644 --- a/kernel/trace/trace_output.c +++ b/kernel/trace/trace_output.c @@ -1049,6 +1049,168 @@ static struct trace_event trace_fn_event = {  	.funcs		= &trace_fn_funcs,  }; +/* TRACE_GRAPH_ENT */ +static enum print_line_t trace_graph_ent_trace(struct trace_iterator *iter, int flags, +					struct trace_event *event) +{ +	struct trace_seq *s = &iter->seq; +	struct ftrace_graph_ent_entry *field; + +	trace_assign_type(field, iter->ent); + +	if (!trace_seq_puts(s, "graph_ent: func=")) +		return TRACE_TYPE_PARTIAL_LINE; + +	if (!seq_print_ip_sym(s, field->graph_ent.func, flags)) +		return TRACE_TYPE_PARTIAL_LINE; + +	if (!trace_seq_puts(s, "\n")) +		return TRACE_TYPE_PARTIAL_LINE; + +	return TRACE_TYPE_HANDLED; +} + +static enum print_line_t trace_graph_ent_raw(struct trace_iterator *iter, int flags, +				      struct trace_event *event) +{ +	struct ftrace_graph_ent_entry *field; + +	trace_assign_type(field, iter->ent); + +	if (!trace_seq_printf(&iter->seq, "%lx %d\n", +			      field->graph_ent.func, +			      field->graph_ent.depth)) +		return TRACE_TYPE_PARTIAL_LINE; + +	return TRACE_TYPE_HANDLED; +} + +static enum print_line_t trace_graph_ent_hex(struct trace_iterator *iter, int flags, +				      struct trace_event *event) +{ +	struct ftrace_graph_ent_entry *field; +	struct trace_seq *s = &iter->seq; + +	trace_assign_type(field, iter->ent); + +	SEQ_PUT_HEX_FIELD_RET(s, field->graph_ent.func); +	SEQ_PUT_HEX_FIELD_RET(s, field->graph_ent.depth); + +	return TRACE_TYPE_HANDLED; +} + +static enum print_line_t trace_graph_ent_bin(struct trace_iterator *iter, int flags, +				      struct trace_event *event) +{ +	struct ftrace_graph_ent_entry *field; +	struct trace_seq *s = &iter->seq; + +	trace_assign_type(field, iter->ent); + +	SEQ_PUT_FIELD_RET(s, field->graph_ent.func); +	SEQ_PUT_FIELD_RET(s, field->graph_ent.depth); + +	return TRACE_TYPE_HANDLED; +} + +static struct trace_event_functions trace_graph_ent_funcs = { +	.trace		= trace_graph_ent_trace, +	.raw		= trace_graph_ent_raw, +	.hex		= trace_graph_ent_hex, +	.binary		= trace_graph_ent_bin, +}; + +static struct trace_event trace_graph_ent_event = { +	.type		= TRACE_GRAPH_ENT, +	.funcs		= &trace_graph_ent_funcs, +}; + +/* TRACE_GRAPH_RET */ +static enum print_line_t trace_graph_ret_trace(struct trace_iterator *iter, int flags, +					struct trace_event *event) +{ +	struct trace_seq *s = &iter->seq; +	struct trace_entry *entry = iter->ent; +	struct ftrace_graph_ret_entry *field; + +	trace_assign_type(field, entry); + +	if (!trace_seq_puts(s, "graph_ret: func=")) +		return TRACE_TYPE_PARTIAL_LINE; + +	if (!seq_print_ip_sym(s, field->ret.func, flags)) +		return TRACE_TYPE_PARTIAL_LINE; + +	if (!trace_seq_puts(s, "\n")) +		return TRACE_TYPE_PARTIAL_LINE; + +	return TRACE_TYPE_HANDLED; +} + +static enum print_line_t trace_graph_ret_raw(struct trace_iterator *iter, int flags, +				      struct trace_event *event) +{ +	struct ftrace_graph_ret_entry *field; + +	trace_assign_type(field, iter->ent); + +	if (!trace_seq_printf(&iter->seq, "%lx %lld %lld %ld %d\n", +			      field->ret.func, +			      field->ret.calltime, +			      field->ret.rettime, +			      field->ret.overrun, +			      field->ret.depth)); +		return TRACE_TYPE_PARTIAL_LINE; + +	return TRACE_TYPE_HANDLED; +} + +static enum print_line_t trace_graph_ret_hex(struct trace_iterator *iter, int flags, +				      struct trace_event *event) +{ +	struct ftrace_graph_ret_entry *field; +	struct trace_seq *s = &iter->seq; + +	trace_assign_type(field, iter->ent); + +	SEQ_PUT_HEX_FIELD_RET(s, field->ret.func); +	SEQ_PUT_HEX_FIELD_RET(s, field->ret.calltime); +	SEQ_PUT_HEX_FIELD_RET(s, field->ret.rettime); +	SEQ_PUT_HEX_FIELD_RET(s, field->ret.overrun); +	SEQ_PUT_HEX_FIELD_RET(s, field->ret.depth); + +	return TRACE_TYPE_HANDLED; +} + +static enum print_line_t trace_graph_ret_bin(struct trace_iterator *iter, int flags, +				      struct trace_event *event) +{ +	struct ftrace_graph_ret_entry *field; +	struct trace_seq *s = &iter->seq; + +	trace_assign_type(field, iter->ent); + +	SEQ_PUT_FIELD_RET(s, field->ret.func); +	SEQ_PUT_FIELD_RET(s, field->ret.calltime); +	SEQ_PUT_FIELD_RET(s, field->ret.rettime); +	SEQ_PUT_FIELD_RET(s, field->ret.overrun); +	SEQ_PUT_FIELD_RET(s, field->ret.depth); + +	return TRACE_TYPE_HANDLED; +} + +static struct trace_event_functions trace_graph_ret_funcs = { +	.trace		= trace_graph_ret_trace, +	.raw		= trace_graph_ret_raw, +	.hex		= trace_graph_ret_hex, +	.binary		= trace_graph_ret_bin, +}; + +static struct trace_event trace_graph_ret_event = { +	.type		= TRACE_GRAPH_RET, +	.funcs		= &trace_graph_ret_funcs, +}; +  /* TRACE_CTX an TRACE_WAKE */  static enum print_line_t trace_ctxwake_print(struct trace_iterator *iter,  					     char *delim) @@ -1439,6 +1601,8 @@ static struct trace_event trace_print_event = {  static struct trace_event *events[] __initdata = {  	&trace_fn_event, +	&trace_graph_ent_event, +	&trace_graph_ret_event,  	&trace_ctx_event,  	&trace_wake_event,  	&trace_stack_event, |