Skip to content

Commit

Permalink
tracing/ftrace: handle more than one stat file per tracer
Browse files Browse the repository at this point in the history
Impact: new API for tracers

Make the stat tracing API reentrant. And also provide the new directory
/debugfs/tracing/trace_stat which will contain all the stat files for the
current active tracer.

Now a tracer will, if desired, want to provide a zero terminated array of
tracer_stat structures.
Each one contains the callbacks necessary for one stat file.
It have to provide at least a name for its stat file, an iterator with
stat_start/start_next callback and an output callback for one stat entry.

Also adapt the branch tracer to this new API.
We create two files "all" and "annotated" inside the /debugfs/tracing/trace_stat
directory, making the both stats simultaneously available instead of needing
to change an option to switch from one stat file to another.

The output of these stats haven't changed.

Changes in v2:

_ Apply the previous memory leak fix (rebase against tip/master)

Changes in v3:

_ Merge the patch that adapted the branch tracer to this Api in this patch to
  not break the kernel build.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Frederic Weisbecker authored and Ingo Molnar committed Jan 11, 2009
1 parent 67d3472 commit 034939b
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 117 deletions.
35 changes: 20 additions & 15 deletions kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,25 @@ struct tracer_flags {
/* Makes more easy to define a tracer opt */
#define TRACER_OPT(s, b) .name = #s, .bit = b

/*
* If you want to provide a stat file (one-shot statistics), fill
* an iterator with stat_start/stat_next and a stat_show callbacks.
* The others callbacks are optional.
*/
struct tracer_stat {
/* The name of your stat file */
const char *name;
/* Iteration over statistic entries */
void *(*stat_start)(void);
void *(*stat_next)(void *prev, int idx);
/* Compare two entries for sorting (optional) for stats */
int (*stat_cmp)(void *p1, void *p2);
/* Print a stat entry */
int (*stat_show)(struct seq_file *s, void *p);
/* Print the headers of your stat entries */
int (*stat_headers)(struct seq_file *s);
};

/*
* A specific tracer, represented by methods that operate on a trace array:
*/
Expand Down Expand Up @@ -361,21 +380,7 @@ struct tracer {
struct tracer *next;
int print_max;
struct tracer_flags *flags;

/*
* If you change one of the following on tracing runtime, recall
* init_tracer_stat()
*/

/* Iteration over statistic entries */
void *(*stat_start)(void);
void *(*stat_next)(void *prev, int idx);
/* Compare two entries for sorting (optional) for stats */
int (*stat_cmp)(void *p1, void *p2);
/* Print a stat entry */
int (*stat_show)(struct seq_file *s, void *p);
/* Print the headers of your stat entries */
int (*stat_headers)(struct seq_file *s);
struct tracer_stat *stats;
};

struct trace_seq {
Expand Down
69 changes: 28 additions & 41 deletions kernel/trace/trace_branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,19 +306,6 @@ static int annotated_branch_stat_cmp(void *p1, void *p2)
}

#ifdef CONFIG_PROFILE_ALL_BRANCHES
enum {
TRACE_BRANCH_OPT_ALL = 0x1
};

static struct tracer_opt branch_opts[] = {
{ TRACER_OPT(stat_all_branch, TRACE_BRANCH_OPT_ALL) },
{ }
};

static struct tracer_flags branch_flags = {
.val = 0,
.opts = branch_opts
};

extern unsigned long __start_branch_profile[];
extern unsigned long __stop_branch_profile[];
Expand Down Expand Up @@ -352,28 +339,36 @@ all_branch_stat_next(void *v, int idx)
return p;
}

static int branch_set_flag(u32 old_flags, u32 bit, int set)
{
if (bit == TRACE_BRANCH_OPT_ALL) {
if (set) {
branch_trace.stat_headers = all_branch_stat_headers;
branch_trace.stat_start = all_branch_stat_start;
branch_trace.stat_next = all_branch_stat_next;
branch_trace.stat_cmp = NULL;
} else {
branch_trace.stat_headers =
annotated_branch_stat_headers;
branch_trace.stat_start = annotated_branch_stat_start;
branch_trace.stat_next = annotated_branch_stat_next;
branch_trace.stat_cmp = annotated_branch_stat_cmp;
}
init_tracer_stat(&branch_trace);
}
return 0;
}
static struct tracer_stat branch_stats[] = {
{.name = "annotated",
.stat_start = annotated_branch_stat_start,
.stat_next = annotated_branch_stat_next,
.stat_cmp = annotated_branch_stat_cmp,
.stat_headers = annotated_branch_stat_headers,
.stat_show = branch_stat_show},

{.name = "all",
.stat_start = all_branch_stat_start,
.stat_next = all_branch_stat_next,
.stat_headers = all_branch_stat_headers,
.stat_show = branch_stat_show},

{ }
};
#else
static struct tracer_stat branch_stats[] = {
{.name = "annotated",
.stat_start = annotated_branch_stat_start,
.stat_next = annotated_branch_stat_next,
.stat_cmp = annotated_branch_stat_cmp,
.stat_headers = annotated_branch_stat_headers,
.stat_show = branch_stat_show},

{ }
};
#endif /* CONFIG_PROFILE_ALL_BRANCHES */


static struct tracer branch_trace __read_mostly =
{
.name = "branch",
Expand All @@ -383,16 +378,8 @@ static struct tracer branch_trace __read_mostly =
#ifdef CONFIG_FTRACE_SELFTEST
.selftest = trace_selftest_startup_branch,
#endif /* CONFIG_FTRACE_SELFTEST */
#endif /* CONFIG_BRANCH_TRACER */
.stat_start = annotated_branch_stat_start,
.stat_next = annotated_branch_stat_next,
.stat_show = branch_stat_show,
.stat_headers = annotated_branch_stat_headers,
.stat_cmp = annotated_branch_stat_cmp,
#ifdef CONFIG_PROFILE_ALL_BRANCHES
.flags = &branch_flags,
.set_flag = branch_set_flag,
#endif
.stats = branch_stats
};

__init static int init_branch_trace(void)
Expand Down
Loading

0 comments on commit 034939b

Please sign in to comment.