aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRik van Riel <riel@redhat.com>2008-04-29 03:59:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:03 -0400
commit5045bcae0fb466a1dbb6af0036e56901fd7aafb7 (patch)
tree3ad84c429ff74ec0f541cc7cf05ab3788114022f /drivers
parent6e574195b75543bc6a6240306313988b1952470c (diff)
sysrq: add show-backtrace-on-all-cpus function
SysRQ-P is not always useful on SMP systems, since it usually ends up showing the backtrace of a CPU that is doing just fine, instead of the backtrace of the CPU that is having problems. This patch adds SysRQ show-all-cpus(L), which shows the backtrace of every active CPU in the system. It skips idle CPUs because some SMP systems are just too large and we already know what the backtrace of the idle task looks like. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Rik van Riel <riel@redhat.com> Randy Dunlap <randy.dunlap@oracle.com> Cc: <lwoodman@redhat.com> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/sysrq.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 1ade193c9128..9e9bad8bdcf4 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -196,6 +196,48 @@ static struct sysrq_key_op sysrq_showlocks_op = {
196#define sysrq_showlocks_op (*(struct sysrq_key_op *)0) 196#define sysrq_showlocks_op (*(struct sysrq_key_op *)0)
197#endif 197#endif
198 198
199#ifdef CONFIG_SMP
200static DEFINE_SPINLOCK(show_lock);
201
202static void showacpu(void *dummy)
203{
204 unsigned long flags;
205
206 /* Idle CPUs have no interesting backtrace. */
207 if (idle_cpu(smp_processor_id()))
208 return;
209
210 spin_lock_irqsave(&show_lock, flags);
211 printk(KERN_INFO "CPU%d:\n", smp_processor_id());
212 show_stack(NULL, NULL);
213 spin_unlock_irqrestore(&show_lock, flags);
214}
215
216static void sysrq_showregs_othercpus(struct work_struct *dummy)
217{
218 smp_call_function(showacpu, NULL, 0, 0);
219}
220
221static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
222
223static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
224{
225 struct pt_regs *regs = get_irq_regs();
226 if (regs) {
227 printk(KERN_INFO "CPU%d:\n", smp_processor_id());
228 show_regs(regs);
229 }
230 schedule_work(&sysrq_showallcpus);
231}
232
233static struct sysrq_key_op sysrq_showallcpus_op = {
234 .handler = sysrq_handle_showallcpus,
235 .help_msg = "aLlcpus",
236 .action_msg = "Show backtrace of all active CPUs",
237 .enable_mask = SYSRQ_ENABLE_DUMP,
238};
239#endif
240
199static void sysrq_handle_showregs(int key, struct tty_struct *tty) 241static void sysrq_handle_showregs(int key, struct tty_struct *tty)
200{ 242{
201 struct pt_regs *regs = get_irq_regs(); 243 struct pt_regs *regs = get_irq_regs();
@@ -340,7 +382,11 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
340 &sysrq_kill_op, /* i */ 382 &sysrq_kill_op, /* i */
341 NULL, /* j */ 383 NULL, /* j */
342 &sysrq_SAK_op, /* k */ 384 &sysrq_SAK_op, /* k */
385#ifdef CONFIG_SMP
386 &sysrq_showallcpus_op, /* l */
387#else
343 NULL, /* l */ 388 NULL, /* l */
389#endif
344 &sysrq_showmem_op, /* m */ 390 &sysrq_showmem_op, /* m */
345 &sysrq_unrt_op, /* n */ 391 &sysrq_unrt_op, /* n */
346 /* o: This will often be registered as 'Off' at init time */ 392 /* o: This will often be registered as 'Off' at init time */