oprof.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /**
  2. * @file oprof.c
  3. *
  4. * @remark Copyright 2002 OProfile authors
  5. * @remark Read the file COPYING
  6. *
  7. * @author John Levon <levon@movementarian.org>
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/init.h>
  12. #include <linux/oprofile.h>
  13. #include <linux/moduleparam.h>
  14. #include <asm/semaphore.h>
  15. #include "oprof.h"
  16. #include "event_buffer.h"
  17. #include "cpu_buffer.h"
  18. #include "buffer_sync.h"
  19. #include "oprofile_stats.h"
  20. struct oprofile_operations oprofile_ops;
  21. unsigned long oprofile_started;
  22. unsigned long backtrace_depth;
  23. static unsigned long is_setup;
  24. static DECLARE_MUTEX(start_sem);
  25. /* timer
  26. 0 - use performance monitoring hardware if available
  27. 1 - use the timer int mechanism regardless
  28. */
  29. static int timer = 0;
  30. int oprofile_setup(void)
  31. {
  32. int err;
  33. down(&start_sem);
  34. if ((err = alloc_cpu_buffers()))
  35. goto out;
  36. if ((err = alloc_event_buffer()))
  37. goto out1;
  38. if (oprofile_ops.setup && (err = oprofile_ops.setup()))
  39. goto out2;
  40. /* Note even though this starts part of the
  41. * profiling overhead, it's necessary to prevent
  42. * us missing task deaths and eventually oopsing
  43. * when trying to process the event buffer.
  44. */
  45. if ((err = sync_start()))
  46. goto out3;
  47. is_setup = 1;
  48. up(&start_sem);
  49. return 0;
  50. out3:
  51. if (oprofile_ops.shutdown)
  52. oprofile_ops.shutdown();
  53. out2:
  54. free_event_buffer();
  55. out1:
  56. free_cpu_buffers();
  57. out:
  58. up(&start_sem);
  59. return err;
  60. }
  61. /* Actually start profiling (echo 1>/dev/oprofile/enable) */
  62. int oprofile_start(void)
  63. {
  64. int err = -EINVAL;
  65. down(&start_sem);
  66. if (!is_setup)
  67. goto out;
  68. err = 0;
  69. if (oprofile_started)
  70. goto out;
  71. oprofile_reset_stats();
  72. if ((err = oprofile_ops.start()))
  73. goto out;
  74. oprofile_started = 1;
  75. out:
  76. up(&start_sem);
  77. return err;
  78. }
  79. /* echo 0>/dev/oprofile/enable */
  80. void oprofile_stop(void)
  81. {
  82. down(&start_sem);
  83. if (!oprofile_started)
  84. goto out;
  85. oprofile_ops.stop();
  86. oprofile_started = 0;
  87. /* wake up the daemon to read what remains */
  88. wake_up_buffer_waiter();
  89. out:
  90. up(&start_sem);
  91. }
  92. void oprofile_shutdown(void)
  93. {
  94. down(&start_sem);
  95. sync_stop();
  96. if (oprofile_ops.shutdown)
  97. oprofile_ops.shutdown();
  98. is_setup = 0;
  99. free_event_buffer();
  100. free_cpu_buffers();
  101. up(&start_sem);
  102. }
  103. int oprofile_set_backtrace(unsigned long val)
  104. {
  105. int err = 0;
  106. down(&start_sem);
  107. if (oprofile_started) {
  108. err = -EBUSY;
  109. goto out;
  110. }
  111. if (!oprofile_ops.backtrace) {
  112. err = -EINVAL;
  113. goto out;
  114. }
  115. backtrace_depth = val;
  116. out:
  117. up(&start_sem);
  118. return err;
  119. }
  120. static int __init oprofile_init(void)
  121. {
  122. int err;
  123. err = oprofile_arch_init(&oprofile_ops);
  124. if (err < 0 || timer) {
  125. printk(KERN_INFO "oprofile: using timer interrupt.\n");
  126. oprofile_timer_init(&oprofile_ops);
  127. }
  128. err = oprofilefs_register();
  129. if (err)
  130. oprofile_arch_exit();
  131. return err;
  132. }
  133. static void __exit oprofile_exit(void)
  134. {
  135. oprofilefs_unregister();
  136. oprofile_arch_exit();
  137. }
  138. module_init(oprofile_init);
  139. module_exit(oprofile_exit);
  140. module_param_named(timer, timer, int, 0644);
  141. MODULE_PARM_DESC(timer, "force use of timer interrupt");
  142. MODULE_LICENSE("GPL");
  143. MODULE_AUTHOR("John Levon <levon@movementarian.org>");
  144. MODULE_DESCRIPTION("OProfile system profiler");