Commit | Line | Data |
---|---|---|
5bdc9b44 | 1 | /* |
5bdc9b44 HC |
2 | * Stack trace management functions |
3 | * | |
a53c8fab | 4 | * Copyright IBM Corp. 2006 |
5bdc9b44 HC |
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> |
6 | */ | |
7 | ||
8 | #include <linux/sched.h> | |
9 | #include <linux/stacktrace.h> | |
10 | #include <linux/kallsyms.h> | |
8de2ce86 | 11 | #include <linux/module.h> |
5bdc9b44 | 12 | |
758d39eb | 13 | static int __save_address(void *data, unsigned long address, int nosched) |
5bdc9b44 | 14 | { |
758d39eb | 15 | struct stack_trace *trace = data; |
5bdc9b44 | 16 | |
758d39eb HC |
17 | if (nosched && in_sched_functions(address)) |
18 | return 0; | |
19 | if (trace->skip > 0) { | |
20 | trace->skip--; | |
21 | return 0; | |
5bdc9b44 | 22 | } |
758d39eb HC |
23 | if (trace->nr_entries < trace->max_entries) { |
24 | trace->entries[trace->nr_entries++] = address; | |
25 | return 0; | |
26 | } | |
27 | return 1; | |
5bdc9b44 HC |
28 | } |
29 | ||
d0208639 | 30 | static int save_address(void *data, unsigned long address, int reliable) |
5bdc9b44 | 31 | { |
758d39eb HC |
32 | return __save_address(data, address, 0); |
33 | } | |
5bdc9b44 | 34 | |
d0208639 | 35 | static int save_address_nosched(void *data, unsigned long address, int reliable) |
758d39eb HC |
36 | { |
37 | return __save_address(data, address, 1); | |
66adce8f HC |
38 | } |
39 | ||
40 | void save_stack_trace(struct stack_trace *trace) | |
41 | { | |
66adce8f HC |
42 | unsigned long sp; |
43 | ||
76737ce1 | 44 | sp = current_stack_pointer(); |
758d39eb | 45 | dump_trace(save_address, trace, NULL, sp); |
f6331aac HC |
46 | if (trace->nr_entries < trace->max_entries) |
47 | trace->entries[trace->nr_entries++] = ULONG_MAX; | |
a3afe70b | 48 | } |
7b4c9505 | 49 | EXPORT_SYMBOL_GPL(save_stack_trace); |
a3afe70b HC |
50 | |
51 | void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | |
52 | { | |
758d39eb | 53 | unsigned long sp; |
a3afe70b | 54 | |
9cb1ccec | 55 | sp = tsk->thread.ksp; |
76737ce1 HC |
56 | if (tsk == current) |
57 | sp = current_stack_pointer(); | |
758d39eb | 58 | dump_trace(save_address_nosched, trace, tsk, sp); |
a3afe70b HC |
59 | if (trace->nr_entries < trace->max_entries) |
60 | trace->entries[trace->nr_entries++] = ULONG_MAX; | |
5bdc9b44 | 61 | } |
7b4c9505 | 62 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |
e0115875 PA |
63 | |
64 | void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) | |
65 | { | |
66 | unsigned long sp; | |
67 | ||
68 | sp = kernel_stack_pointer(regs); | |
758d39eb | 69 | dump_trace(save_address, trace, NULL, sp); |
e0115875 PA |
70 | if (trace->nr_entries < trace->max_entries) |
71 | trace->entries[trace->nr_entries++] = ULONG_MAX; | |
72 | } | |
73 | EXPORT_SYMBOL_GPL(save_stack_trace_regs); |