diff options
author | Steven Rostedt <srostedt@redhat.com> | 2011-09-22 14:01:55 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2012-04-23 21:15:55 -0400 |
commit | 07d777fe8c3985bc83428c2866713c2d1b3d4129 (patch) | |
tree | f14c6aa59b9719761ad9feebebca22550ebdf0e3 /include/linux/kernel.h | |
parent | a385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff) |
tracing: Add percpu buffers for trace_printk()
Currently, trace_printk() uses a single buffer to write into
to calculate the size and format needed to save the trace. To
do this safely in an SMP environment, a spin_lock() is taken
to only allow one writer at a time to the buffer. But this could
also affect what is being traced, and add synchronization that
would not be there otherwise.
Ideally, using percpu buffers would be useful, but since trace_printk()
is only used in development, having per cpu buffers for something
never used is a waste of space. Thus, the use of the trace_bprintk()
format section is changed to be used for static fmts as well as dynamic ones.
Then at boot up, we can check if the section that holds the trace_printk
formats is non-empty, and if it does contain something, then we
know a trace_printk() has been added to the kernel. At this time
the trace_printk per cpu buffers are allocated. A check is also
done at module load time in case a module is added that contains a
trace_printk().
Once the buffers are allocated, they are never freed. If you use
a trace_printk() then you should know what you are doing.
A buffer is made for each type of context:
normal
softirq
irq
nmi
The context is checked and the appropriate buffer is used.
This allows for totally lockless usage of trace_printk(),
and they no longer even disable interrupts.
Requested-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'include/linux/kernel.h')
-rw-r--r-- | include/linux/kernel.h | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 645231c373c8..c0d34420a913 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -480,15 +480,16 @@ do { \ | |||
480 | 480 | ||
481 | #define trace_printk(fmt, args...) \ | 481 | #define trace_printk(fmt, args...) \ |
482 | do { \ | 482 | do { \ |
483 | static const char *trace_printk_fmt \ | ||
484 | __attribute__((section("__trace_printk_fmt"))) = \ | ||
485 | __builtin_constant_p(fmt) ? fmt : NULL; \ | ||
486 | \ | ||
483 | __trace_printk_check_format(fmt, ##args); \ | 487 | __trace_printk_check_format(fmt, ##args); \ |
484 | if (__builtin_constant_p(fmt)) { \ | ||
485 | static const char *trace_printk_fmt \ | ||
486 | __attribute__((section("__trace_printk_fmt"))) = \ | ||
487 | __builtin_constant_p(fmt) ? fmt : NULL; \ | ||
488 | \ | 488 | \ |
489 | if (__builtin_constant_p(fmt)) \ | ||
489 | __trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \ | 490 | __trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \ |
490 | } else \ | 491 | else \ |
491 | __trace_printk(_THIS_IP_, fmt, ##args); \ | 492 | __trace_printk(_THIS_IP_, fmt, ##args); \ |
492 | } while (0) | 493 | } while (0) |
493 | 494 | ||
494 | extern __printf(2, 3) | 495 | extern __printf(2, 3) |