diff options
-rw-r--r-- | lib/dump_stack.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/lib/dump_stack.c b/lib/dump_stack.c index 53bad099ebd6..c03154173cc7 100644 --- a/lib/dump_stack.c +++ b/lib/dump_stack.c | |||
@@ -6,15 +6,58 @@ | |||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/export.h> | 7 | #include <linux/export.h> |
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <linux/smp.h> | ||
10 | #include <linux/atomic.h> | ||
11 | |||
12 | static void __dump_stack(void) | ||
13 | { | ||
14 | dump_stack_print_info(KERN_DEFAULT); | ||
15 | show_stack(NULL, NULL); | ||
16 | } | ||
9 | 17 | ||
10 | /** | 18 | /** |
11 | * dump_stack - dump the current task information and its stack trace | 19 | * dump_stack - dump the current task information and its stack trace |
12 | * | 20 | * |
13 | * Architectures can override this implementation by implementing its own. | 21 | * Architectures can override this implementation by implementing its own. |
14 | */ | 22 | */ |
23 | #ifdef CONFIG_SMP | ||
24 | static atomic_t dump_lock = ATOMIC_INIT(-1); | ||
25 | |||
15 | void dump_stack(void) | 26 | void dump_stack(void) |
16 | { | 27 | { |
17 | dump_stack_print_info(KERN_DEFAULT); | 28 | int was_locked; |
18 | show_stack(NULL, NULL); | 29 | int old; |
30 | int cpu; | ||
31 | |||
32 | /* | ||
33 | * Permit this cpu to perform nested stack dumps while serialising | ||
34 | * against other CPUs | ||
35 | */ | ||
36 | preempt_disable(); | ||
37 | |||
38 | retry: | ||
39 | cpu = smp_processor_id(); | ||
40 | old = atomic_cmpxchg(&dump_lock, -1, cpu); | ||
41 | if (old == -1) { | ||
42 | was_locked = 0; | ||
43 | } else if (old == cpu) { | ||
44 | was_locked = 1; | ||
45 | } else { | ||
46 | cpu_relax(); | ||
47 | goto retry; | ||
48 | } | ||
49 | |||
50 | __dump_stack(); | ||
51 | |||
52 | if (!was_locked) | ||
53 | atomic_set(&dump_lock, -1); | ||
54 | |||
55 | preempt_enable(); | ||
56 | } | ||
57 | #else | ||
58 | void dump_stack(void) | ||
59 | { | ||
60 | __dump_stack(); | ||
19 | } | 61 | } |
62 | #endif | ||
20 | EXPORT_SYMBOL(dump_stack); | 63 | EXPORT_SYMBOL(dump_stack); |