Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 140697
b: refs/heads/master
c: 78d904b
h: refs/heads/master
i:
  140695: 331df11
v: v3
  • Loading branch information
Steven Rostedt committed Feb 8, 2009
1 parent 128f2d3 commit f2831ca
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 8 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: 1830b52d0de8c60c4f5dfbac134aa8f69d815801
refs/heads/master: 78d904b46a72fcf15ea6a39672bbef92953876b5
1 change: 1 addition & 0 deletions trunk/arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ config X86
select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_FTRACE_NMI_ENTER if DYNAMIC_FTRACE || FUNCTION_GRAPH_TRACER
select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64)
select HAVE_ARCH_KGDB if !X86_VOYAGER
select HAVE_ARCH_TRACEHOOK
Expand Down
8 changes: 4 additions & 4 deletions trunk/arch/x86/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static void ftrace_mod_code(void)
MCOUNT_INSN_SIZE);
}

void ftrace_nmi_enter(void)
void arch_ftrace_nmi_enter(void)
{
atomic_inc(&in_nmi);
/* Must have in_nmi seen before reading write flag */
Expand All @@ -124,7 +124,7 @@ void ftrace_nmi_enter(void)
}
}

void ftrace_nmi_exit(void)
void arch_ftrace_nmi_exit(void)
{
/* Finish all executions before clearing in_nmi */
smp_wmb();
Expand Down Expand Up @@ -376,12 +376,12 @@ int ftrace_disable_ftrace_graph_caller(void)
*/
static atomic_t in_nmi;

void ftrace_nmi_enter(void)
void arch_ftrace_nmi_enter(void)
{
atomic_inc(&in_nmi);
}

void ftrace_nmi_exit(void)
void arch_ftrace_nmi_exit(void)
{
atomic_dec(&in_nmi);
}
Expand Down
10 changes: 9 additions & 1 deletion trunk/include/linux/ftrace_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
#define _LINUX_FTRACE_IRQ_H


#if defined(CONFIG_DYNAMIC_FTRACE) || defined(CONFIG_FUNCTION_GRAPH_TRACER)
#ifdef CONFIG_FTRACE_NMI_ENTER
extern void arch_ftrace_nmi_enter(void);
extern void arch_ftrace_nmi_exit(void);
#else
static inline void arch_ftrace_nmi_enter(void) { }
static inline void arch_ftrace_nmi_exit(void) { }
#endif

#ifdef CONFIG_RING_BUFFER
extern void ftrace_nmi_enter(void);
extern void ftrace_nmi_exit(void);
#else
Expand Down
8 changes: 8 additions & 0 deletions trunk/kernel/trace/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ config USER_STACKTRACE_SUPPORT
config NOP_TRACER
bool

config HAVE_FTRACE_NMI_ENTER
bool

config HAVE_FUNCTION_TRACER
bool

Expand Down Expand Up @@ -37,6 +40,11 @@ config TRACER_MAX_TRACE
config RING_BUFFER
bool

config FTRACE_NMI_ENTER
bool
depends on HAVE_FTRACE_NMI_ENTER
default y

config TRACING
bool
select DEBUG_FS
Expand Down
48 changes: 46 additions & 2 deletions trunk/kernel/trace/ring_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
*/
#include <linux/ring_buffer.h>
#include <linux/ftrace_irq.h>
#include <linux/spinlock.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
Expand All @@ -18,6 +19,35 @@

#include "trace.h"

/*
* Since the write to the buffer is still not fully lockless,
* we must be careful with NMIs. The locks in the writers
* are taken when a write crosses to a new page. The locks
* protect against races with the readers (this will soon
* be fixed with a lockless solution).
*
* Because we can not protect against NMIs, and we want to
* keep traces reentrant, we need to manage what happens
* when we are in an NMI.
*/
static DEFINE_PER_CPU(int, rb_in_nmi);

void ftrace_nmi_enter(void)
{
__get_cpu_var(rb_in_nmi)++;
/* call arch specific handler too */
arch_ftrace_nmi_enter();
}

void ftrace_nmi_exit(void)
{
arch_ftrace_nmi_exit();
__get_cpu_var(rb_in_nmi)--;
/* NMIs are not recursive */
WARN_ON_ONCE(__get_cpu_var(rb_in_nmi));
}


/*
* A fast way to enable or disable all ring buffers is to
* call tracing_on or tracing_off. Turning off the ring buffers
Expand Down Expand Up @@ -982,6 +1012,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
struct ring_buffer *buffer = cpu_buffer->buffer;
struct ring_buffer_event *event;
unsigned long flags;
bool lock_taken = false;

commit_page = cpu_buffer->commit_page;
/* we just need to protect against interrupts */
Expand All @@ -995,7 +1026,19 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
struct buffer_page *next_page = tail_page;

local_irq_save(flags);
__raw_spin_lock(&cpu_buffer->lock);
/*
* NMIs can happen after we take the lock.
* If we are in an NMI, only take the lock
* if it is not already taken. Otherwise
* simply fail.
*/
if (unlikely(__get_cpu_var(rb_in_nmi))) {
if (!__raw_spin_trylock(&cpu_buffer->lock))
goto out_unlock;
} else
__raw_spin_lock(&cpu_buffer->lock);

lock_taken = true;

rb_inc_page(cpu_buffer, &next_page);

Expand Down Expand Up @@ -1097,7 +1140,8 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
if (tail <= BUF_PAGE_SIZE)
local_set(&tail_page->write, tail);

__raw_spin_unlock(&cpu_buffer->lock);
if (likely(lock_taken))
__raw_spin_unlock(&cpu_buffer->lock);
local_irq_restore(flags);
return NULL;
}
Expand Down

0 comments on commit f2831ca

Please sign in to comment.