Back to home page

LXR

 
 

    


0001 /*
0002  * Provide a default dump_stack() function for architectures
0003  * which don't implement their own.
0004  */
0005 
0006 #include <linux/kernel.h>
0007 #include <linux/export.h>
0008 #include <linux/sched.h>
0009 #include <linux/smp.h>
0010 #include <linux/atomic.h>
0011 
0012 static void __dump_stack(void)
0013 {
0014     dump_stack_print_info(KERN_DEFAULT);
0015     show_stack(NULL, NULL);
0016 }
0017 
0018 /**
0019  * dump_stack - dump the current task information and its stack trace
0020  *
0021  * Architectures can override this implementation by implementing its own.
0022  */
0023 #ifdef CONFIG_SMP
0024 static atomic_t dump_lock = ATOMIC_INIT(-1);
0025 
0026 asmlinkage __visible void dump_stack(void)
0027 {
0028     unsigned long flags;
0029     int was_locked;
0030     int old;
0031     int cpu;
0032 
0033     /*
0034      * Permit this cpu to perform nested stack dumps while serialising
0035      * against other CPUs
0036      */
0037 retry:
0038     local_irq_save(flags);
0039     cpu = smp_processor_id();
0040     old = atomic_cmpxchg(&dump_lock, -1, cpu);
0041     if (old == -1) {
0042         was_locked = 0;
0043     } else if (old == cpu) {
0044         was_locked = 1;
0045     } else {
0046         local_irq_restore(flags);
0047         cpu_relax();
0048         goto retry;
0049     }
0050 
0051     __dump_stack();
0052 
0053     if (!was_locked)
0054         atomic_set(&dump_lock, -1);
0055 
0056     local_irq_restore(flags);
0057 }
0058 #else
0059 asmlinkage __visible void dump_stack(void)
0060 {
0061     __dump_stack();
0062 }
0063 #endif
0064 EXPORT_SYMBOL(dump_stack);