From 07d777fe8c3985bc83428c2866713c2d1b3d4129 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 22 Sep 2011 14:01:55 -0400 Subject: 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 Signed-off-by: Steven Rostedt --- include/linux/kernel.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'include/linux/kernel.h') 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 { \ #define trace_printk(fmt, args...) \ do { \ + static const char *trace_printk_fmt \ + __attribute__((section("__trace_printk_fmt"))) = \ + __builtin_constant_p(fmt) ? fmt : NULL; \ + \ __trace_printk_check_format(fmt, ##args); \ - if (__builtin_constant_p(fmt)) { \ - static const char *trace_printk_fmt \ - __attribute__((section("__trace_printk_fmt"))) = \ - __builtin_constant_p(fmt) ? fmt : NULL; \ \ + if (__builtin_constant_p(fmt)) \ __trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \ - } else \ - __trace_printk(_THIS_IP_, fmt, ##args); \ + else \ + __trace_printk(_THIS_IP_, fmt, ##args); \ } while (0) extern __printf(2, 3) -- cgit v1.2.3 From 446969084d33a4064a39d280806da642c54ba4ac Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 23 May 2012 20:12:50 -0700 Subject: kernel: Move REPEAT_BYTE definition into linux/kernel.h And make sure that everything using it explicitly includes that header file. Signed-off-by: David S. Miller --- arch/sparc/lib/usercopy.c | 3 +-- arch/x86/include/asm/word-at-a-time.h | 4 ++-- fs/namei.c | 1 + include/linux/kernel.h | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include/linux/kernel.h') diff --git a/arch/sparc/lib/usercopy.c b/arch/sparc/lib/usercopy.c index f61ed820cb61..0b12e91d6ccc 100644 --- a/arch/sparc/lib/usercopy.c +++ b/arch/sparc/lib/usercopy.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -11,8 +12,6 @@ void copy_from_user_overflow(void) } EXPORT_SYMBOL(copy_from_user_overflow); -#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) - static inline long find_zero(unsigned long mask) { long byte = 0; diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h index e58f03b206c3..ae03facfadd6 100644 --- a/arch/x86/include/asm/word-at-a-time.h +++ b/arch/x86/include/asm/word-at-a-time.h @@ -1,6 +1,8 @@ #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H +#include + /* * This is largely generic for little-endian machines, but the * optimal byte mask counting is probably going to be something @@ -35,8 +37,6 @@ static inline long count_masked_bytes(long mask) #endif -#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) - /* Return the high bit set in the first byte that is a zero */ static inline unsigned long has_zero(unsigned long a) { diff --git a/fs/namei.c b/fs/namei.c index f9e883c1b856..8d2ba420e42f 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 645231c373c8..fbe9bfacb8db 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -38,6 +38,8 @@ #define STACK_MAGIC 0xdeadbeef +#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) + #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) #define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask)) #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) -- cgit v1.2.3