Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0e950173 authored by Tim Bird's avatar Tim Bird Committed by Steven Rostedt
Browse files

function-graph: Add tracing_thresh support to function_graph tracer



Add support for tracing_thresh to the function_graph tracer.  This
version of this feature isolates the checks into new entry and
return functions, to avoid adding more conditional code into the
main function_graph paths.

When the tracing_thresh is set and the function graph tracer is
enabled, only the functions that took longer than the time in
microseconds that was set in tracing_thresh are recorded. To do this
efficiently, only the function exits are recorded:

 [tracing]# echo 100 > tracing_thresh
 [tracing]# echo function_graph > current_tracer
 [tracing]# cat trace
 # tracer: function_graph
 #
 # CPU  DURATION                  FUNCTION CALLS
 # |     |   |                     |   |   |   |
  1) ! 119.214 us  |  } /* smp_apic_timer_interrupt */
  1)   <========== |
  0) ! 101.527 us  |              } /* __rcu_process_callbacks */
  0) ! 126.461 us  |            } /* rcu_process_callbacks */
  0) ! 145.111 us  |          } /* __do_softirq */
  0) ! 149.667 us  |        } /* do_softirq */
  0) ! 168.817 us  |      } /* irq_exit */
  0) ! 248.254 us  |    } /* smp_apic_timer_interrupt */

Also, add support for specifying tracing_thresh on the kernel
command line.  When used like so: "tracing_thresh=200 ftrace=function_graph"
this can be used to analyse system startup.  It is important to disable
tracing soon after boot, in order to avoid losing the trace data.

Acked-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: default avatarTim Bird <tim.bird@am.sony.com>
LKML-Reference: <4B87098B.4040308@am.sony.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 1acaa1b2
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -374,6 +374,21 @@ static int __init set_buf_size(char *str)
}
}
__setup("trace_buf_size=", set_buf_size);
__setup("trace_buf_size=", set_buf_size);


static int __init set_tracing_thresh(char *str)
{
	unsigned long threshhold;
	int ret;

	if (!str)
		return 0;
	ret = strict_strtoul(str, 0, &threshhold);
	if (ret < 0)
		return 0;
	tracing_thresh = threshhold * 1000;
	return 1;
}
__setup("tracing_thresh=", set_tracing_thresh);

unsigned long nsecs_to_usecs(unsigned long nsecs)
unsigned long nsecs_to_usecs(unsigned long nsecs)
{
{
	return nsecs / 1000;
	return nsecs / 1000;
@@ -579,9 +594,10 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
static arch_spinlock_t ftrace_max_lock =
static arch_spinlock_t ftrace_max_lock =
	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
	(arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;


unsigned long __read_mostly	tracing_thresh;

#ifdef CONFIG_TRACER_MAX_TRACE
#ifdef CONFIG_TRACER_MAX_TRACE
unsigned long __read_mostly	tracing_max_latency;
unsigned long __read_mostly	tracing_max_latency;
unsigned long __read_mostly	tracing_thresh;


/*
/*
 * Copy the new maximum trace into the separate maximum-trace
 * Copy the new maximum trace into the separate maximum-trace
@@ -4248,10 +4264,10 @@ static __init int tracer_init_debugfs(void)
#ifdef CONFIG_TRACER_MAX_TRACE
#ifdef CONFIG_TRACER_MAX_TRACE
	trace_create_file("tracing_max_latency", 0644, d_tracer,
	trace_create_file("tracing_max_latency", 0644, d_tracer,
			&tracing_max_latency, &tracing_max_lat_fops);
			&tracing_max_latency, &tracing_max_lat_fops);
#endif


	trace_create_file("tracing_thresh", 0644, d_tracer,
	trace_create_file("tracing_thresh", 0644, d_tracer,
			&tracing_thresh, &tracing_max_lat_fops);
			&tracing_thresh, &tracing_max_lat_fops);
#endif


	trace_create_file("README", 0444, d_tracer,
	trace_create_file("README", 0444, d_tracer,
			NULL, &tracing_readme_fops);
			NULL, &tracing_readme_fops);
+2 −1
Original line number Original line Diff line number Diff line
@@ -396,9 +396,10 @@ extern int process_new_ksym_entry(char *ksymname, int op, unsigned long addr);


extern unsigned long nsecs_to_usecs(unsigned long nsecs);
extern unsigned long nsecs_to_usecs(unsigned long nsecs);


extern unsigned long tracing_thresh;

#ifdef CONFIG_TRACER_MAX_TRACE
#ifdef CONFIG_TRACER_MAX_TRACE
extern unsigned long tracing_max_latency;
extern unsigned long tracing_max_latency;
extern unsigned long tracing_thresh;


void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu);
void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu);
void update_max_tr_single(struct trace_array *tr,
void update_max_tr_single(struct trace_array *tr,
+23 −2
Original line number Original line Diff line number Diff line
@@ -237,6 +237,14 @@ int trace_graph_entry(struct ftrace_graph_ent *trace)
	return ret;
	return ret;
}
}


int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
{
	if (tracing_thresh)
		return 1;
	else
		return trace_graph_entry(trace);
}

static void __trace_graph_return(struct trace_array *tr,
static void __trace_graph_return(struct trace_array *tr,
				struct ftrace_graph_ret *trace,
				struct ftrace_graph_ret *trace,
				unsigned long flags,
				unsigned long flags,
@@ -290,11 +298,24 @@ void set_graph_array(struct trace_array *tr)
	smp_mb();
	smp_mb();
}
}


void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
{
	if (tracing_thresh &&
	    (trace->rettime - trace->calltime < tracing_thresh))
		return;
	else
		trace_graph_return(trace);
}

static int graph_trace_init(struct trace_array *tr)
static int graph_trace_init(struct trace_array *tr)
{
{
	int ret;
	int ret;


	set_graph_array(tr);
	set_graph_array(tr);
	if (tracing_thresh)
		ret = register_ftrace_graph(&trace_graph_thresh_return,
					    &trace_graph_thresh_entry);
	else
		ret = register_ftrace_graph(&trace_graph_return,
		ret = register_ftrace_graph(&trace_graph_return,
					    &trace_graph_entry);
					    &trace_graph_entry);
	if (ret)
	if (ret)