dump_stack.c 1.2 KB

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