Skip to content

Commit

Permalink
perf events, x86/stacktrace: Fix performance/softlockup by providing …
Browse files Browse the repository at this point in the history
…a special frame pointer-only stack walker

It's just wasteful for stacktrace users like perf to walk
through every entries on the stack whereas these only accept
reliable ones, ie: that the frame pointer validates.

Since perf requires pure reliable stacktraces, it needs a stack
walker based on frame pointers-only to optimize the stacktrace
processing.

This might solve some near-lockup scenarios that can be triggered
by call-graph tracing timer events.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1261024834-5336-2-git-send-regression-fweisbec@gmail.com>
[ v2: fix for modular builds and small detail tidyup ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Frederic Weisbecker authored and Ingo Molnar committed Dec 17, 2009
1 parent 61c1917 commit 06d65bd
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
6 changes: 6 additions & 0 deletions arch/x86/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ print_context_stack(struct thread_info *tinfo,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph);

extern unsigned long
print_context_stack_bp(struct thread_info *tinfo,
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph);

/* Generic stack tracer with callbacks */

struct stacktrace_ops {
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -2336,7 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = {
.warning_symbol = backtrace_warning_symbol,
.stack = backtrace_stack,
.address = backtrace_address,
.walk_stack = print_context_stack,
.walk_stack = print_context_stack_bp,
};

#include "../dumpstack.h"
Expand Down
28 changes: 26 additions & 2 deletions arch/x86/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,30 @@ print_context_stack(struct thread_info *tinfo,
}
return bp;
}
EXPORT_SYMBOL_GPL(print_context_stack);

unsigned long
print_context_stack_bp(struct thread_info *tinfo,
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph)
{
struct stack_frame *frame = (struct stack_frame *)bp;
unsigned long *ret_addr = &frame->return_address;

while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
unsigned long addr = *ret_addr;

if (__kernel_text_address(addr)) {
ops->address(data, addr, 1);
frame = frame->next_frame;
ret_addr = &frame->return_address;
print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
}
}
return (unsigned long)frame;
}
EXPORT_SYMBOL_GPL(print_context_stack_bp);


static void
Expand Down Expand Up @@ -143,8 +167,8 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
static const struct stacktrace_ops print_trace_ops = {
.warning = print_trace_warning,
.warning_symbol = print_trace_warning_symbol,
.stack = print_trace_stack,
.address = print_trace_address,
.stack = print_trace_stack,
.address = print_trace_address,
.walk_stack = print_context_stack,
};

Expand Down

0 comments on commit 06d65bd

Please sign in to comment.