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); |
