trace_sched_switch.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * trace context switch
  4. *
  5. * Copyright (C) 2007 Steven Rostedt <[email protected]>
  6. *
  7. */
  8. #include <linux/module.h>
  9. #include <linux/kallsyms.h>
  10. #include <linux/uaccess.h>
  11. #include <linux/ftrace.h>
  12. #include <trace/events/sched.h>
  13. #include "trace.h"
  14. #define RECORD_CMDLINE 1
  15. #define RECORD_TGID 2
  16. static int sched_cmdline_ref;
  17. static int sched_tgid_ref;
  18. static DEFINE_MUTEX(sched_register_mutex);
  19. static void
  20. probe_sched_switch(void *ignore, bool preempt,
  21. struct task_struct *prev, struct task_struct *next,
  22. unsigned int prev_state)
  23. {
  24. int flags;
  25. flags = (RECORD_TGID * !!sched_tgid_ref) +
  26. (RECORD_CMDLINE * !!sched_cmdline_ref);
  27. if (!flags)
  28. return;
  29. tracing_record_taskinfo_sched_switch(prev, next, flags);
  30. }
  31. static void
  32. probe_sched_wakeup(void *ignore, struct task_struct *wakee)
  33. {
  34. int flags;
  35. flags = (RECORD_TGID * !!sched_tgid_ref) +
  36. (RECORD_CMDLINE * !!sched_cmdline_ref);
  37. if (!flags)
  38. return;
  39. tracing_record_taskinfo_sched_switch(current, wakee, flags);
  40. }
  41. static int tracing_sched_register(void)
  42. {
  43. int ret;
  44. ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
  45. if (ret) {
  46. pr_info("wakeup trace: Couldn't activate tracepoint"
  47. " probe to kernel_sched_wakeup\n");
  48. return ret;
  49. }
  50. ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
  51. if (ret) {
  52. pr_info("wakeup trace: Couldn't activate tracepoint"
  53. " probe to kernel_sched_wakeup_new\n");
  54. goto fail_deprobe;
  55. }
  56. ret = register_trace_sched_switch(probe_sched_switch, NULL);
  57. if (ret) {
  58. pr_info("sched trace: Couldn't activate tracepoint"
  59. " probe to kernel_sched_switch\n");
  60. goto fail_deprobe_wake_new;
  61. }
  62. return ret;
  63. fail_deprobe_wake_new:
  64. unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
  65. fail_deprobe:
  66. unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
  67. return ret;
  68. }
  69. static void tracing_sched_unregister(void)
  70. {
  71. unregister_trace_sched_switch(probe_sched_switch, NULL);
  72. unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
  73. unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
  74. }
  75. static void tracing_start_sched_switch(int ops)
  76. {
  77. bool sched_register;
  78. mutex_lock(&sched_register_mutex);
  79. sched_register = (!sched_cmdline_ref && !sched_tgid_ref);
  80. switch (ops) {
  81. case RECORD_CMDLINE:
  82. sched_cmdline_ref++;
  83. break;
  84. case RECORD_TGID:
  85. sched_tgid_ref++;
  86. break;
  87. }
  88. if (sched_register && (sched_cmdline_ref || sched_tgid_ref))
  89. tracing_sched_register();
  90. mutex_unlock(&sched_register_mutex);
  91. }
  92. static void tracing_stop_sched_switch(int ops)
  93. {
  94. mutex_lock(&sched_register_mutex);
  95. switch (ops) {
  96. case RECORD_CMDLINE:
  97. sched_cmdline_ref--;
  98. break;
  99. case RECORD_TGID:
  100. sched_tgid_ref--;
  101. break;
  102. }
  103. if (!sched_cmdline_ref && !sched_tgid_ref)
  104. tracing_sched_unregister();
  105. mutex_unlock(&sched_register_mutex);
  106. }
  107. void tracing_start_cmdline_record(void)
  108. {
  109. tracing_start_sched_switch(RECORD_CMDLINE);
  110. }
  111. void tracing_stop_cmdline_record(void)
  112. {
  113. tracing_stop_sched_switch(RECORD_CMDLINE);
  114. }
  115. void tracing_start_tgid_record(void)
  116. {
  117. tracing_start_sched_switch(RECORD_TGID);
  118. }
  119. void tracing_stop_tgid_record(void)
  120. {
  121. tracing_stop_sched_switch(RECORD_TGID);
  122. }