diff options
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r-- | kernel/softirq.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index 68eb5efec38..a25bf611d13 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -23,7 +23,10 @@ #include <linux/rcupdate.h> #include <linux/ftrace.h> #include <linux/smp.h> +#include <linux/marker.h> +#include <linux/kallsyms.h> #include <linux/tick.h> +#include <trace/irq.h> #define CREATE_TRACE_POINTS #include <trace/events/irq.h> @@ -54,6 +57,20 @@ EXPORT_SYMBOL(irq_stat); static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; +void ltt_dump_softirq_vec(void *call_data) +{ + int i; + char namebuf[KSYM_NAME_LEN]; + + for (i = 0; i < 32; i++) { + sprint_symbol(namebuf, (unsigned long)softirq_vec[i].action); + __trace_mark(0, softirq_state, softirq_vec, call_data, + "id %d address %p symbol %s", + i, softirq_vec[i].action, namebuf); + } +} +EXPORT_SYMBOL_GPL(ltt_dump_softirq_vec); + static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); char *softirq_to_name[NR_SOFTIRQS] = { @@ -61,6 +78,11 @@ char *softirq_to_name[NR_SOFTIRQS] = { "TASKLET", "SCHED", "HRTIMER", "RCU" }; +DEFINE_TRACE(irq_tasklet_high_entry); +DEFINE_TRACE(irq_tasklet_high_exit); +DEFINE_TRACE(irq_tasklet_low_entry); +DEFINE_TRACE(irq_tasklet_low_exit); + /* * we cannot loop indefinitely here to avoid userspace starvation, * but we also don't want to introduce a worst case 1/HZ latency @@ -341,6 +363,7 @@ void irq_exit(void) */ inline void raise_softirq_irqoff(unsigned int nr) { + trace_softirq_raise(nr); __raise_softirq_irqoff(nr); /* @@ -440,7 +463,9 @@ static void tasklet_action(struct softirq_action *a) if (!atomic_read(&t->count)) { if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) BUG(); + trace_irq_tasklet_low_entry(t); t->func(t->data); + trace_irq_tasklet_low_exit(t); tasklet_unlock(t); continue; } @@ -475,7 +500,9 @@ static void tasklet_hi_action(struct softirq_action *a) if (!atomic_read(&t->count)) { if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) BUG(); + trace_irq_tasklet_high_entry(t); t->func(t->data); + trace_irq_tasklet_high_exit(t); tasklet_unlock(t); continue; } |