diff options
author | Alex Thorlton <athorlton@sgi.com> | 2013-07-03 18:04:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 19:07:41 -0400 |
commit | b58d977432c80ee60d6970042775a62e3f8d7675 (patch) | |
tree | ca998b67437265115d2d242b47f2ac52fa0091c5 /lib/dump_stack.c | |
parent | f170168b9a0b61ea1e647b082b38f605f1d3de3e (diff) |
dump_stack: serialize the output from dump_stack()
Add functionality to serialize the output from dump_stack() to avoid
mangling of the output when dump_stack is called simultaneously from
multiple cpus.
[akpm@linux-foundation.org: fix comment indenting, avoid inclusion of <asm/> files - use <linux/> where possiblem fix uniprocessor build (__dump_stack undefined), remove unneeded ifdef around smp.h inclusion]
Signed-off-by: Alex Thorlton <athorlton@sgi.com>
Reported-by: Russ Anderson <rja@sgi.com>
Reviewed-by: Robin Holt <holt@sgi.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Richard Kuo <rkuo@codeaurora.org>
Cc: Jesper Nilsson <jesper.nilsson@axis.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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); |