linux/arch/cris/kernel/stacktrace.c
<<
>>
Prefs
   1#include <linux/sched.h>
   2#include <linux/stacktrace.h>
   3#include <linux/stacktrace.h>
   4#include <asm/stacktrace.h>
   5
   6void walk_stackframe(unsigned long sp,
   7                     int (*fn)(unsigned long addr, void *data),
   8                     void *data)
   9{
  10        unsigned long high = ALIGN(sp, THREAD_SIZE);
  11
  12        for (; sp <= high - 4; sp += 4) {
  13                unsigned long addr = *(unsigned long *) sp;
  14
  15                if (!kernel_text_address(addr))
  16                        continue;
  17
  18                if (fn(addr, data))
  19                        break;
  20        }
  21}
  22
  23struct stack_trace_data {
  24        struct stack_trace *trace;
  25        unsigned int no_sched_functions;
  26        unsigned int skip;
  27};
  28
  29#ifdef CONFIG_STACKTRACE
  30
  31static int save_trace(unsigned long addr, void *d)
  32{
  33        struct stack_trace_data *data = d;
  34        struct stack_trace *trace = data->trace;
  35
  36        if (data->no_sched_functions && in_sched_functions(addr))
  37                return 0;
  38
  39        if (data->skip) {
  40                data->skip--;
  41                return 0;
  42        }
  43
  44        trace->entries[trace->nr_entries++] = addr;
  45
  46        return trace->nr_entries >= trace->max_entries;
  47}
  48
  49void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
  50{
  51        struct stack_trace_data data;
  52        unsigned long sp;
  53
  54        data.trace = trace;
  55        data.skip = trace->skip;
  56
  57        if (tsk != current) {
  58                data.no_sched_functions = 1;
  59                sp = tsk->thread.ksp;
  60        } else {
  61                data.no_sched_functions = 0;
  62                sp = rdsp();
  63        }
  64
  65        walk_stackframe(sp, save_trace, &data);
  66        if (trace->nr_entries < trace->max_entries)
  67                trace->entries[trace->nr_entries++] = ULONG_MAX;
  68}
  69
  70void save_stack_trace(struct stack_trace *trace)
  71{
  72        save_stack_trace_tsk(current, trace);
  73}
  74EXPORT_SYMBOL_GPL(save_stack_trace);
  75
  76#endif /* CONFIG_STACKTRACE */
  77