diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
-rw-r--r-- | kernel/trace/ring_buffer.c | 114 |
1 files changed, 85 insertions, 29 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index ce8514feedcd..6989df2ba194 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -3,8 +3,10 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com> | 4 | * Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com> |
5 | */ | 5 | */ |
6 | #include <linux/ftrace_event.h> | ||
6 | #include <linux/ring_buffer.h> | 7 | #include <linux/ring_buffer.h> |
7 | #include <linux/trace_clock.h> | 8 | #include <linux/trace_clock.h> |
9 | #include <linux/trace_seq.h> | ||
8 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
9 | #include <linux/debugfs.h> | 11 | #include <linux/debugfs.h> |
10 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
@@ -21,7 +23,6 @@ | |||
21 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
22 | 24 | ||
23 | #include <asm/local.h> | 25 | #include <asm/local.h> |
24 | #include "trace.h" | ||
25 | 26 | ||
26 | static void update_pages_handler(struct work_struct *work); | 27 | static void update_pages_handler(struct work_struct *work); |
27 | 28 | ||
@@ -177,7 +178,7 @@ void tracing_off_permanent(void) | |||
177 | #define RB_MAX_SMALL_DATA (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX) | 178 | #define RB_MAX_SMALL_DATA (RB_ALIGNMENT * RINGBUF_TYPE_DATA_TYPE_LEN_MAX) |
178 | #define RB_EVNT_MIN_SIZE 8U /* two 32bit words */ | 179 | #define RB_EVNT_MIN_SIZE 8U /* two 32bit words */ |
179 | 180 | ||
180 | #if !defined(CONFIG_64BIT) || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 181 | #ifndef CONFIG_HAVE_64BIT_ALIGNED_ACCESS |
181 | # define RB_FORCE_8BYTE_ALIGNMENT 0 | 182 | # define RB_FORCE_8BYTE_ALIGNMENT 0 |
182 | # define RB_ARCH_ALIGNMENT RB_ALIGNMENT | 183 | # define RB_ARCH_ALIGNMENT RB_ALIGNMENT |
183 | #else | 184 | #else |
@@ -185,6 +186,8 @@ void tracing_off_permanent(void) | |||
185 | # define RB_ARCH_ALIGNMENT 8U | 186 | # define RB_ARCH_ALIGNMENT 8U |
186 | #endif | 187 | #endif |
187 | 188 | ||
189 | #define RB_ALIGN_DATA __aligned(RB_ARCH_ALIGNMENT) | ||
190 | |||
188 | /* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */ | 191 | /* define RINGBUF_TYPE_DATA for 'case RINGBUF_TYPE_DATA:' */ |
189 | #define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX | 192 | #define RINGBUF_TYPE_DATA 0 ... RINGBUF_TYPE_DATA_TYPE_LEN_MAX |
190 | 193 | ||
@@ -333,7 +336,7 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data); | |||
333 | struct buffer_data_page { | 336 | struct buffer_data_page { |
334 | u64 time_stamp; /* page time stamp */ | 337 | u64 time_stamp; /* page time stamp */ |
335 | local_t commit; /* write committed index */ | 338 | local_t commit; /* write committed index */ |
336 | unsigned char data[]; /* data of buffer page */ | 339 | unsigned char data[] RB_ALIGN_DATA; /* data of buffer page */ |
337 | }; | 340 | }; |
338 | 341 | ||
339 | /* | 342 | /* |
@@ -2432,41 +2435,76 @@ rb_reserve_next_event(struct ring_buffer *buffer, | |||
2432 | 2435 | ||
2433 | #ifdef CONFIG_TRACING | 2436 | #ifdef CONFIG_TRACING |
2434 | 2437 | ||
2435 | #define TRACE_RECURSIVE_DEPTH 16 | 2438 | /* |
2439 | * The lock and unlock are done within a preempt disable section. | ||
2440 | * The current_context per_cpu variable can only be modified | ||
2441 | * by the current task between lock and unlock. But it can | ||
2442 | * be modified more than once via an interrupt. To pass this | ||
2443 | * information from the lock to the unlock without having to | ||
2444 | * access the 'in_interrupt()' functions again (which do show | ||
2445 | * a bit of overhead in something as critical as function tracing, | ||
2446 | * we use a bitmask trick. | ||
2447 | * | ||
2448 | * bit 0 = NMI context | ||
2449 | * bit 1 = IRQ context | ||
2450 | * bit 2 = SoftIRQ context | ||
2451 | * bit 3 = normal context. | ||
2452 | * | ||
2453 | * This works because this is the order of contexts that can | ||
2454 | * preempt other contexts. A SoftIRQ never preempts an IRQ | ||
2455 | * context. | ||
2456 | * | ||
2457 | * When the context is determined, the corresponding bit is | ||
2458 | * checked and set (if it was set, then a recursion of that context | ||
2459 | * happened). | ||
2460 | * | ||
2461 | * On unlock, we need to clear this bit. To do so, just subtract | ||
2462 | * 1 from the current_context and AND it to itself. | ||
2463 | * | ||
2464 | * (binary) | ||
2465 | * 101 - 1 = 100 | ||
2466 | * 101 & 100 = 100 (clearing bit zero) | ||
2467 | * | ||
2468 | * 1010 - 1 = 1001 | ||
2469 | * 1010 & 1001 = 1000 (clearing bit 1) | ||
2470 | * | ||
2471 | * The least significant bit can be cleared this way, and it | ||
2472 | * just so happens that it is the same bit corresponding to | ||
2473 | * the current context. | ||
2474 | */ | ||
2475 | static DEFINE_PER_CPU(unsigned int, current_context); | ||
2436 | 2476 | ||
2437 | /* Keep this code out of the fast path cache */ | 2477 | static __always_inline int trace_recursive_lock(void) |
2438 | static noinline void trace_recursive_fail(void) | ||
2439 | { | 2478 | { |
2440 | /* Disable all tracing before we do anything else */ | 2479 | unsigned int val = this_cpu_read(current_context); |
2441 | tracing_off_permanent(); | 2480 | int bit; |
2442 | |||
2443 | printk_once(KERN_WARNING "Tracing recursion: depth[%ld]:" | ||
2444 | "HC[%lu]:SC[%lu]:NMI[%lu]\n", | ||
2445 | trace_recursion_buffer(), | ||
2446 | hardirq_count() >> HARDIRQ_SHIFT, | ||
2447 | softirq_count() >> SOFTIRQ_SHIFT, | ||
2448 | in_nmi()); | ||
2449 | |||
2450 | WARN_ON_ONCE(1); | ||
2451 | } | ||
2452 | 2481 | ||
2453 | static inline int trace_recursive_lock(void) | 2482 | if (in_interrupt()) { |
2454 | { | 2483 | if (in_nmi()) |
2455 | trace_recursion_inc(); | 2484 | bit = 0; |
2485 | else if (in_irq()) | ||
2486 | bit = 1; | ||
2487 | else | ||
2488 | bit = 2; | ||
2489 | } else | ||
2490 | bit = 3; | ||
2456 | 2491 | ||
2457 | if (likely(trace_recursion_buffer() < TRACE_RECURSIVE_DEPTH)) | 2492 | if (unlikely(val & (1 << bit))) |
2458 | return 0; | 2493 | return 1; |
2459 | 2494 | ||
2460 | trace_recursive_fail(); | 2495 | val |= (1 << bit); |
2496 | this_cpu_write(current_context, val); | ||
2461 | 2497 | ||
2462 | return -1; | 2498 | return 0; |
2463 | } | 2499 | } |
2464 | 2500 | ||
2465 | static inline void trace_recursive_unlock(void) | 2501 | static __always_inline void trace_recursive_unlock(void) |
2466 | { | 2502 | { |
2467 | WARN_ON_ONCE(!trace_recursion_buffer()); | 2503 | unsigned int val = this_cpu_read(current_context); |
2468 | 2504 | ||
2469 | trace_recursion_dec(); | 2505 | val--; |
2506 | val &= this_cpu_read(current_context); | ||
2507 | this_cpu_write(current_context, val); | ||
2470 | } | 2508 | } |
2471 | 2509 | ||
2472 | #else | 2510 | #else |
@@ -3067,6 +3105,24 @@ ring_buffer_dropped_events_cpu(struct ring_buffer *buffer, int cpu) | |||
3067 | EXPORT_SYMBOL_GPL(ring_buffer_dropped_events_cpu); | 3105 | EXPORT_SYMBOL_GPL(ring_buffer_dropped_events_cpu); |
3068 | 3106 | ||
3069 | /** | 3107 | /** |
3108 | * ring_buffer_read_events_cpu - get the number of events successfully read | ||
3109 | * @buffer: The ring buffer | ||
3110 | * @cpu: The per CPU buffer to get the number of events read | ||
3111 | */ | ||
3112 | unsigned long | ||
3113 | ring_buffer_read_events_cpu(struct ring_buffer *buffer, int cpu) | ||
3114 | { | ||
3115 | struct ring_buffer_per_cpu *cpu_buffer; | ||
3116 | |||
3117 | if (!cpumask_test_cpu(cpu, buffer->cpumask)) | ||
3118 | return 0; | ||
3119 | |||
3120 | cpu_buffer = buffer->buffers[cpu]; | ||
3121 | return cpu_buffer->read; | ||
3122 | } | ||
3123 | EXPORT_SYMBOL_GPL(ring_buffer_read_events_cpu); | ||
3124 | |||
3125 | /** | ||
3070 | * ring_buffer_entries - get the number of entries in a buffer | 3126 | * ring_buffer_entries - get the number of entries in a buffer |
3071 | * @buffer: The ring buffer | 3127 | * @buffer: The ring buffer |
3072 | * | 3128 | * |
@@ -3425,7 +3481,7 @@ static void rb_advance_iter(struct ring_buffer_iter *iter) | |||
3425 | /* check for end of page padding */ | 3481 | /* check for end of page padding */ |
3426 | if ((iter->head >= rb_page_size(iter->head_page)) && | 3482 | if ((iter->head >= rb_page_size(iter->head_page)) && |
3427 | (iter->head_page != cpu_buffer->commit_page)) | 3483 | (iter->head_page != cpu_buffer->commit_page)) |
3428 | rb_advance_iter(iter); | 3484 | rb_inc_iter(iter); |
3429 | } | 3485 | } |
3430 | 3486 | ||
3431 | static int rb_lost_events(struct ring_buffer_per_cpu *cpu_buffer) | 3487 | static int rb_lost_events(struct ring_buffer_per_cpu *cpu_buffer) |