1 /* 2 * Provide a default dump_stack() function for architectures 3 * which don't implement their own. 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/export.h> 8 #include <linux/sched.h> 9 #include <linux/sched/debug.h> 10 #include <linux/smp.h> 11 #include <linux/atomic.h> 12 13 static void __dump_stack(void) 14 { 15 dump_stack_print_info(KERN_DEFAULT); 16 show_stack(NULL, NULL); 17 } 18 19 /** 20 * dump_stack - dump the current task information and its stack trace 21 * 22 * Architectures can override this implementation by implementing its own. 23 */ 24 #ifdef CONFIG_SMP 25 static atomic_t dump_lock = ATOMIC_INIT(-1); 26 27 asmlinkage __visible void dump_stack(void) 28 { 29 unsigned long flags; 30 int was_locked; 31 int old; 32 int cpu; 33 34 /* 35 * Permit this cpu to perform nested stack dumps while serialising 36 * against other CPUs 37 */ 38 retry: 39 local_irq_save(flags); 40 cpu = smp_processor_id(); 41 old = atomic_cmpxchg(&dump_lock, -1, cpu); 42 if (old == -1) { 43 was_locked = 0; 44 } else if (old == cpu) { 45 was_locked = 1; 46 } else { 47 local_irq_restore(flags); 48 cpu_relax(); 49 goto retry; 50 } 51 52 __dump_stack(); 53 54 if (!was_locked) 55 atomic_set(&dump_lock, -1); 56 57 local_irq_restore(flags); 58 } 59 #else 60 asmlinkage __visible void dump_stack(void) 61 { 62 __dump_stack(); 63 } 64 #endif 65 EXPORT_SYMBOL(dump_stack); 66