Commit 57422797 authored by Ingo Molnar's avatar Ingo Molnar Committed by Thomas Gleixner

ftrace: add wakeup events to sched tracer

Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent e309b41d
...@@ -57,7 +57,7 @@ static struct trace_array max_tr; ...@@ -57,7 +57,7 @@ static struct trace_array max_tr;
static DEFINE_PER_CPU(struct trace_array_cpu, max_data); static DEFINE_PER_CPU(struct trace_array_cpu, max_data);
static int tracer_enabled = 1; static int tracer_enabled = 1;
static unsigned long trace_nr_entries = 16384UL; static unsigned long trace_nr_entries = 65536UL;
static struct tracer *trace_types __read_mostly; static struct tracer *trace_types __read_mostly;
static struct tracer *current_trace __read_mostly; static struct tracer *current_trace __read_mostly;
...@@ -87,6 +87,7 @@ enum trace_type { ...@@ -87,6 +87,7 @@ enum trace_type {
TRACE_FN, TRACE_FN,
TRACE_CTX, TRACE_CTX,
TRACE_WAKE,
TRACE_SPECIAL, TRACE_SPECIAL,
__TRACE_LAST_TYPE __TRACE_LAST_TYPE
...@@ -711,6 +712,30 @@ tracing_sched_switch_trace(struct trace_array *tr, ...@@ -711,6 +712,30 @@ tracing_sched_switch_trace(struct trace_array *tr,
wake_up (&trace_wait); wake_up (&trace_wait);
} }
void
tracing_sched_wakeup_trace(struct trace_array *tr,
struct trace_array_cpu *data,
struct task_struct *wakee, struct task_struct *curr,
unsigned long flags)
{
struct trace_entry *entry;
unsigned long irq_flags;
spin_lock_irqsave(&data->lock, irq_flags);
entry = tracing_get_trace_entry(tr, data);
tracing_generic_entry_update(entry, flags);
entry->type = TRACE_WAKE;
entry->ctx.prev_pid = curr->pid;
entry->ctx.prev_prio = curr->prio;
entry->ctx.prev_state = curr->state;
entry->ctx.next_pid = wakee->pid;
entry->ctx.next_prio = wakee->prio;
spin_unlock_irqrestore(&data->lock, irq_flags);
if (!(trace_flags & TRACE_ITER_BLOCK))
wake_up(&trace_wait);
}
#ifdef CONFIG_FTRACE #ifdef CONFIG_FTRACE
static void static void
function_trace_call(unsigned long ip, unsigned long parent_ip) function_trace_call(unsigned long ip, unsigned long parent_ip)
...@@ -1183,13 +1208,14 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) ...@@ -1183,13 +1208,14 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
trace_seq_puts(s, ")\n"); trace_seq_puts(s, ")\n");
break; break;
case TRACE_CTX: case TRACE_CTX:
case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ? S = entry->ctx.prev_state < sizeof(state_to_char) ?
state_to_char[entry->ctx.prev_state] : 'X'; state_to_char[entry->ctx.prev_state] : 'X';
comm = trace_find_cmdline(entry->ctx.next_pid); comm = trace_find_cmdline(entry->ctx.next_pid);
trace_seq_printf(s, " %d:%d:%c --> %d:%d %s\n", trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d %s\n",
entry->ctx.prev_pid, entry->ctx.prev_pid,
entry->ctx.prev_prio, entry->ctx.prev_prio,
S, S, entry->type == TRACE_CTX ? "==>" : " +",
entry->ctx.next_pid, entry->ctx.next_pid,
entry->ctx.next_prio, entry->ctx.next_prio,
comm); comm);
...@@ -1256,12 +1282,14 @@ static int print_trace_fmt(struct trace_iterator *iter) ...@@ -1256,12 +1282,14 @@ static int print_trace_fmt(struct trace_iterator *iter)
return 0; return 0;
break; break;
case TRACE_CTX: case TRACE_CTX:
case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ? S = entry->ctx.prev_state < sizeof(state_to_char) ?
state_to_char[entry->ctx.prev_state] : 'X'; state_to_char[entry->ctx.prev_state] : 'X';
ret = trace_seq_printf(s, " %d:%d:%c ==> %d:%d\n", ret = trace_seq_printf(s, " %5d:%3d:%c %s %5d:%3d\n",
entry->ctx.prev_pid, entry->ctx.prev_pid,
entry->ctx.prev_prio, entry->ctx.prev_prio,
S, S,
entry->type == TRACE_CTX ? "==>" : " +",
entry->ctx.next_pid, entry->ctx.next_pid,
entry->ctx.next_prio); entry->ctx.next_prio);
if (!ret) if (!ret)
...@@ -1301,8 +1329,11 @@ static int print_raw_fmt(struct trace_iterator *iter) ...@@ -1301,8 +1329,11 @@ static int print_raw_fmt(struct trace_iterator *iter)
return 0; return 0;
break; break;
case TRACE_CTX: case TRACE_CTX:
case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ? S = entry->ctx.prev_state < sizeof(state_to_char) ?
state_to_char[entry->ctx.prev_state] : 'X'; state_to_char[entry->ctx.prev_state] : 'X';
if (entry->type == TRACE_WAKE)
S = '+';
ret = trace_seq_printf(s, "%d %d %c %d %d\n", ret = trace_seq_printf(s, "%d %d %c %d %d\n",
entry->ctx.prev_pid, entry->ctx.prev_pid,
entry->ctx.prev_prio, entry->ctx.prev_prio,
...@@ -1355,8 +1386,11 @@ static int print_hex_fmt(struct trace_iterator *iter) ...@@ -1355,8 +1386,11 @@ static int print_hex_fmt(struct trace_iterator *iter)
SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip); SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip);
break; break;
case TRACE_CTX: case TRACE_CTX:
case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ? S = entry->ctx.prev_state < sizeof(state_to_char) ?
state_to_char[entry->ctx.prev_state] : 'X'; state_to_char[entry->ctx.prev_state] : 'X';
if (entry->type == TRACE_WAKE)
S = '+';
SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_pid); SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_pid);
SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_prio); SEQ_PUT_HEX_FIELD_RET(s, entry->ctx.prev_prio);
SEQ_PUT_HEX_FIELD_RET(s, S); SEQ_PUT_HEX_FIELD_RET(s, S);
......
...@@ -164,6 +164,12 @@ void tracing_sched_switch_trace(struct trace_array *tr, ...@@ -164,6 +164,12 @@ void tracing_sched_switch_trace(struct trace_array *tr,
struct task_struct *next, struct task_struct *next,
unsigned long flags); unsigned long flags);
void tracing_record_cmdline(struct task_struct *tsk); void tracing_record_cmdline(struct task_struct *tsk);
void tracing_sched_wakeup_trace(struct trace_array *tr,
struct trace_array_cpu *data,
struct task_struct *wakee,
struct task_struct *cur,
unsigned long flags);
void trace_special(struct trace_array *tr, void trace_special(struct trace_array *tr,
struct trace_array_cpu *data, struct trace_array_cpu *data,
unsigned long arg1, unsigned long arg1,
...@@ -194,11 +200,17 @@ extern cycle_t ftrace_now(int cpu); ...@@ -194,11 +200,17 @@ extern cycle_t ftrace_now(int cpu);
#ifdef CONFIG_SCHED_TRACER #ifdef CONFIG_SCHED_TRACER
extern void extern void
wakeup_sched_switch(struct task_struct *prev, struct task_struct *next); wakeup_sched_switch(struct task_struct *prev, struct task_struct *next);
extern void
wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr);
#else #else
static inline void static inline void
wakeup_sched_switch(struct task_struct *prev, struct task_struct *next) wakeup_sched_switch(struct task_struct *prev, struct task_struct *next)
{ {
} }
static inline void
wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr)
{
}
#endif #endif
#ifdef CONFIG_CONTEXT_SWITCH_TRACER #ifdef CONFIG_CONTEXT_SWITCH_TRACER
......
...@@ -41,6 +41,29 @@ ctx_switch_func(struct task_struct *prev, struct task_struct *next) ...@@ -41,6 +41,29 @@ ctx_switch_func(struct task_struct *prev, struct task_struct *next)
local_irq_restore(flags); local_irq_restore(flags);
} }
static void wakeup_func(struct task_struct *wakee, struct task_struct *curr)
{
struct trace_array *tr = ctx_trace;
struct trace_array_cpu *data;
unsigned long flags;
long disabled;
int cpu;
if (!tracer_enabled)
return;
local_irq_save(flags);
cpu = raw_smp_processor_id();
data = tr->data[cpu];
disabled = atomic_inc_return(&data->disabled);
if (likely(disabled == 1))
tracing_sched_wakeup_trace(tr, data, wakee, curr, flags);
atomic_dec(&data->disabled);
local_irq_restore(flags);
}
void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next) void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next)
{ {
tracing_record_cmdline(prev); tracing_record_cmdline(prev);
...@@ -57,6 +80,19 @@ void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next) ...@@ -57,6 +80,19 @@ void ftrace_ctx_switch(struct task_struct *prev, struct task_struct *next)
wakeup_sched_switch(prev, next); wakeup_sched_switch(prev, next);
} }
void
ftrace_wake_up_task(struct task_struct *wakee, struct task_struct *curr)
{
tracing_record_cmdline(curr);
wakeup_func(wakee, curr);
/*
* Chain to the wakeup tracer (this is a NOP if disabled):
*/
wakeup_sched_wakeup(wakee, curr);
}
static void sched_switch_reset(struct trace_array *tr) static void sched_switch_reset(struct trace_array *tr)
{ {
int cpu; int cpu;
......
...@@ -202,7 +202,7 @@ wakeup_check_start(struct trace_array *tr, struct task_struct *p, ...@@ -202,7 +202,7 @@ wakeup_check_start(struct trace_array *tr, struct task_struct *p,
} }
void void
ftrace_wake_up_task(struct task_struct *wakee, struct task_struct *curr) wakeup_sched_wakeup(struct task_struct *wakee, struct task_struct *curr)
{ {
if (likely(!tracer_enabled)) if (likely(!tracer_enabled))
return; return;
......
...@@ -8,6 +8,7 @@ static inline int trace_valid_entry(struct trace_entry *entry) ...@@ -8,6 +8,7 @@ static inline int trace_valid_entry(struct trace_entry *entry)
switch (entry->type) { switch (entry->type) {
case TRACE_FN: case TRACE_FN:
case TRACE_CTX: case TRACE_CTX:
case TRACE_WAKE:
return 1; return 1;
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment