forked from Minki/linux
Merge branches 'tracing/ftrace' and 'tracing/function-graph-tracer' into tracing/core
This commit is contained in:
commit
5ce1b1ed27
@ -1,7 +1,7 @@
|
||||
/*
|
||||
*
|
||||
* Function graph tracer.
|
||||
* Copyright (c) 2008 Frederic Weisbecker <fweisbec@gmail.com>
|
||||
* Copyright (c) 2008-2009 Frederic Weisbecker <fweisbec@gmail.com>
|
||||
* Mostly borrowed from function tracer which
|
||||
* is Copyright (c) Steven Rostedt <srostedt@redhat.com>
|
||||
*
|
||||
@ -21,9 +21,11 @@
|
||||
#define TRACE_GRAPH_PRINT_CPU 0x2
|
||||
#define TRACE_GRAPH_PRINT_OVERHEAD 0x4
|
||||
#define TRACE_GRAPH_PRINT_PROC 0x8
|
||||
#define TRACE_GRAPH_PRINT_DURATION 0x10
|
||||
#define TRACE_GRAPH_PRINT_ABS_TIME 0X20
|
||||
|
||||
static struct tracer_opt trace_opts[] = {
|
||||
/* Display overruns ? */
|
||||
/* Display overruns? (for self-debug purpose) */
|
||||
{ TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
|
||||
/* Display CPU ? */
|
||||
{ TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) },
|
||||
@ -31,17 +33,22 @@ static struct tracer_opt trace_opts[] = {
|
||||
{ TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) },
|
||||
/* Display proc name/pid */
|
||||
{ TRACER_OPT(funcgraph-proc, TRACE_GRAPH_PRINT_PROC) },
|
||||
/* Display duration of execution */
|
||||
{ TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
|
||||
/* Display absolute time of an entry */
|
||||
{ TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
|
||||
{ } /* Empty entry */
|
||||
};
|
||||
|
||||
static struct tracer_flags tracer_flags = {
|
||||
/* Don't display overruns and proc by default */
|
||||
.val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD,
|
||||
.val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
|
||||
TRACE_GRAPH_PRINT_DURATION,
|
||||
.opts = trace_opts
|
||||
};
|
||||
|
||||
/* pid on the last trace processed */
|
||||
static pid_t last_pid[NR_CPUS] = { [0 ... NR_CPUS-1] = -1 };
|
||||
|
||||
|
||||
static int graph_trace_init(struct trace_array *tr)
|
||||
{
|
||||
@ -154,17 +161,25 @@ print_graph_proc(struct trace_seq *s, pid_t pid)
|
||||
|
||||
/* If the pid changed since the last trace, output this event */
|
||||
static enum print_line_t
|
||||
verif_pid(struct trace_seq *s, pid_t pid, int cpu)
|
||||
verif_pid(struct trace_seq *s, pid_t pid, int cpu, pid_t *last_pids_cpu)
|
||||
{
|
||||
pid_t prev_pid;
|
||||
pid_t *last_pid;
|
||||
int ret;
|
||||
|
||||
if (last_pid[cpu] != -1 && last_pid[cpu] == pid)
|
||||
if (!last_pids_cpu)
|
||||
return TRACE_TYPE_HANDLED;
|
||||
|
||||
prev_pid = last_pid[cpu];
|
||||
last_pid[cpu] = pid;
|
||||
last_pid = per_cpu_ptr(last_pids_cpu, cpu);
|
||||
|
||||
if (*last_pid == pid)
|
||||
return TRACE_TYPE_HANDLED;
|
||||
|
||||
prev_pid = *last_pid;
|
||||
*last_pid = pid;
|
||||
|
||||
if (prev_pid == -1)
|
||||
return TRACE_TYPE_HANDLED;
|
||||
/*
|
||||
* Context-switch trace line:
|
||||
|
||||
@ -232,9 +247,34 @@ trace_branch_is_leaf(struct trace_iterator *iter,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Signal a overhead of time execution to the output */
|
||||
static int
|
||||
print_graph_overhead(unsigned long long duration, struct trace_seq *s)
|
||||
{
|
||||
/* If duration disappear, we don't need anything */
|
||||
if (!(tracer_flags.val & TRACE_GRAPH_PRINT_DURATION))
|
||||
return 1;
|
||||
|
||||
/* Non nested entry or return */
|
||||
if (duration == -1)
|
||||
return trace_seq_printf(s, " ");
|
||||
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
/* Duration exceeded 100 msecs */
|
||||
if (duration > 100000ULL)
|
||||
return trace_seq_printf(s, "! ");
|
||||
|
||||
/* Duration exceeded 10 msecs */
|
||||
if (duration > 10000ULL)
|
||||
return trace_seq_printf(s, "+ ");
|
||||
}
|
||||
|
||||
return trace_seq_printf(s, " ");
|
||||
}
|
||||
|
||||
static enum print_line_t
|
||||
print_graph_irq(struct trace_seq *s, unsigned long addr,
|
||||
enum trace_type type, int cpu, pid_t pid)
|
||||
enum trace_type type, int cpu, pid_t pid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -242,35 +282,40 @@ print_graph_irq(struct trace_seq *s, unsigned long addr,
|
||||
addr >= (unsigned long)__irqentry_text_end)
|
||||
return TRACE_TYPE_UNHANDLED;
|
||||
|
||||
if (type == TRACE_GRAPH_ENT) {
|
||||
ret = trace_seq_printf(s, "==========> | ");
|
||||
} else {
|
||||
/* Cpu */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
|
||||
ret = print_graph_cpu(s, cpu);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
/* Proc */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) {
|
||||
ret = print_graph_proc(s, pid);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
ret = trace_seq_printf(s, " | ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* No overhead */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
ret = trace_seq_printf(s, " ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
ret = trace_seq_printf(s, "<========== |\n");
|
||||
/* Cpu */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
|
||||
ret = print_graph_cpu(s, cpu);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
/* Proc */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) {
|
||||
ret = print_graph_proc(s, pid);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
ret = trace_seq_printf(s, " | ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* No overhead */
|
||||
ret = print_graph_overhead(-1, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
if (type == TRACE_GRAPH_ENT)
|
||||
ret = trace_seq_printf(s, "==========>");
|
||||
else
|
||||
ret = trace_seq_printf(s, "<==========");
|
||||
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Don't close the duration column if haven't one */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)
|
||||
trace_seq_printf(s, " |");
|
||||
ret = trace_seq_printf(s, "\n");
|
||||
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
return TRACE_TYPE_HANDLED;
|
||||
@ -289,7 +334,7 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s)
|
||||
sprintf(msecs_str, "%lu", (unsigned long) duration);
|
||||
|
||||
/* Print msecs */
|
||||
ret = trace_seq_printf(s, msecs_str);
|
||||
ret = trace_seq_printf(s, "%s", msecs_str);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
@ -322,19 +367,15 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s)
|
||||
|
||||
}
|
||||
|
||||
/* Signal a overhead of time execution to the output */
|
||||
static int
|
||||
print_graph_overhead(unsigned long long duration, struct trace_seq *s)
|
||||
static int print_graph_abs_time(u64 t, struct trace_seq *s)
|
||||
{
|
||||
/* Duration exceeded 100 msecs */
|
||||
if (duration > 100000ULL)
|
||||
return trace_seq_printf(s, "! ");
|
||||
unsigned long usecs_rem;
|
||||
|
||||
/* Duration exceeded 10 msecs */
|
||||
if (duration > 10000ULL)
|
||||
return trace_seq_printf(s, "+ ");
|
||||
usecs_rem = do_div(t, 1000000000);
|
||||
usecs_rem /= 1000;
|
||||
|
||||
return trace_seq_printf(s, " ");
|
||||
return trace_seq_printf(s, "%5lu.%06lu | ",
|
||||
(unsigned long)t, usecs_rem);
|
||||
}
|
||||
|
||||
/* Case of a leaf function on its call entry */
|
||||
@ -357,16 +398,16 @@ print_graph_entry_leaf(struct trace_iterator *iter,
|
||||
duration = graph_ret->rettime - graph_ret->calltime;
|
||||
|
||||
/* Overhead */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
ret = print_graph_overhead(duration, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
ret = print_graph_overhead(duration, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Duration */
|
||||
ret = print_graph_duration(duration, s);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
|
||||
ret = print_graph_duration(duration, s);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* Function */
|
||||
for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
|
||||
@ -395,25 +436,17 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
|
||||
struct ftrace_graph_ent *call = &entry->graph_ent;
|
||||
|
||||
/* No overhead */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
ret = trace_seq_printf(s, " ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
ret = print_graph_overhead(-1, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Interrupt */
|
||||
ret = print_graph_irq(s, call->func, TRACE_GRAPH_ENT, cpu, pid);
|
||||
if (ret == TRACE_TYPE_UNHANDLED) {
|
||||
/* No time */
|
||||
/* No time */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
|
||||
ret = trace_seq_printf(s, " | ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
} else {
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
|
||||
/* Function */
|
||||
for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
|
||||
ret = trace_seq_printf(s, " ");
|
||||
@ -434,15 +467,30 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
|
||||
|
||||
static enum print_line_t
|
||||
print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
|
||||
struct trace_iterator *iter, int cpu)
|
||||
struct trace_iterator *iter)
|
||||
{
|
||||
int ret;
|
||||
int cpu = iter->cpu;
|
||||
pid_t *last_entry = iter->private;
|
||||
struct trace_entry *ent = iter->ent;
|
||||
struct ftrace_graph_ent *call = &field->graph_ent;
|
||||
|
||||
/* Pid */
|
||||
if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE)
|
||||
if (verif_pid(s, ent->pid, cpu, last_entry) == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Interrupt */
|
||||
ret = print_graph_irq(s, call->func, TRACE_GRAPH_ENT, cpu, ent->pid);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Absolute time */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) {
|
||||
ret = print_graph_abs_time(iter->ts, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* Cpu */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
|
||||
ret = print_graph_cpu(s, cpu);
|
||||
@ -470,16 +518,25 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
|
||||
|
||||
static enum print_line_t
|
||||
print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
|
||||
struct trace_entry *ent, int cpu)
|
||||
struct trace_entry *ent, struct trace_iterator *iter)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int cpu = iter->cpu;
|
||||
pid_t *last_pid = iter->private;
|
||||
unsigned long long duration = trace->rettime - trace->calltime;
|
||||
|
||||
/* Pid */
|
||||
if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE)
|
||||
if (verif_pid(s, ent->pid, cpu, last_pid) == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Absolute time */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) {
|
||||
ret = print_graph_abs_time(iter->ts, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* Cpu */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
|
||||
ret = print_graph_cpu(s, cpu);
|
||||
@ -499,16 +556,16 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
|
||||
}
|
||||
|
||||
/* Overhead */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
ret = print_graph_overhead(duration, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
ret = print_graph_overhead(duration, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Duration */
|
||||
ret = print_graph_duration(duration, s);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
|
||||
ret = print_graph_duration(duration, s);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* Closing brace */
|
||||
for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) {
|
||||
@ -542,14 +599,23 @@ print_graph_comment(struct print_entry *trace, struct trace_seq *s,
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int cpu = iter->cpu;
|
||||
pid_t *last_pid = iter->private;
|
||||
|
||||
/* Absolute time */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) {
|
||||
ret = print_graph_abs_time(iter->ts, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* Pid */
|
||||
if (verif_pid(s, ent->pid, iter->cpu) == TRACE_TYPE_PARTIAL_LINE)
|
||||
if (verif_pid(s, ent->pid, cpu, last_pid) == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Cpu */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
|
||||
ret = print_graph_cpu(s, iter->cpu);
|
||||
ret = print_graph_cpu(s, cpu);
|
||||
if (ret == TRACE_TYPE_PARTIAL_LINE)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
@ -566,17 +632,17 @@ print_graph_comment(struct print_entry *trace, struct trace_seq *s,
|
||||
}
|
||||
|
||||
/* No overhead */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
ret = trace_seq_printf(s, " ");
|
||||
ret = print_graph_overhead(-1, s);
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* No time */
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
|
||||
ret = trace_seq_printf(s, " | ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
}
|
||||
|
||||
/* No time */
|
||||
ret = trace_seq_printf(s, " | ");
|
||||
if (!ret)
|
||||
return TRACE_TYPE_PARTIAL_LINE;
|
||||
|
||||
/* Indentation */
|
||||
if (trace->depth > 0)
|
||||
for (i = 0; i < (trace->depth + 1) * TRACE_GRAPH_INDENT; i++) {
|
||||
@ -614,13 +680,12 @@ print_graph_function(struct trace_iterator *iter)
|
||||
case TRACE_GRAPH_ENT: {
|
||||
struct ftrace_graph_ent_entry *field;
|
||||
trace_assign_type(field, entry);
|
||||
return print_graph_entry(field, s, iter,
|
||||
iter->cpu);
|
||||
return print_graph_entry(field, s, iter);
|
||||
}
|
||||
case TRACE_GRAPH_RET: {
|
||||
struct ftrace_graph_ret_entry *field;
|
||||
trace_assign_type(field, entry);
|
||||
return print_graph_return(&field->ret, s, entry, iter->cpu);
|
||||
return print_graph_return(&field->ret, s, entry, iter);
|
||||
}
|
||||
case TRACE_PRINT: {
|
||||
struct print_entry *field;
|
||||
@ -636,28 +701,55 @@ static void print_graph_headers(struct seq_file *s)
|
||||
{
|
||||
/* 1st line */
|
||||
seq_printf(s, "# ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME)
|
||||
seq_printf(s, " TIME ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU)
|
||||
seq_printf(s, "CPU ");
|
||||
seq_printf(s, "CPU");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC)
|
||||
seq_printf(s, "TASK/PID ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD)
|
||||
seq_printf(s, "OVERHEAD/");
|
||||
seq_printf(s, "DURATION FUNCTION CALLS\n");
|
||||
seq_printf(s, " TASK/PID ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)
|
||||
seq_printf(s, " DURATION ");
|
||||
seq_printf(s, " FUNCTION CALLS\n");
|
||||
|
||||
/* 2nd line */
|
||||
seq_printf(s, "# ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME)
|
||||
seq_printf(s, " | ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU)
|
||||
seq_printf(s, "| ");
|
||||
seq_printf(s, "| ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC)
|
||||
seq_printf(s, "| | ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
|
||||
seq_printf(s, "| ");
|
||||
seq_printf(s, "| | | | |\n");
|
||||
} else
|
||||
seq_printf(s, " | | | | |\n");
|
||||
seq_printf(s, " | | ");
|
||||
if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)
|
||||
seq_printf(s, " | | ");
|
||||
seq_printf(s, " | | | |\n");
|
||||
}
|
||||
|
||||
static void graph_trace_open(struct trace_iterator *iter)
|
||||
{
|
||||
/* pid on the last trace processed */
|
||||
pid_t *last_pid = alloc_percpu(pid_t);
|
||||
int cpu;
|
||||
|
||||
if (!last_pid)
|
||||
pr_warning("function graph tracer: not enough memory\n");
|
||||
else
|
||||
for_each_possible_cpu(cpu) {
|
||||
pid_t *pid = per_cpu_ptr(last_pid, cpu);
|
||||
*pid = -1;
|
||||
}
|
||||
|
||||
iter->private = last_pid;
|
||||
}
|
||||
|
||||
static void graph_trace_close(struct trace_iterator *iter)
|
||||
{
|
||||
percpu_free(iter->private);
|
||||
}
|
||||
|
||||
static struct tracer graph_trace __read_mostly = {
|
||||
.name = "function_graph",
|
||||
.open = graph_trace_open,
|
||||
.close = graph_trace_close,
|
||||
.init = graph_trace_init,
|
||||
.reset = graph_trace_reset,
|
||||
.print_line = print_graph_function,
|
||||
|
Loading…
Reference in New Issue
Block a user