linux/arch/sh/kernel/stacktrace.c
<<
>>
Prefs
   1/*
   2 * arch/sh/kernel/stacktrace.c
   3 *
   4 * Stack trace management functions
   5 *
   6 *  Copyright (C) 2006 - 2008  Paul Mundt
   7 *
   8 * This file is subject to the terms and conditions of the GNU General Public
   9 * License.  See the file "COPYING" in the main directory of this archive
  10 * for more details.
  11 */
  12#include <linux/sched.h>
  13#include <linux/stacktrace.h>
  14#include <linux/thread_info.h>
  15#include <linux/module.h>
  16#include <asm/unwinder.h>
  17#include <asm/ptrace.h>
  18#include <asm/stacktrace.h>
  19
  20static int save_stack_stack(void *data, char *name)
  21{
  22        return 0;
  23}
  24
  25/*
  26 * Save stack-backtrace addresses into a stack_trace buffer.
  27 */
  28static void save_stack_address(void *data, unsigned long addr, int reliable)
  29{
  30        struct stack_trace *trace = data;
  31
  32        if (!reliable)
  33                return;
  34
  35        if (trace->skip > 0) {
  36                trace->skip--;
  37                return;
  38        }
  39
  40        if (trace->nr_entries < trace->max_entries)
  41                trace->entries[trace->nr_entries++] = addr;
  42}
  43
  44static const struct stacktrace_ops save_stack_ops = {
  45        .stack = save_stack_stack,
  46        .address = save_stack_address,
  47};
  48
  49void save_stack_trace(struct stack_trace *trace)
  50{
  51        unsigned long *sp = (unsigned long *)current_stack_pointer;
  52
  53        unwind_stack(current, NULL, sp,  &save_stack_ops, trace);
  54        if (trace->nr_entries < trace->max_entries)
  55                trace->entries[trace->nr_entries++] = ULONG_MAX;
  56}
  57EXPORT_SYMBOL_GPL(save_stack_trace);
  58
  59static void
  60save_stack_address_nosched(void *data, unsigned long addr, int reliable)
  61{
  62        struct stack_trace *trace = (struct stack_trace *)data;
  63
  64        if (!reliable)
  65                return;
  66
  67        if (in_sched_functions(addr))
  68                return;
  69
  70        if (trace->skip > 0) {
  71                trace->skip--;
  72                return;
  73        }
  74
  75        if (trace->nr_entries < trace->max_entries)
  76                trace->entries[trace->nr_entries++] = addr;
  77}
  78
  79static const struct stacktrace_ops save_stack_ops_nosched = {
  80        .stack = save_stack_stack,
  81        .address = save_stack_address_nosched,
  82};
  83
  84void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  85{
  86        unsigned long *sp = (unsigned long *)tsk->thread.sp;
  87
  88        unwind_stack(current, NULL, sp,  &save_stack_ops_nosched, trace);
  89        if (trace->nr_entries < trace->max_entries)
  90                trace->entries[trace->nr_entries++] = ULONG_MAX;
  91}
  92EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
  93