Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 121205
b: refs/heads/master
c: 287b6e6
h: refs/heads/master
i:
  121203: a7f2b2b
v: v3
  • Loading branch information
Frederic Weisbecker authored and Ingo Molnar committed Nov 26, 2008
1 parent 3aa1745 commit 7167a0d
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 177 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: fb52607afcd0629776f1dc9e657647ceae81dd50
refs/heads/master: 287b6e68ca7209caec40b2f44f837c580a413bae
32 changes: 21 additions & 11 deletions trunk/arch/x86/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ void ftrace_nmi_exit(void)

/* Add a function return address to the trace stack on thread info.*/
static int push_return_trace(unsigned long ret, unsigned long long time,
unsigned long func)
unsigned long func, int *depth)
{
int index;

Expand All @@ -365,21 +365,22 @@ static int push_return_trace(unsigned long ret, unsigned long long time,
current->ret_stack[index].ret = ret;
current->ret_stack[index].func = func;
current->ret_stack[index].calltime = time;
*depth = index;

return 0;
}

/* Retrieve a function return address to the trace stack on thread info.*/
static void pop_return_trace(unsigned long *ret, unsigned long long *time,
unsigned long *func, unsigned long *overrun)
static void pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret)
{
int index;

index = current->curr_ret_stack;
*ret = current->ret_stack[index].ret;
*func = current->ret_stack[index].func;
*time = current->ret_stack[index].calltime;
*overrun = atomic_read(&current->trace_overrun);
trace->func = current->ret_stack[index].func;
trace->calltime = current->ret_stack[index].calltime;
trace->overrun = atomic_read(&current->trace_overrun);
trace->depth = index;
current->curr_ret_stack--;
}

Expand All @@ -390,12 +391,13 @@ static void pop_return_trace(unsigned long *ret, unsigned long long *time,
unsigned long ftrace_return_to_handler(void)
{
struct ftrace_graph_ret trace;
pop_return_trace(&trace.ret, &trace.calltime, &trace.func,
&trace.overrun);
unsigned long ret;

pop_return_trace(&trace, &ret);
trace.rettime = cpu_clock(raw_smp_processor_id());
ftrace_graph_function(&trace);
ftrace_graph_return(&trace);

return trace.ret;
return ret;
}

/*
Expand All @@ -407,6 +409,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
unsigned long old;
unsigned long long calltime;
int faulted;
struct ftrace_graph_ent trace;
unsigned long return_hooker = (unsigned long)
&return_to_handler;

Expand Down Expand Up @@ -452,8 +455,15 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)

calltime = cpu_clock(raw_smp_processor_id());

if (push_return_trace(old, calltime, self_addr) == -EBUSY)
if (push_return_trace(old, calltime,
self_addr, &trace.depth) == -EBUSY) {
*parent = old;
return;
}

trace.func = self_addr;
ftrace_graph_entry(&trace);

}

#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
25 changes: 19 additions & 6 deletions trunk/include/linux/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,27 +312,40 @@ ftrace_init_module(struct module *mod,
#endif


/*
* Structure that defines an entry function trace.
*/
struct ftrace_graph_ent {
unsigned long func; /* Current function */
int depth;
};

/*
* Structure that defines a return function trace.
*/
struct ftrace_graph_ret {
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;
int depth;
};

#ifdef CONFIG_FUNCTION_GRAPH_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_graph_t)(struct ftrace_graph_ret *);
/* Type of the callback handlers for tracing function graph*/
typedef void (*trace_func_graph_ret_t)(struct ftrace_graph_ret *); /* return */
typedef void (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */

extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc);

/* The current handlers in use */
extern trace_func_graph_ret_t ftrace_graph_return;
extern trace_func_graph_ent_t ftrace_graph_entry;

extern int register_ftrace_graph(trace_function_graph_t func);
/* The current handler in use */
extern trace_function_graph_t ftrace_graph_function;
extern void unregister_ftrace_graph(void);

extern void ftrace_graph_init_task(struct task_struct *t);
Expand Down
30 changes: 16 additions & 14 deletions trunk/kernel/trace/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1498,12 +1498,13 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,

#ifdef CONFIG_FUNCTION_GRAPH_TRACER

static atomic_t ftrace_retfunc_active;

/* The callback that hooks the return of a function */
trace_function_graph_t ftrace_graph_function =
(trace_function_graph_t)ftrace_stub;
static atomic_t ftrace_graph_active;

/* The callbacks that hook a function */
trace_func_graph_ret_t ftrace_graph_return =
(trace_func_graph_ret_t)ftrace_stub;
trace_func_graph_ent_t ftrace_graph_entry =
(trace_func_graph_ent_t)ftrace_stub;

/* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */
static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
Expand Down Expand Up @@ -1569,7 +1570,8 @@ static int start_graph_tracing(void)
return ret;
}

int register_ftrace_graph(trace_function_graph_t func)
int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc)
{
int ret = 0;

Expand All @@ -1583,14 +1585,15 @@ int register_ftrace_graph(trace_function_graph_t func)
ret = -EBUSY;
goto out;
}
atomic_inc(&ftrace_retfunc_active);
atomic_inc(&ftrace_graph_active);
ret = start_graph_tracing();
if (ret) {
atomic_dec(&ftrace_retfunc_active);
atomic_dec(&ftrace_graph_active);
goto out;
}
ftrace_tracing_type = FTRACE_TYPE_RETURN;
ftrace_graph_function = func;
ftrace_graph_return = retfunc;
ftrace_graph_entry = entryfunc;
ftrace_startup();

out:
Expand All @@ -1602,8 +1605,9 @@ void unregister_ftrace_graph(void)
{
mutex_lock(&ftrace_sysctl_lock);

atomic_dec(&ftrace_retfunc_active);
ftrace_graph_function = (trace_function_graph_t)ftrace_stub;
atomic_dec(&ftrace_graph_active);
ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub;
ftrace_graph_entry = (trace_func_graph_ent_t)ftrace_stub;
ftrace_shutdown();
/* Restore normal tracing type */
ftrace_tracing_type = FTRACE_TYPE_ENTER;
Expand All @@ -1614,7 +1618,7 @@ void unregister_ftrace_graph(void)
/* Allocate a return stack for newly created task */
void ftrace_graph_init_task(struct task_struct *t)
{
if (atomic_read(&ftrace_retfunc_active)) {
if (atomic_read(&ftrace_graph_active)) {
t->ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
* sizeof(struct ftrace_ret_stack),
GFP_KERNEL);
Expand All @@ -1638,5 +1642,3 @@ void ftrace_graph_exit_task(struct task_struct *t)
}
#endif



67 changes: 55 additions & 12 deletions trunk/kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,14 +879,38 @@ trace_function(struct trace_array *tr, struct trace_array_cpu *data,
}

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static void __trace_function_graph(struct trace_array *tr,
static void __trace_graph_entry(struct trace_array *tr,
struct trace_array_cpu *data,
struct ftrace_graph_ent *trace,
unsigned long flags,
int pc)
{
struct ring_buffer_event *event;
struct ftrace_graph_ent_entry *entry;
unsigned long irq_flags;

if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
return;

event = ring_buffer_lock_reserve(global_trace.buffer, sizeof(*entry),
&irq_flags);
if (!event)
return;
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(&entry->ent, flags, pc);
entry->ent.type = TRACE_GRAPH_ENT;
entry->graph_ent = *trace;
ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags);
}

static void __trace_graph_return(struct trace_array *tr,
struct trace_array_cpu *data,
struct ftrace_graph_ret *trace,
unsigned long flags,
int pc)
{
struct ring_buffer_event *event;
struct ftrace_graph_entry *entry;
struct ftrace_graph_ret_entry *entry;
unsigned long irq_flags;

if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled))))
Expand All @@ -898,12 +922,8 @@ static void __trace_function_graph(struct trace_array *tr,
return;
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(&entry->ent, flags, pc);
entry->ent.type = TRACE_FN_RET;
entry->ip = trace->func;
entry->parent_ip = trace->ret;
entry->rettime = trace->rettime;
entry->calltime = trace->calltime;
entry->overrun = trace->overrun;
entry->ent.type = TRACE_GRAPH_RET;
entry->ret = *trace;
ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags);
}
#endif
Expand Down Expand Up @@ -1178,7 +1198,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip)
}

#ifdef CONFIG_FUNCTION_GRAPH_TRACER
void trace_function_graph(struct ftrace_graph_ret *trace)
void trace_graph_entry(struct ftrace_graph_ent *trace)
{
struct trace_array *tr = &global_trace;
struct trace_array_cpu *data;
Expand All @@ -1193,7 +1213,28 @@ void trace_function_graph(struct ftrace_graph_ret *trace)
disabled = atomic_inc_return(&data->disabled);
if (likely(disabled == 1)) {
pc = preempt_count();
__trace_function_graph(tr, data, trace, flags, pc);
__trace_graph_entry(tr, data, trace, flags, pc);
}
atomic_dec(&data->disabled);
raw_local_irq_restore(flags);
}

void trace_graph_return(struct ftrace_graph_ret *trace)
{
struct trace_array *tr = &global_trace;
struct trace_array_cpu *data;
unsigned long flags;
long disabled;
int cpu;
int pc;

raw_local_irq_save(flags);
cpu = raw_smp_processor_id();
data = tr->data[cpu];
disabled = atomic_inc_return(&data->disabled);
if (likely(disabled == 1)) {
pc = preempt_count();
__trace_graph_return(tr, data, trace, flags, pc);
}
atomic_dec(&data->disabled);
raw_local_irq_restore(flags);
Expand Down Expand Up @@ -2000,9 +2041,11 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
trace_seq_print_cont(s, iter);
break;
}
case TRACE_FN_RET: {
case TRACE_GRAPH_RET: {
return print_graph_function(iter);
}
case TRACE_GRAPH_ENT: {
return print_graph_function(iter);
break;
}
case TRACE_BRANCH: {
struct trace_branch *field;
Expand Down
28 changes: 17 additions & 11 deletions trunk/kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ enum trace_type {
TRACE_BRANCH,
TRACE_BOOT_CALL,
TRACE_BOOT_RET,
TRACE_FN_RET,
TRACE_GRAPH_RET,
TRACE_GRAPH_ENT,
TRACE_USER_STACK,
TRACE_BTS,

Expand Down Expand Up @@ -56,14 +57,16 @@ struct ftrace_entry {
unsigned long parent_ip;
};

/* Function call entry */
struct ftrace_graph_ent_entry {
struct trace_entry ent;
struct ftrace_graph_ent graph_ent;
};

/* Function return entry */
struct ftrace_graph_entry {
struct trace_entry ent;
unsigned long ip;
unsigned long parent_ip;
unsigned long long calltime;
unsigned long long rettime;
unsigned long overrun;
struct ftrace_graph_ret_entry {
struct trace_entry ent;
struct ftrace_graph_ret ret;
};
extern struct tracer boot_tracer;

Expand Down Expand Up @@ -264,7 +267,10 @@ extern void __ftrace_bad_type(void);
IF_ASSIGN(var, ent, struct trace_boot_call, TRACE_BOOT_CALL);\
IF_ASSIGN(var, ent, struct trace_boot_ret, TRACE_BOOT_RET);\
IF_ASSIGN(var, ent, struct trace_branch, TRACE_BRANCH); \
IF_ASSIGN(var, ent, struct ftrace_graph_entry, TRACE_FN_RET);\
IF_ASSIGN(var, ent, struct ftrace_graph_ent_entry, \
TRACE_GRAPH_ENT); \
IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \
TRACE_GRAPH_RET); \
IF_ASSIGN(var, ent, struct bts_entry, TRACE_BTS);\
__ftrace_bad_type(); \
} while (0)
Expand Down Expand Up @@ -397,9 +403,9 @@ void trace_function(struct trace_array *tr,
unsigned long ip,
unsigned long parent_ip,
unsigned long flags, int pc);
void
trace_function_graph(struct ftrace_graph_ret *trace);

void trace_graph_return(struct ftrace_graph_ret *trace);
void trace_graph_entry(struct ftrace_graph_ent *trace);
void trace_bts(struct trace_array *tr,
unsigned long from,
unsigned long to);
Expand Down
Loading

0 comments on commit 7167a0d

Please sign in to comment.