static DEFINE_PER_CPU(struct trace_array_cpu, max_data);
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 *current_trace __read_mostly;
TRACE_FN,
TRACE_CTX,
+ TRACE_WAKE,
TRACE_SPECIAL,
__TRACE_LAST_TYPE
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
static void
function_trace_call(unsigned long ip, unsigned long parent_ip)
trace_seq_puts(s, ")\n");
break;
case TRACE_CTX:
+ case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ?
state_to_char[entry->ctx.prev_state] : 'X';
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_prio,
- S,
+ S, entry->type == TRACE_CTX ? "==>" : " +",
entry->ctx.next_pid,
entry->ctx.next_prio,
comm);
return 0;
break;
case TRACE_CTX:
+ case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ?
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_prio,
S,
+ entry->type == TRACE_CTX ? "==>" : " +",
entry->ctx.next_pid,
entry->ctx.next_prio);
if (!ret)
return 0;
break;
case TRACE_CTX:
+ case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ?
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",
entry->ctx.prev_pid,
entry->ctx.prev_prio,
SEQ_PUT_HEX_FIELD_RET(s, entry->fn.parent_ip);
break;
case TRACE_CTX:
+ case TRACE_WAKE:
S = entry->ctx.prev_state < sizeof(state_to_char) ?
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_prio);
SEQ_PUT_HEX_FIELD_RET(s, S);
struct task_struct *next,
unsigned long flags);
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,
struct trace_array_cpu *data,
unsigned long arg1,
#ifdef CONFIG_SCHED_TRACER
extern void
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
static inline void
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
#ifdef CONFIG_CONTEXT_SWITCH_TRACER
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)
{
tracing_record_cmdline(prev);
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)
{
int cpu;