oprof.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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/mutex.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 oprofile_backtrace_depth;
  23. static unsigned long is_setup;
  24. static DEFINE_MUTEX(start_mutex);
  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. mutex_lock(&start_mutex);
  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 (oprofile_ops.sync_start) {
  46. int sync_ret = oprofile_ops.sync_start();
  47. switch (sync_ret) {
  48. case 0:
  49. goto post_sync;
  50. case 1:
  51. goto do_generic;
  52. case -1:
  53. goto out3;
  54. default:
  55. goto out3;
  56. }
  57. }
  58. do_generic:
  59. if ((err = sync_start()))
  60. goto out3;
  61. post_sync:
  62. is_setup = 1;
  63. mutex_unlock(&start_mutex);
  64. return 0;
  65. out3:
  66. if (oprofile_ops.shutdown)
  67. oprofile_ops.shutdown();
  68. out2:
  69. free_event_buffer();
  70. out1:
  71. free_cpu_buffers();
  72. out:
  73. mutex_unlock(&start_mutex);
  74. return err;
  75. }
  76. /* Actually start profiling (echo 1>/dev/oprofile/enable) */
  77. int oprofile_start(void)
  78. {
  79. int err = -EINVAL;
  80. mutex_lock(&start_mutex);
  81. if (!is_setup)
  82. goto out;
  83. err = 0;
  84. if (oprofile_started)
  85. goto out;
  86. oprofile_reset_stats();
  87. if ((err = oprofile_ops.start()))
  88. goto out;
  89. oprofile_started = 1;
  90. out:
  91. mutex_unlock(&start_mutex);
  92. return err;
  93. }
  94. /* echo 0>/dev/oprofile/enable */
  95. void oprofile_stop(void)
  96. {
  97. mutex_lock(&start_mutex);
  98. if (!oprofile_started)
  99. goto out;
  100. oprofile_ops.stop();
  101. oprofile_started = 0;
  102. /* wake up the daemon to read what remains */
  103. wake_up_buffer_waiter();
  104. out:
  105. mutex_unlock(&start_mutex);
  106. }
  107. void oprofile_shutdown(void)
  108. {
  109. mutex_lock(&start_mutex);
  110. if (oprofile_ops.sync_stop) {
  111. int sync_ret = oprofile_ops.sync_stop();
  112. switch (sync_ret) {
  113. case 0:
  114. goto post_sync;
  115. case 1:
  116. goto do_generic;
  117. default:
  118. goto post_sync;
  119. }
  120. }
  121. do_generic:
  122. sync_stop();
  123. post_sync:
  124. if (oprofile_ops.shutdown)
  125. oprofile_ops.shutdown();
  126. is_setup = 0;
  127. free_event_buffer();
  128. free_cpu_buffers();
  129. mutex_unlock(&start_mutex);
  130. }
  131. int oprofile_set_backtrace(unsigned long val)
  132. {
  133. int err = 0;
  134. mutex_lock(&start_mutex);
  135. if (oprofile_started) {
  136. err = -EBUSY;
  137. goto out;
  138. }
  139. if (!oprofile_ops.backtrace) {
  140. err = -EINVAL;
  141. goto out;
  142. }
  143. oprofile_backtrace_depth = val;
  144. out:
  145. mutex_unlock(&start_mutex);
  146. return err;
  147. }
  148. static int __init oprofile_init(void)
  149. {
  150. int err;
  151. err = oprofile_arch_init(&oprofile_ops);
  152. if (err < 0 || timer) {
  153. printk(KERN_INFO "oprofile: using timer interrupt.\n");
  154. oprofile_timer_init(&oprofile_ops);
  155. }
  156. err = oprofilefs_register();
  157. if (err)
  158. oprofile_arch_exit();
  159. return err;
  160. }
  161. static void __exit oprofile_exit(void)
  162. {
  163. oprofilefs_unregister();
  164. oprofile_arch_exit();
  165. }
  166. module_init(oprofile_init);
  167. module_exit(oprofile_exit);
  168. module_param_named(timer, timer, int, 0644);
  169. MODULE_PARM_DESC(timer, "force use of timer interrupt");
  170. MODULE_LICENSE("GPL");
  171. MODULE_AUTHOR("John Levon <levon@movementarian.org>");
  172. MODULE_DESCRIPTION("OProfile system profiler");