Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 158462
b: refs/heads/master
c: 35dce1a
h: refs/heads/master
v: v3
  • Loading branch information
Ingo Molnar committed Aug 26, 2009
1 parent 240c706 commit 49d3ebe
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 56 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: 1c569f0264ea629c10bbab471dd0626ce4d3f19f
refs/heads/master: 35dce1a99d010f3d738af4ce1b9b77302fdfe69c
42 changes: 42 additions & 0 deletions trunk/Documentation/trace/function-graph-fold.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
" Enable folding for ftrace function_graph traces.
"
" To use, :source this file while viewing a function_graph trace, or use vim's
" -S option to load from the command-line together with a trace. You can then
" use the usual vim fold commands, such as "za", to open and close nested
" functions. While closed, a fold will show the total time taken for a call,
" as would normally appear on the line with the closing brace. Folded
" functions will not include finish_task_switch(), so folding should remain
" relatively sane even through a context switch.
"
" Note that this will almost certainly only work well with a
" single-CPU trace (e.g. trace-cmd report --cpu 1).

function! FunctionGraphFoldExpr(lnum)
let line = getline(a:lnum)
if line[-1:] == '{'
if line =~ 'finish_task_switch() {$'
return '>1'
endif
return 'a1'
elseif line[-1:] == '}'
return 's1'
else
return '='
endif
endfunction

function! FunctionGraphFoldText()
let s = split(getline(v:foldstart), '|', 1)
if getline(v:foldend+1) =~ 'finish_task_switch() {$'
let s[2] = ' task switch '
else
let e = split(getline(v:foldend), '|', 1)
let s[2] = e[2]
endif
return join(s, '|')
endfunction

setlocal foldexpr=FunctionGraphFoldExpr(v:lnum)
setlocal foldtext=FunctionGraphFoldText()
setlocal foldcolumn=12
setlocal foldmethod=expr
10 changes: 9 additions & 1 deletion trunk/include/linux/ftrace_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,17 @@ extern int filter_current_check_discard(struct ftrace_event_call *call,
void *rec,
struct ring_buffer_event *event);

enum {
FILTER_OTHER = 0,
FILTER_STATIC_STRING,
FILTER_DYN_STRING,
FILTER_PTR_STRING,
};

extern int trace_define_field(struct ftrace_event_call *call,
const char *type, const char *name,
int offset, int size, int is_signed);
int offset, int size, int is_signed,
int filter_type);
extern int trace_define_common_fields(struct ftrace_event_call *call);

#define is_signed_type(type) (((type)(-1)) < 0)
Expand Down
12 changes: 10 additions & 2 deletions trunk/include/linux/tracepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,15 @@ static inline void tracepoint_synchronize_unregister(void)

#define PARAMS(args...) args

#endif /* _LINUX_TRACEPOINT_H */

/*
* Note: we keep the TRACE_EVENT outside the include file ifdef protection.
* This is due to the way trace events work. If a file includes two
* trace event headers under one "CREATE_TRACE_POINTS" the first include
* will override the TRACE_EVENT and break the second include.
*/

#ifndef TRACE_EVENT
/*
* For use with the TRACE_EVENT macro:
Expand Down Expand Up @@ -276,6 +285,5 @@ static inline void tracepoint_synchronize_unregister(void)
#define TRACE_EVENT_FN(name, proto, args, struct, \
assign, print, reg, unreg) \
DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
#endif

#endif
#endif /* ifdef TRACE_EVENT (see note above) */
1 change: 1 addition & 0 deletions trunk/include/trace/define_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include <trace/ftrace.h>
#endif

#undef TRACE_EVENT
#undef TRACE_HEADER_MULTI_READ

/* Only undef what we defined in this file */
Expand Down
12 changes: 8 additions & 4 deletions trunk/include/trace/events/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,20 @@ TRACE_EVENT(sched_wakeup,
__field( pid_t, pid )
__field( int, prio )
__field( int, success )
__field( int, cpu )
),

TP_fast_assign(
memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
__entry->pid = p->pid;
__entry->prio = p->prio;
__entry->success = success;
__entry->cpu = task_cpu(p);
),

TP_printk("task %s:%d [%d] success=%d",
TP_printk("task %s:%d [%d] success=%d [%03d]",
__entry->comm, __entry->pid, __entry->prio,
__entry->success)
__entry->success, __entry->cpu)
);

/*
Expand All @@ -125,18 +127,20 @@ TRACE_EVENT(sched_wakeup_new,
__field( pid_t, pid )
__field( int, prio )
__field( int, success )
__field( int, cpu )
),

TP_fast_assign(
memcpy(__entry->comm, p->comm, TASK_COMM_LEN);
__entry->pid = p->pid;
__entry->prio = p->prio;
__entry->success = success;
__entry->cpu = task_cpu(p);
),

TP_printk("task %s:%d [%d] success=%d",
TP_printk("task %s:%d [%d] success=%d [%03d]",
__entry->comm, __entry->pid, __entry->prio,
__entry->success)
__entry->success, __entry->cpu)
);

/*
Expand Down
31 changes: 24 additions & 7 deletions trunk/include/trace/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#undef __field
#define __field(type, item) type item;

#undef __field_ext
#define __field_ext(type, item, filter_type) type item;

#undef __array
#define __array(type, item, len) type item[len];

Expand Down Expand Up @@ -71,7 +74,10 @@
*/

#undef __field
#define __field(type, item);
#define __field(type, item)

#undef __field_ext
#define __field_ext(type, item, filter_type)

#undef __array
#define __array(type, item, len)
Expand Down Expand Up @@ -119,6 +125,9 @@
if (!ret) \
return 0;

#undef __field_ext
#define __field_ext(type, item, filter_type) __field(type, item)

#undef __array
#define __array(type, item, len) \
ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
Expand Down Expand Up @@ -274,28 +283,33 @@ ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \

#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

#undef __field
#define __field(type, item) \
#undef __field_ext
#define __field_ext(type, item, filter_type) \
ret = trace_define_field(event_call, #type, #item, \
offsetof(typeof(field), item), \
sizeof(field.item), is_signed_type(type)); \
sizeof(field.item), \
is_signed_type(type), filter_type); \
if (ret) \
return ret;

#undef __field
#define __field(type, item) __field_ext(type, item, FILTER_OTHER)

#undef __array
#define __array(type, item, len) \
BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
ret = trace_define_field(event_call, #type "[" #len "]", #item, \
offsetof(typeof(field), item), \
sizeof(field.item), 0); \
sizeof(field.item), 0, FILTER_OTHER); \
if (ret) \
return ret;

#undef __dynamic_array
#define __dynamic_array(type, item, len) \
ret = trace_define_field(event_call, "__data_loc " #type "[]", #item, \
offsetof(typeof(field), __data_loc_##item), \
sizeof(field.__data_loc_##item), 0);
offsetof(typeof(field), __data_loc_##item), \
sizeof(field.__data_loc_##item), 0, \
FILTER_OTHER);

#undef __string
#define __string(item, src) __dynamic_array(char, item, -1)
Expand Down Expand Up @@ -329,6 +343,9 @@ ftrace_define_fields_##call(struct ftrace_event_call *event_call) \
#undef __field
#define __field(type, item)

#undef __field_ext
#define __field_ext(type, item, filter_type)

#undef __array
#define __array(type, item, len)

Expand Down
92 changes: 75 additions & 17 deletions trunk/kernel/trace/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,21 @@ static const char *trace_options[] = {
"printk-msg-only",
"context-info",
"latency-format",
"global-clock",
"sleep-time",
"graph-time",
NULL
};

static struct {
u64 (*func)(void);
const char *name;
} trace_clocks[] = {
{ trace_clock_local, "local" },
{ trace_clock_global, "global" },
};

int trace_clock_id;

/*
* ftrace_max_lock is used to protect the swapping of buffers
* when taking a max snapshot. The buffers themselves are
Expand Down Expand Up @@ -2159,22 +2168,6 @@ static void set_tracer_flags(unsigned int mask, int enabled)
trace_flags |= mask;
else
trace_flags &= ~mask;

if (mask == TRACE_ITER_GLOBAL_CLK) {
u64 (*func)(void);

if (enabled)
func = trace_clock_global;
else
func = trace_clock_local;

mutex_lock(&trace_types_lock);
ring_buffer_set_clock(global_trace.buffer, func);

if (max_tr.buffer)
ring_buffer_set_clock(max_tr.buffer, func);
mutex_unlock(&trace_types_lock);
}
}

static ssize_t
Expand Down Expand Up @@ -3142,6 +3135,62 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,
return cnt;
}

static ssize_t tracing_clock_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
char buf[64];
int bufiter = 0;
int i;

for (i = 0; i < ARRAY_SIZE(trace_clocks); i++)
bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter,
"%s%s%s%s", i ? " " : "",
i == trace_clock_id ? "[" : "", trace_clocks[i].name,
i == trace_clock_id ? "]" : "");
bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, "\n");

return simple_read_from_buffer(ubuf, cnt, ppos, buf, bufiter);
}

static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *fpos)
{
char buf[64];
const char *clockstr;
int i;

if (cnt >= sizeof(buf))
return -EINVAL;

if (copy_from_user(&buf, ubuf, cnt))
return -EFAULT;

buf[cnt] = 0;

clockstr = strstrip(buf);

for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) {
if (strcmp(trace_clocks[i].name, clockstr) == 0)
break;
}
if (i == ARRAY_SIZE(trace_clocks))
return -EINVAL;

trace_clock_id = i;

mutex_lock(&trace_types_lock);

ring_buffer_set_clock(global_trace.buffer, trace_clocks[i].func);
if (max_tr.buffer)
ring_buffer_set_clock(max_tr.buffer, trace_clocks[i].func);

mutex_unlock(&trace_types_lock);

*fpos += cnt;

return cnt;
}

static const struct file_operations tracing_max_lat_fops = {
.open = tracing_open_generic,
.read = tracing_max_lat_read,
Expand Down Expand Up @@ -3179,6 +3228,12 @@ static const struct file_operations tracing_mark_fops = {
.write = tracing_mark_write,
};

static const struct file_operations trace_clock_fops = {
.open = tracing_open_generic,
.read = tracing_clock_read,
.write = tracing_clock_write,
};

struct ftrace_buffer_info {
struct trace_array *tr;
void *spare;
Expand Down Expand Up @@ -3918,6 +3973,9 @@ static __init int tracer_init_debugfs(void)
trace_create_file("saved_cmdlines", 0444, d_tracer,
NULL, &tracing_saved_cmdlines_fops);

trace_create_file("trace_clock", 0644, d_tracer, NULL,
&trace_clock_fops);

#ifdef CONFIG_DYNAMIC_FTRACE
trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
&ftrace_update_tot_cnt, &tracing_dyn_info_fops);
Expand Down
9 changes: 6 additions & 3 deletions trunk/kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,8 @@ trace_vprintk(unsigned long ip, const char *fmt, va_list args);

extern unsigned long trace_flags;

extern int trace_clock_id;

/* Standard output formatting function used for function return traces */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
extern enum print_line_t print_graph_function(struct trace_iterator *iter);
Expand Down Expand Up @@ -656,9 +658,8 @@ enum trace_iterator_flags {
TRACE_ITER_PRINTK_MSGONLY = 0x10000,
TRACE_ITER_CONTEXT_INFO = 0x20000, /* Print pid/cpu/time */
TRACE_ITER_LATENCY_FMT = 0x40000,
TRACE_ITER_GLOBAL_CLK = 0x80000,
TRACE_ITER_SLEEP_TIME = 0x100000,
TRACE_ITER_GRAPH_TIME = 0x200000,
TRACE_ITER_SLEEP_TIME = 0x80000,
TRACE_ITER_GRAPH_TIME = 0x100000,
};

/*
Expand Down Expand Up @@ -755,6 +756,7 @@ struct ftrace_event_field {
struct list_head link;
char *name;
char *type;
int filter_type;
int offset;
int size;
int is_signed;
Expand Down Expand Up @@ -800,6 +802,7 @@ extern int apply_subsystem_event_filter(struct event_subsystem *system,
char *filter_string);
extern void print_subsystem_event_filter(struct event_subsystem *system,
struct trace_seq *s);
extern int filter_assign_type(const char *type);

static inline int
filter_check_discard(struct ftrace_event_call *call, void *rec,
Expand Down
Loading

0 comments on commit 49d3ebe

Please sign in to comment.