oprof.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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 <linux/workqueue.h>
  15. #include <linux/time.h>
  16. #include <linux/mutex.h>
  17. #include "oprof.h"
  18. #include "event_buffer.h"
  19. #include "cpu_buffer.h"
  20. #include "buffer_sync.h"
  21. #include "oprofile_stats.h"
  22. struct oprofile_operations oprofile_ops;
  23. unsigned long oprofile_started;
  24. unsigned long oprofile_backtrace_depth;
  25. static unsigned long is_setup;
  26. static DEFINE_MUTEX(start_mutex);
  27. /* timer
  28. 0 - use performance monitoring hardware if available
  29. 1 - use the timer int mechanism regardless
  30. */
  31. static int timer = 0;
  32. int oprofile_setup(void)
  33. {
  34. int err;
  35. mutex_lock(&start_mutex);
  36. if ((err = alloc_cpu_buffers()))
  37. goto out;
  38. if ((err = alloc_event_buffer()))
  39. goto out1;
  40. if (oprofile_ops.setup && (err = oprofile_ops.setup()))
  41. goto out2;
  42. /* Note even though this starts part of the
  43. * profiling overhead, it's necessary to prevent
  44. * us missing task deaths and eventually oopsing
  45. * when trying to process the event buffer.
  46. */
  47. if (oprofile_ops.sync_start) {
  48. int sync_ret = oprofile_ops.sync_start();
  49. switch (sync_ret) {
  50. case 0:
  51. goto post_sync;
  52. case 1:
  53. goto do_generic;
  54. case -1:
  55. goto out3;
  56. default:
  57. goto out3;
  58. }
  59. }
  60. do_generic:
  61. if ((err = sync_start()))
  62. goto out3;
  63. post_sync:
  64. is_setup = 1;
  65. mutex_unlock(&start_mutex);
  66. return 0;
  67. out3:
  68. if (oprofile_ops.shutdown)
  69. oprofile_ops.shutdown();
  70. out2:
  71. free_event_buffer();
  72. out1:
  73. free_cpu_buffers();
  74. out:
  75. mutex_unlock(&start_mutex);
  76. return err;
  77. }
  78. #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
  79. static void switch_worker(struct work_struct *work);
  80. static DECLARE_DELAYED_WORK(switch_work, switch_worker);
  81. static void start_switch_worker(void)
  82. {
  83. if (oprofile_ops.switch_events)
  84. schedule_delayed_work(&switch_work, oprofile_time_slice);
  85. }
  86. static void stop_switch_worker(void)
  87. {
  88. cancel_delayed_work_sync(&switch_work);
  89. }
  90. static void switch_worker(struct work_struct *work)
  91. {
  92. if (oprofile_ops.switch_events())
  93. return;
  94. atomic_inc(&oprofile_stats.multiplex_counter);
  95. start_switch_worker();
  96. }
  97. /* User inputs in ms, converts to jiffies */
  98. int oprofile_set_timeout(unsigned long val_msec)
  99. {
  100. int err = 0;
  101. unsigned long time_slice;
  102. mutex_lock(&start_mutex);
  103. if (oprofile_started) {
  104. err = -EBUSY;
  105. goto out;
  106. }
  107. if (!oprofile_ops.switch_events) {
  108. err = -EINVAL;
  109. goto out;
  110. }
  111. time_slice = msecs_to_jiffies(val_msec);
  112. if (time_slice == MAX_JIFFY_OFFSET) {
  113. err = -EINVAL;
  114. goto out;
  115. }
  116. oprofile_time_slice = time_slice;
  117. out:
  118. mutex_unlock(&start_mutex);
  119. return err;
  120. }
  121. #else
  122. static inline void start_switch_worker(void) { }
  123. static inline void stop_switch_worker(void) { }
  124. #endif
  125. /* Actually start profiling (echo 1>/dev/oprofile/enable) */
  126. int oprofile_start(void)
  127. {
  128. int err = -EINVAL;
  129. mutex_lock(&start_mutex);
  130. if (!is_setup)
  131. goto out;
  132. err = 0;
  133. if (oprofile_started)
  134. goto out;
  135. oprofile_reset_stats();
  136. if ((err = oprofile_ops.start()))
  137. goto out;
  138. start_switch_worker();
  139. oprofile_started = 1;
  140. out:
  141. mutex_unlock(&start_mutex);
  142. return err;
  143. }
  144. /* echo 0>/dev/oprofile/enable */
  145. void oprofile_stop(void)
  146. {
  147. mutex_lock(&start_mutex);
  148. if (!oprofile_started)
  149. goto out;
  150. oprofile_ops.stop();
  151. oprofile_started = 0;
  152. stop_switch_worker();
  153. /* wake up the daemon to read what remains */
  154. wake_up_buffer_waiter();
  155. out:
  156. mutex_unlock(&start_mutex);
  157. }
  158. void oprofile_shutdown(void)
  159. {
  160. mutex_lock(&start_mutex);
  161. if (oprofile_ops.sync_stop) {
  162. int sync_ret = oprofile_ops.sync_stop();
  163. switch (sync_ret) {
  164. case 0:
  165. goto post_sync;
  166. case 1:
  167. goto do_generic;
  168. default:
  169. goto post_sync;
  170. }
  171. }
  172. do_generic:
  173. sync_stop();
  174. post_sync:
  175. if (oprofile_ops.shutdown)
  176. oprofile_ops.shutdown();
  177. is_setup = 0;
  178. free_event_buffer();
  179. free_cpu_buffers();
  180. mutex_unlock(&start_mutex);
  181. }
  182. int oprofile_set_ulong(unsigned long *addr, unsigned long val)
  183. {
  184. int err = -EBUSY;
  185. mutex_lock(&start_mutex);
  186. if (!oprofile_started) {
  187. *addr = val;
  188. err = 0;
  189. }
  190. mutex_unlock(&start_mutex);
  191. return err;
  192. }
  193. static int timer_mode;
  194. static int __init oprofile_init(void)
  195. {
  196. int err;
  197. /* always init architecture to setup backtrace support */
  198. err = oprofile_arch_init(&oprofile_ops);
  199. timer_mode = err || timer; /* fall back to timer mode on errors */
  200. if (timer_mode) {
  201. if (!err)
  202. oprofile_arch_exit();
  203. err = oprofile_timer_init(&oprofile_ops);
  204. if (err)
  205. return err;
  206. }
  207. err = oprofilefs_register();
  208. if (!err)
  209. return 0;
  210. /* failed */
  211. if (timer_mode)
  212. oprofile_timer_exit();
  213. else
  214. oprofile_arch_exit();
  215. return err;
  216. }
  217. static void __exit oprofile_exit(void)
  218. {
  219. oprofilefs_unregister();
  220. if (timer_mode)
  221. oprofile_timer_exit();
  222. else
  223. oprofile_arch_exit();
  224. }
  225. module_init(oprofile_init);
  226. module_exit(oprofile_exit);
  227. module_param_named(timer, timer, int, 0644);
  228. MODULE_PARM_DESC(timer, "force use of timer interrupt");
  229. MODULE_LICENSE("GPL");
  230. MODULE_AUTHOR("John Levon <levon@movementarian.org>");
  231. MODULE_DESCRIPTION("OProfile system profiler");