dump_stack.c 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  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. void dump_stack(void)
  23. {
  24. int was_locked;
  25. int old;
  26. int cpu;
  27. /*
  28. * Permit this cpu to perform nested stack dumps while serialising
  29. * against other CPUs
  30. */
  31. preempt_disable();
  32. retry:
  33. cpu = smp_processor_id();
  34. old = atomic_cmpxchg(&dump_lock, -1, cpu);
  35. if (old == -1) {
  36. was_locked = 0;
  37. } else if (old == cpu) {
  38. was_locked = 1;
  39. } else {
  40. cpu_relax();
  41. goto retry;
  42. }
  43. __dump_stack();
  44. if (!was_locked)
  45. atomic_set(&dump_lock, -1);
  46. preempt_enable();
  47. }
  48. #else
  49. void dump_stack(void)
  50. {
  51. __dump_stack();
  52. }
  53. #endif
  54. EXPORT_SYMBOL(dump_stack);