606b4c992f
This inserts a ULONG_MAX entry at the end of the valid entries in the stack trace buffer so the default code doesn't need to scan to the end of available slots. This also makes the trace buffer termination behaviour consistent with the other architectures. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
106 lines
2.4 KiB
C
106 lines
2.4 KiB
C
/*
|
|
* arch/sh/kernel/stacktrace.c
|
|
*
|
|
* Stack trace management functions
|
|
*
|
|
* Copyright (C) 2006 - 2008 Paul Mundt
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
* for more details.
|
|
*/
|
|
#include <linux/sched.h>
|
|
#include <linux/stacktrace.h>
|
|
#include <linux/thread_info.h>
|
|
#include <linux/module.h>
|
|
#include <asm/unwinder.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/stacktrace.h>
|
|
|
|
static void save_stack_warning(void *data, char *msg)
|
|
{
|
|
}
|
|
|
|
static void
|
|
save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
|
|
{
|
|
}
|
|
|
|
static int save_stack_stack(void *data, char *name)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Save stack-backtrace addresses into a stack_trace buffer.
|
|
*/
|
|
static void save_stack_address(void *data, unsigned long addr, int reliable)
|
|
{
|
|
struct stack_trace *trace = data;
|
|
|
|
if (!reliable)
|
|
return;
|
|
|
|
if (trace->skip > 0) {
|
|
trace->skip--;
|
|
return;
|
|
}
|
|
|
|
if (trace->nr_entries < trace->max_entries)
|
|
trace->entries[trace->nr_entries++] = addr;
|
|
}
|
|
|
|
static const struct stacktrace_ops save_stack_ops = {
|
|
.warning = save_stack_warning,
|
|
.warning_symbol = save_stack_warning_symbol,
|
|
.stack = save_stack_stack,
|
|
.address = save_stack_address,
|
|
};
|
|
|
|
void save_stack_trace(struct stack_trace *trace)
|
|
{
|
|
unsigned long *sp = (unsigned long *)current_stack_pointer;
|
|
|
|
unwind_stack(current, NULL, sp, &save_stack_ops, trace);
|
|
if (trace->nr_entries < trace->max_entries)
|
|
trace->entries[trace->nr_entries++] = ULONG_MAX;
|
|
}
|
|
EXPORT_SYMBOL_GPL(save_stack_trace);
|
|
|
|
static void
|
|
save_stack_address_nosched(void *data, unsigned long addr, int reliable)
|
|
{
|
|
struct stack_trace *trace = (struct stack_trace *)data;
|
|
|
|
if (!reliable)
|
|
return;
|
|
|
|
if (in_sched_functions(addr))
|
|
return;
|
|
|
|
if (trace->skip > 0) {
|
|
trace->skip--;
|
|
return;
|
|
}
|
|
|
|
if (trace->nr_entries < trace->max_entries)
|
|
trace->entries[trace->nr_entries++] = addr;
|
|
}
|
|
|
|
static const struct stacktrace_ops save_stack_ops_nosched = {
|
|
.warning = save_stack_warning,
|
|
.warning_symbol = save_stack_warning_symbol,
|
|
.stack = save_stack_stack,
|
|
.address = save_stack_address_nosched,
|
|
};
|
|
|
|
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
|
|
{
|
|
unsigned long *sp = (unsigned long *)tsk->thread.sp;
|
|
|
|
unwind_stack(current, NULL, sp, &save_stack_ops_nosched, trace);
|
|
if (trace->nr_entries < trace->max_entries)
|
|
trace->entries[trace->nr_entries++] = ULONG_MAX;
|
|
}
|
|
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
|