diff options
-rw-r--r-- | kernel/trace/ring_buffer.c | 64 |
1 files changed, 17 insertions, 47 deletions
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 81279c6602ff..f6ee9b1ef62a 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -2538,61 +2538,29 @@ rb_wakeups(struct ring_buffer *buffer, struct ring_buffer_per_cpu *cpu_buffer) | |||
2538 | * The lock and unlock are done within a preempt disable section. | 2538 | * The lock and unlock are done within a preempt disable section. |
2539 | * The current_context per_cpu variable can only be modified | 2539 | * The current_context per_cpu variable can only be modified |
2540 | * by the current task between lock and unlock. But it can | 2540 | * by the current task between lock and unlock. But it can |
2541 | * be modified more than once via an interrupt. To pass this | 2541 | * be modified more than once via an interrupt. There are four |
2542 | * information from the lock to the unlock without having to | 2542 | * different contexts that we need to consider. |
2543 | * access the 'in_interrupt()' functions again (which do show | ||
2544 | * a bit of overhead in something as critical as function tracing, | ||
2545 | * we use a bitmask trick. | ||
2546 | * | 2543 | * |
2547 | * bit 0 = NMI context | 2544 | * Normal context. |
2548 | * bit 1 = IRQ context | 2545 | * SoftIRQ context |
2549 | * bit 2 = SoftIRQ context | 2546 | * IRQ context |
2550 | * bit 3 = normal context. | 2547 | * NMI context |
2551 | * | 2548 | * |
2552 | * This works because this is the order of contexts that can | 2549 | * If for some reason the ring buffer starts to recurse, we |
2553 | * preempt other contexts. A SoftIRQ never preempts an IRQ | 2550 | * only allow that to happen at most 4 times (one for each |
2554 | * context. | 2551 | * context). If it happens 5 times, then we consider this a |
2555 | * | 2552 | * recusive loop and do not let it go further. |
2556 | * When the context is determined, the corresponding bit is | ||
2557 | * checked and set (if it was set, then a recursion of that context | ||
2558 | * happened). | ||
2559 | * | ||
2560 | * On unlock, we need to clear this bit. To do so, just subtract | ||
2561 | * 1 from the current_context and AND it to itself. | ||
2562 | * | ||
2563 | * (binary) | ||
2564 | * 101 - 1 = 100 | ||
2565 | * 101 & 100 = 100 (clearing bit zero) | ||
2566 | * | ||
2567 | * 1010 - 1 = 1001 | ||
2568 | * 1010 & 1001 = 1000 (clearing bit 1) | ||
2569 | * | ||
2570 | * The least significant bit can be cleared this way, and it | ||
2571 | * just so happens that it is the same bit corresponding to | ||
2572 | * the current context. | ||
2573 | */ | 2553 | */ |
2574 | 2554 | ||
2575 | static __always_inline int | 2555 | static __always_inline int |
2576 | trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer) | 2556 | trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer) |
2577 | { | 2557 | { |
2578 | unsigned int val = cpu_buffer->current_context; | 2558 | if (cpu_buffer->current_context >= 4) |
2579 | int bit; | ||
2580 | |||
2581 | if (in_interrupt()) { | ||
2582 | if (in_nmi()) | ||
2583 | bit = RB_CTX_NMI; | ||
2584 | else if (in_irq()) | ||
2585 | bit = RB_CTX_IRQ; | ||
2586 | else | ||
2587 | bit = RB_CTX_SOFTIRQ; | ||
2588 | } else | ||
2589 | bit = RB_CTX_NORMAL; | ||
2590 | |||
2591 | if (unlikely(val & (1 << bit))) | ||
2592 | return 1; | 2559 | return 1; |
2593 | 2560 | ||
2594 | val |= (1 << bit); | 2561 | cpu_buffer->current_context++; |
2595 | cpu_buffer->current_context = val; | 2562 | /* Interrupts must see this update */ |
2563 | barrier(); | ||
2596 | 2564 | ||
2597 | return 0; | 2565 | return 0; |
2598 | } | 2566 | } |
@@ -2600,7 +2568,9 @@ trace_recursive_lock(struct ring_buffer_per_cpu *cpu_buffer) | |||
2600 | static __always_inline void | 2568 | static __always_inline void |
2601 | trace_recursive_unlock(struct ring_buffer_per_cpu *cpu_buffer) | 2569 | trace_recursive_unlock(struct ring_buffer_per_cpu *cpu_buffer) |
2602 | { | 2570 | { |
2603 | cpu_buffer->current_context &= cpu_buffer->current_context - 1; | 2571 | /* Don't let the dec leak out */ |
2572 | barrier(); | ||
2573 | cpu_buffer->current_context--; | ||
2604 | } | 2574 | } |
2605 | 2575 | ||
2606 | /** | 2576 | /** |