Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 349865
b: refs/heads/master
c: 567cd4d
h: refs/heads/master
i:
  349863: 8df8fd7
v: v3
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Jan 23, 2013
1 parent 2484284 commit 716a006
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 32 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 897f68a48b1f8fb6cb7493e1ee37e3ed7f879937
refs/heads/master: 567cd4da54ff45513d2ca1f0e3cb9ba45b66d6cf
85 changes: 60 additions & 25 deletions trunk/kernel/trace/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2432,41 +2432,76 @@ rb_reserve_next_event(struct ring_buffer *buffer,

#ifdef CONFIG_TRACING

#define TRACE_RECURSIVE_DEPTH 16
/*
* The lock and unlock are done within a preempt disable section.
* The current_context per_cpu variable can only be modified
* by the current task between lock and unlock. But it can
* be modified more than once via an interrupt. To pass this
* information from the lock to the unlock without having to
* access the 'in_interrupt()' functions again (which do show
* a bit of overhead in something as critical as function tracing,
* we use a bitmask trick.
*
* bit 0 = NMI context
* bit 1 = IRQ context
* bit 2 = SoftIRQ context
* bit 3 = normal context.
*
* This works because this is the order of contexts that can
* preempt other contexts. A SoftIRQ never preempts an IRQ
* context.
*
* When the context is determined, the corresponding bit is
* checked and set (if it was set, then a recursion of that context
* happened).
*
* On unlock, we need to clear this bit. To do so, just subtract
* 1 from the current_context and AND it to itself.
*
* (binary)
* 101 - 1 = 100
* 101 & 100 = 100 (clearing bit zero)
*
* 1010 - 1 = 1001
* 1010 & 1001 = 1000 (clearing bit 1)
*
* The least significant bit can be cleared this way, and it
* just so happens that it is the same bit corresponding to
* the current context.
*/
static DEFINE_PER_CPU(unsigned int, current_context);

/* Keep this code out of the fast path cache */
static noinline void trace_recursive_fail(void)
static __always_inline int trace_recursive_lock(void)
{
/* Disable all tracing before we do anything else */
tracing_off_permanent();

printk_once(KERN_WARNING "Tracing recursion: depth[%ld]:"
"HC[%lu]:SC[%lu]:NMI[%lu]\n",
trace_recursion_buffer(),
hardirq_count() >> HARDIRQ_SHIFT,
softirq_count() >> SOFTIRQ_SHIFT,
in_nmi());
unsigned int val = this_cpu_read(current_context);
int bit;

WARN_ON_ONCE(1);
}

static inline int trace_recursive_lock(void)
{
trace_recursion_inc();
if (in_interrupt()) {
if (in_nmi())
bit = 0;
else if (in_irq())
bit = 1;
else
bit = 2;
} else
bit = 3;

if (likely(trace_recursion_buffer() < TRACE_RECURSIVE_DEPTH))
return 0;
if (unlikely(val & (1 << bit)))
return 1;

trace_recursive_fail();
val |= (1 << bit);
this_cpu_write(current_context, val);

return -1;
return 0;
}

static inline void trace_recursive_unlock(void)
static __always_inline void trace_recursive_unlock(void)
{
WARN_ON_ONCE(!trace_recursion_buffer());
unsigned int val = this_cpu_read(current_context);

trace_recursion_dec();
val--;
val &= this_cpu_read(current_context);
this_cpu_write(current_context, val);
}

#else
Expand Down
13 changes: 7 additions & 6 deletions trunk/kernel/trace/trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,6 @@ struct tracer {


/* Only current can touch trace_recursion */
#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)

/* Ring buffer has the 10 LSB bits to count */
#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)

/*
* For function tracing recursion:
Expand Down Expand Up @@ -323,7 +318,13 @@ struct tracer {
* caller, and we can skip the current check.
*/
enum {
TRACE_FTRACE_BIT = 11,
TRACE_BUFFER_BIT,
TRACE_BUFFER_NMI_BIT,
TRACE_BUFFER_IRQ_BIT,
TRACE_BUFFER_SIRQ_BIT,

/* Start of function recursion bits */
TRACE_FTRACE_BIT,
TRACE_FTRACE_NMI_BIT,
TRACE_FTRACE_IRQ_BIT,
TRACE_FTRACE_SIRQ_BIT,
Expand Down

0 comments on commit 716a006

Please sign in to comment.