trace_functions_graph.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. *
  3. * Function graph tracer.
  4. * Copyright (c) 2008 Frederic Weisbecker <fweisbec@gmail.com>
  5. * Mostly borrowed from function tracer which
  6. * is Copyright (c) Steven Rostedt <srostedt@redhat.com>
  7. *
  8. */
  9. #include <linux/debugfs.h>
  10. #include <linux/uaccess.h>
  11. #include <linux/ftrace.h>
  12. #include <linux/fs.h>
  13. #include "trace.h"
  14. #define TRACE_GRAPH_INDENT 2
  15. #define TRACE_GRAPH_PRINT_OVERRUN 0x1
  16. static struct tracer_opt trace_opts[] = {
  17. /* Display overruns or not */
  18. { TRACER_OPT(overrun, TRACE_GRAPH_PRINT_OVERRUN) },
  19. { } /* Empty entry */
  20. };
  21. static struct tracer_flags tracer_flags = {
  22. .val = 0, /* Don't display overruns by default */
  23. .opts = trace_opts
  24. };
  25. /* pid on the last trace processed */
  26. static pid_t last_pid = -1;
  27. static int graph_trace_init(struct trace_array *tr)
  28. {
  29. int cpu;
  30. for_each_online_cpu(cpu)
  31. tracing_reset(tr, cpu);
  32. return register_ftrace_graph(&trace_graph_return,
  33. &trace_graph_entry);
  34. }
  35. static void graph_trace_reset(struct trace_array *tr)
  36. {
  37. unregister_ftrace_graph();
  38. }
  39. /* If the pid changed since the last trace, output this event */
  40. static int verif_pid(struct trace_seq *s, pid_t pid)
  41. {
  42. if (last_pid != -1 && last_pid == pid)
  43. return 1;
  44. last_pid = pid;
  45. return trace_seq_printf(s, "\n------------8<---------- thread %d"
  46. " ------------8<----------\n\n",
  47. pid);
  48. }
  49. static enum print_line_t
  50. print_graph_entry(struct ftrace_graph_ent *call, struct trace_seq *s,
  51. struct trace_entry *ent)
  52. {
  53. int i;
  54. int ret;
  55. if (!verif_pid(s, ent->pid))
  56. return TRACE_TYPE_PARTIAL_LINE;
  57. for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
  58. ret = trace_seq_printf(s, " ");
  59. if (!ret)
  60. return TRACE_TYPE_PARTIAL_LINE;
  61. }
  62. ret = seq_print_ip_sym(s, call->func, 0);
  63. if (!ret)
  64. return TRACE_TYPE_PARTIAL_LINE;
  65. ret = trace_seq_printf(s, "() {\n");
  66. if (!ret)
  67. return TRACE_TYPE_PARTIAL_LINE;
  68. return TRACE_TYPE_HANDLED;
  69. }
  70. static enum print_line_t
  71. print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
  72. struct trace_entry *ent)
  73. {
  74. int i;
  75. int ret;
  76. if (!verif_pid(s, ent->pid))
  77. return TRACE_TYPE_PARTIAL_LINE;
  78. for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) {
  79. ret = trace_seq_printf(s, " ");
  80. if (!ret)
  81. return TRACE_TYPE_PARTIAL_LINE;
  82. }
  83. ret = trace_seq_printf(s, "} ");
  84. if (!ret)
  85. return TRACE_TYPE_PARTIAL_LINE;
  86. ret = trace_seq_printf(s, "%llu\n", trace->rettime - trace->calltime);
  87. if (!ret)
  88. return TRACE_TYPE_PARTIAL_LINE;
  89. if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) {
  90. ret = trace_seq_printf(s, " (Overruns: %lu)\n",
  91. trace->overrun);
  92. if (!ret)
  93. return TRACE_TYPE_PARTIAL_LINE;
  94. }
  95. return TRACE_TYPE_HANDLED;
  96. }
  97. enum print_line_t
  98. print_graph_function(struct trace_iterator *iter)
  99. {
  100. struct trace_seq *s = &iter->seq;
  101. struct trace_entry *entry = iter->ent;
  102. switch (entry->type) {
  103. case TRACE_GRAPH_ENT: {
  104. struct ftrace_graph_ent_entry *field;
  105. trace_assign_type(field, entry);
  106. return print_graph_entry(&field->graph_ent, s, entry);
  107. }
  108. case TRACE_GRAPH_RET: {
  109. struct ftrace_graph_ret_entry *field;
  110. trace_assign_type(field, entry);
  111. return print_graph_return(&field->ret, s, entry);
  112. }
  113. default:
  114. return TRACE_TYPE_UNHANDLED;
  115. }
  116. }
  117. static struct tracer graph_trace __read_mostly = {
  118. .name = "function-graph",
  119. .init = graph_trace_init,
  120. .reset = graph_trace_reset,
  121. .print_line = print_graph_function,
  122. .flags = &tracer_flags,
  123. };
  124. static __init int init_graph_trace(void)
  125. {
  126. return register_tracer(&graph_trace);
  127. }
  128. device_initcall(init_graph_trace);