diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-05 14:04:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-05 14:04:19 -0400 |
commit | 714f83d5d9f7c785f622259dad1f4fad12d64664 (patch) | |
tree | 20563541ae438e11d686b4d629074eb002a481b7 /kernel/softirq.c | |
parent | 8901e7ffc2fa78ede7ce9826dbad68a3a25dc2dc (diff) | |
parent | 645dae969c3b8651c5bc7c54a1835ec03820f85f (diff) |
Merge branch 'tracing-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'tracing-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (413 commits)
tracing, net: fix net tree and tracing tree merge interaction
tracing, powerpc: fix powerpc tree and tracing tree interaction
ring-buffer: do not remove reader page from list on ring buffer free
function-graph: allow unregistering twice
trace: make argument 'mem' of trace_seq_putmem() const
tracing: add missing 'extern' keywords to trace_output.h
tracing: provide trace_seq_reserve()
blktrace: print out BLK_TN_MESSAGE properly
blktrace: extract duplidate code
blktrace: fix memory leak when freeing struct blk_io_trace
blktrace: fix blk_probes_ref chaos
blktrace: make classic output more classic
blktrace: fix off-by-one bug
blktrace: fix the original blktrace
blktrace: fix a race when creating blk_tree_root in debugfs
blktrace: fix timestamp in binary output
tracing, Text Edit Lock: cleanup
tracing: filter fix for TRACE_EVENT_FORMAT events
ftrace: Using FTRACE_WARN_ON() to check "freed record" in ftrace_release()
x86: kretprobe-booster interrupt emulation code fix
...
Fix up trivial conflicts in
arch/parisc/include/asm/ftrace.h
include/linux/memory.h
kernel/extable.c
kernel/module.c
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r-- | kernel/softirq.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index ea23ec087ee9..d105a82543d0 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -21,8 +21,10 @@ | |||
21 | #include <linux/freezer.h> | 21 | #include <linux/freezer.h> |
22 | #include <linux/kthread.h> | 22 | #include <linux/kthread.h> |
23 | #include <linux/rcupdate.h> | 23 | #include <linux/rcupdate.h> |
24 | #include <linux/ftrace.h> | ||
24 | #include <linux/smp.h> | 25 | #include <linux/smp.h> |
25 | #include <linux/tick.h> | 26 | #include <linux/tick.h> |
27 | #include <trace/irq.h> | ||
26 | 28 | ||
27 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
28 | /* | 30 | /* |
@@ -52,6 +54,11 @@ static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp | |||
52 | 54 | ||
53 | static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); | 55 | static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); |
54 | 56 | ||
57 | char *softirq_to_name[NR_SOFTIRQS] = { | ||
58 | "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", | ||
59 | "TASKLET", "SCHED", "HRTIMER", "RCU" | ||
60 | }; | ||
61 | |||
55 | /* | 62 | /* |
56 | * we cannot loop indefinitely here to avoid userspace starvation, | 63 | * we cannot loop indefinitely here to avoid userspace starvation, |
57 | * but we also don't want to introduce a worst case 1/HZ latency | 64 | * but we also don't want to introduce a worst case 1/HZ latency |
@@ -79,13 +86,23 @@ static void __local_bh_disable(unsigned long ip) | |||
79 | WARN_ON_ONCE(in_irq()); | 86 | WARN_ON_ONCE(in_irq()); |
80 | 87 | ||
81 | raw_local_irq_save(flags); | 88 | raw_local_irq_save(flags); |
82 | add_preempt_count(SOFTIRQ_OFFSET); | 89 | /* |
90 | * The preempt tracer hooks into add_preempt_count and will break | ||
91 | * lockdep because it calls back into lockdep after SOFTIRQ_OFFSET | ||
92 | * is set and before current->softirq_enabled is cleared. | ||
93 | * We must manually increment preempt_count here and manually | ||
94 | * call the trace_preempt_off later. | ||
95 | */ | ||
96 | preempt_count() += SOFTIRQ_OFFSET; | ||
83 | /* | 97 | /* |
84 | * Were softirqs turned off above: | 98 | * Were softirqs turned off above: |
85 | */ | 99 | */ |
86 | if (softirq_count() == SOFTIRQ_OFFSET) | 100 | if (softirq_count() == SOFTIRQ_OFFSET) |
87 | trace_softirqs_off(ip); | 101 | trace_softirqs_off(ip); |
88 | raw_local_irq_restore(flags); | 102 | raw_local_irq_restore(flags); |
103 | |||
104 | if (preempt_count() == SOFTIRQ_OFFSET) | ||
105 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); | ||
89 | } | 106 | } |
90 | #else /* !CONFIG_TRACE_IRQFLAGS */ | 107 | #else /* !CONFIG_TRACE_IRQFLAGS */ |
91 | static inline void __local_bh_disable(unsigned long ip) | 108 | static inline void __local_bh_disable(unsigned long ip) |
@@ -169,6 +186,9 @@ EXPORT_SYMBOL(local_bh_enable_ip); | |||
169 | */ | 186 | */ |
170 | #define MAX_SOFTIRQ_RESTART 10 | 187 | #define MAX_SOFTIRQ_RESTART 10 |
171 | 188 | ||
189 | DEFINE_TRACE(softirq_entry); | ||
190 | DEFINE_TRACE(softirq_exit); | ||
191 | |||
172 | asmlinkage void __do_softirq(void) | 192 | asmlinkage void __do_softirq(void) |
173 | { | 193 | { |
174 | struct softirq_action *h; | 194 | struct softirq_action *h; |
@@ -195,12 +215,14 @@ restart: | |||
195 | if (pending & 1) { | 215 | if (pending & 1) { |
196 | int prev_count = preempt_count(); | 216 | int prev_count = preempt_count(); |
197 | 217 | ||
218 | trace_softirq_entry(h, softirq_vec); | ||
198 | h->action(h); | 219 | h->action(h); |
199 | 220 | trace_softirq_exit(h, softirq_vec); | |
200 | if (unlikely(prev_count != preempt_count())) { | 221 | if (unlikely(prev_count != preempt_count())) { |
201 | printk(KERN_ERR "huh, entered softirq %td %p" | 222 | printk(KERN_ERR "huh, entered softirq %td %s %p" |
202 | "with preempt_count %08x," | 223 | "with preempt_count %08x," |
203 | " exited with %08x?\n", h - softirq_vec, | 224 | " exited with %08x?\n", h - softirq_vec, |
225 | softirq_to_name[h - softirq_vec], | ||
204 | h->action, prev_count, preempt_count()); | 226 | h->action, prev_count, preempt_count()); |
205 | preempt_count() = prev_count; | 227 | preempt_count() = prev_count; |
206 | } | 228 | } |