diff options
author | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-08-15 14:11:45 -0400 |
commit | ee3e542fec6e69bc9fb668698889a37d93950ddf (patch) | |
tree | e74ee766a4764769ef1d3d45d266b4dea64101d3 /lib/dump_stack.c | |
parent | fe2a801b50c0bb8039d627e5ae1fec249d10ff39 (diff) | |
parent | f1d6e17f540af37bb1891480143669ba7636c4cf (diff) |
Merge remote-tracking branch 'linus/master' into testing
Diffstat (limited to 'lib/dump_stack.c')
-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); |