Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
Merge branch 'tip/perf/core' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/rostedt/linux-2.6-trace into perf/core
  • Loading branch information
Ingo Molnar committed Oct 19, 2010
2 parents 3f7edb1 + 7e40798 commit 750ed15
Show file tree
Hide file tree
Showing 6 changed files with 373 additions and 131 deletions.
4 changes: 2 additions & 2 deletions kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1638,8 +1638,8 @@ ftrace_failures_open(struct inode *inode, struct file *file)

ret = ftrace_avail_open(inode, file);
if (!ret) {
m = (struct seq_file *)file->private_data;
iter = (struct ftrace_iterator *)m->private;
m = file->private_data;
iter = m->private;
iter->flags = FTRACE_ITER_FAILURES;
}

Expand Down
2 changes: 1 addition & 1 deletion kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -2196,7 +2196,7 @@ int tracing_open_generic(struct inode *inode, struct file *filp)

static int tracing_release(struct inode *inode, struct file *file)
{
struct seq_file *m = (struct seq_file *)file->private_data;
struct seq_file *m = file->private_data;
struct trace_iterator *iter;
int cpu;

Expand Down
4 changes: 4 additions & 0 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ void trace_function(struct trace_array *tr,
unsigned long ip,
unsigned long parent_ip,
unsigned long flags, int pc);
void trace_graph_function(struct trace_array *tr,
unsigned long ip,
unsigned long parent_ip,
unsigned long flags, int pc);
void trace_default_header(struct seq_file *m);
void print_trace_header(struct seq_file *m, struct trace_iterator *iter);
int trace_empty(struct trace_iterator *iter);
Expand Down
86 changes: 79 additions & 7 deletions kernel/trace/trace_functions_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,34 @@ int trace_graph_thresh_entry(struct ftrace_graph_ent *trace)
return trace_graph_entry(trace);
}

static void
__trace_graph_function(struct trace_array *tr,
unsigned long ip, unsigned long flags, int pc)
{
u64 time = trace_clock_local();
struct ftrace_graph_ent ent = {
.func = ip,
.depth = 0,
};
struct ftrace_graph_ret ret = {
.func = ip,
.depth = 0,
.calltime = time,
.rettime = time,
};

__trace_graph_entry(tr, &ent, flags, pc);
__trace_graph_return(tr, &ret, flags, pc);
}

void
trace_graph_function(struct trace_array *tr,
unsigned long ip, unsigned long parent_ip,
unsigned long flags, int pc)
{
__trace_graph_function(tr, ip, flags, pc);
}

void __trace_graph_return(struct trace_array *tr,
struct ftrace_graph_ret *trace,
unsigned long flags,
Expand Down Expand Up @@ -888,12 +916,20 @@ check_irq_entry(struct trace_iterator *iter, u32 flags,
unsigned long addr, int depth)
{
int cpu = iter->cpu;
int *depth_irq;
struct fgraph_data *data = iter->private;
int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);

if (flags & TRACE_GRAPH_PRINT_IRQS)
/*
* If we are either displaying irqs, or we got called as
* a graph event and private data does not exist,
* then we bypass the irq check.
*/
if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
(!data))
return 0;

depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);

/*
* We are inside the irq code
*/
Expand Down Expand Up @@ -926,12 +962,20 @@ static int
check_irq_return(struct trace_iterator *iter, u32 flags, int depth)
{
int cpu = iter->cpu;
int *depth_irq;
struct fgraph_data *data = iter->private;
int *depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);

if (flags & TRACE_GRAPH_PRINT_IRQS)
/*
* If we are either displaying irqs, or we got called as
* a graph event and private data does not exist,
* then we bypass the irq check.
*/
if ((flags & TRACE_GRAPH_PRINT_IRQS) ||
(!data))
return 0;

depth_irq = &(per_cpu_ptr(data->cpu_data, cpu)->depth_irq);

/*
* We are not inside the irq code.
*/
Expand Down Expand Up @@ -1163,7 +1207,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,


enum print_line_t
print_graph_function_flags(struct trace_iterator *iter, u32 flags)
__print_graph_function_flags(struct trace_iterator *iter, u32 flags)
{
struct ftrace_graph_ent_entry *field;
struct fgraph_data *data = iter->private;
Expand Down Expand Up @@ -1226,7 +1270,18 @@ print_graph_function_flags(struct trace_iterator *iter, u32 flags)
static enum print_line_t
print_graph_function(struct trace_iterator *iter)
{
return print_graph_function_flags(iter, tracer_flags.val);
return __print_graph_function_flags(iter, tracer_flags.val);
}

enum print_line_t print_graph_function_flags(struct trace_iterator *iter,
u32 flags)
{
if (trace_flags & TRACE_ITER_LATENCY_FMT)
flags |= TRACE_GRAPH_PRINT_DURATION;
else
flags |= TRACE_GRAPH_PRINT_ABS_TIME;

return __print_graph_function_flags(iter, flags);
}

static enum print_line_t
Expand Down Expand Up @@ -1258,7 +1313,7 @@ static void print_lat_header(struct seq_file *s, u32 flags)
seq_printf(s, "#%.*s|||| / \n", size, spaces);
}

void print_graph_headers_flags(struct seq_file *s, u32 flags)
static void __print_graph_headers_flags(struct seq_file *s, u32 flags)
{
int lat = trace_flags & TRACE_ITER_LATENCY_FMT;

Expand Down Expand Up @@ -1299,6 +1354,23 @@ void print_graph_headers(struct seq_file *s)
print_graph_headers_flags(s, tracer_flags.val);
}

void print_graph_headers_flags(struct seq_file *s, u32 flags)
{
struct trace_iterator *iter = s->private;

if (trace_flags & TRACE_ITER_LATENCY_FMT) {
/* print nothing if the buffers are empty */
if (trace_empty(iter))
return;

print_trace_header(s, iter);
flags |= TRACE_GRAPH_PRINT_DURATION;
} else
flags |= TRACE_GRAPH_PRINT_ABS_TIME;

__print_graph_headers_flags(s, flags);
}

void graph_trace_open(struct trace_iterator *iter)
{
/* pid and depth on the last trace processed */
Expand Down
152 changes: 55 additions & 97 deletions kernel/trace/trace_irqsoff.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,22 @@ static __cacheline_aligned_in_smp unsigned long max_sequence;

#ifdef CONFIG_FUNCTION_TRACER
/*
* irqsoff uses its own tracer function to keep the overhead down:
* Prologue for the preempt and irqs off function tracers.
*
* Returns 1 if it is OK to continue, and data->disabled is
* incremented.
* 0 if the trace is to be ignored, and data->disabled
* is kept the same.
*
* Note, this function is also used outside this ifdef but
* inside the #ifdef of the function graph tracer below.
* This is OK, since the function graph tracer is
* dependent on the function tracer.
*/
static void
irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
static int func_prolog_dec(struct trace_array *tr,
struct trace_array_cpu **data,
unsigned long *flags)
{
struct trace_array *tr = irqsoff_trace;
struct trace_array_cpu *data;
unsigned long flags;
long disabled;
int cpu;

Expand All @@ -106,18 +114,38 @@ irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
*/
cpu = raw_smp_processor_id();
if (likely(!per_cpu(tracing_cpu, cpu)))
return;
return 0;

local_save_flags(flags);
local_save_flags(*flags);
/* slight chance to get a false positive on tracing_cpu */
if (!irqs_disabled_flags(flags))
return;
if (!irqs_disabled_flags(*flags))
return 0;

data = tr->data[cpu];
disabled = atomic_inc_return(&data->disabled);
*data = tr->data[cpu];
disabled = atomic_inc_return(&(*data)->disabled);

if (likely(disabled == 1))
trace_function(tr, ip, parent_ip, flags, preempt_count());
return 1;

atomic_dec(&(*data)->disabled);

return 0;
}

/*
* irqsoff uses its own tracer function to keep the overhead down:
*/
static void
irqsoff_tracer_call(unsigned long ip, unsigned long parent_ip)
{
struct trace_array *tr = irqsoff_trace;
struct trace_array_cpu *data;
unsigned long flags;

if (!func_prolog_dec(tr, &data, &flags))
return;

trace_function(tr, ip, parent_ip, flags, preempt_count());

atomic_dec(&data->disabled);
}
Expand Down Expand Up @@ -155,30 +183,16 @@ static int irqsoff_graph_entry(struct ftrace_graph_ent *trace)
struct trace_array *tr = irqsoff_trace;
struct trace_array_cpu *data;
unsigned long flags;
long disabled;
int ret;
int cpu;
int pc;

cpu = raw_smp_processor_id();
if (likely(!per_cpu(tracing_cpu, cpu)))
if (!func_prolog_dec(tr, &data, &flags))
return 0;

local_save_flags(flags);
/* slight chance to get a false positive on tracing_cpu */
if (!irqs_disabled_flags(flags))
return 0;

data = tr->data[cpu];
disabled = atomic_inc_return(&data->disabled);

if (likely(disabled == 1)) {
pc = preempt_count();
ret = __trace_graph_entry(tr, trace, flags, pc);
} else
ret = 0;

pc = preempt_count();
ret = __trace_graph_entry(tr, trace, flags, pc);
atomic_dec(&data->disabled);

return ret;
}

Expand All @@ -187,27 +201,13 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace)
struct trace_array *tr = irqsoff_trace;
struct trace_array_cpu *data;
unsigned long flags;
long disabled;
int cpu;
int pc;

cpu = raw_smp_processor_id();
if (likely(!per_cpu(tracing_cpu, cpu)))
if (!func_prolog_dec(tr, &data, &flags))
return;

local_save_flags(flags);
/* slight chance to get a false positive on tracing_cpu */
if (!irqs_disabled_flags(flags))
return;

data = tr->data[cpu];
disabled = atomic_inc_return(&data->disabled);

if (likely(disabled == 1)) {
pc = preempt_count();
__trace_graph_return(tr, trace, flags, pc);
}

pc = preempt_count();
__trace_graph_return(tr, trace, flags, pc);
atomic_dec(&data->disabled);
}

Expand All @@ -229,75 +229,33 @@ static void irqsoff_trace_close(struct trace_iterator *iter)

static enum print_line_t irqsoff_print_line(struct trace_iterator *iter)
{
u32 flags = GRAPH_TRACER_FLAGS;

if (trace_flags & TRACE_ITER_LATENCY_FMT)
flags |= TRACE_GRAPH_PRINT_DURATION;
else
flags |= TRACE_GRAPH_PRINT_ABS_TIME;

/*
* In graph mode call the graph tracer output function,
* otherwise go with the TRACE_FN event handler
*/
if (is_graph())
return print_graph_function_flags(iter, flags);
return print_graph_function_flags(iter, GRAPH_TRACER_FLAGS);

return TRACE_TYPE_UNHANDLED;
}

static void irqsoff_print_header(struct seq_file *s)
{
if (is_graph()) {
struct trace_iterator *iter = s->private;
u32 flags = GRAPH_TRACER_FLAGS;

if (trace_flags & TRACE_ITER_LATENCY_FMT) {
/* print nothing if the buffers are empty */
if (trace_empty(iter))
return;

print_trace_header(s, iter);
flags |= TRACE_GRAPH_PRINT_DURATION;
} else
flags |= TRACE_GRAPH_PRINT_ABS_TIME;

print_graph_headers_flags(s, flags);
} else
if (is_graph())
print_graph_headers_flags(s, GRAPH_TRACER_FLAGS);
else
trace_default_header(s);
}

static void
trace_graph_function(struct trace_array *tr,
unsigned long ip, unsigned long flags, int pc)
{
u64 time = trace_clock_local();
struct ftrace_graph_ent ent = {
.func = ip,
.depth = 0,
};
struct ftrace_graph_ret ret = {
.func = ip,
.depth = 0,
.calltime = time,
.rettime = time,
};

__trace_graph_entry(tr, &ent, flags, pc);
__trace_graph_return(tr, &ret, flags, pc);
}

static void
__trace_function(struct trace_array *tr,
unsigned long ip, unsigned long parent_ip,
unsigned long flags, int pc)
{
if (!is_graph())
if (is_graph())
trace_graph_function(tr, ip, parent_ip, flags, pc);
else
trace_function(tr, ip, parent_ip, flags, pc);
else {
trace_graph_function(tr, parent_ip, flags, pc);
trace_graph_function(tr, ip, flags, pc);
}
}

#else
Expand Down
Loading

0 comments on commit 750ed15

Please sign in to comment.