trace_functions_graph.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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, ret;
  30. for_each_online_cpu(cpu)
  31. tracing_reset(tr, cpu);
  32. ret = register_ftrace_graph(&trace_graph_return,
  33. &trace_graph_entry);
  34. if (ret)
  35. return ret;
  36. tracing_start_cmdline_record();
  37. return 0;
  38. }
  39. static void graph_trace_reset(struct trace_array *tr)
  40. {
  41. tracing_stop_cmdline_record();
  42. unregister_ftrace_graph();
  43. }
  44. /* If the pid changed since the last trace, output this event */
  45. static int verif_pid(struct trace_seq *s, pid_t pid)
  46. {
  47. char *comm;
  48. if (last_pid != -1 && last_pid == pid)
  49. return 1;
  50. last_pid = pid;
  51. comm = trace_find_cmdline(pid);
  52. return trace_seq_printf(s, "\n------------8<---------- thread %s-%d"
  53. " ------------8<----------\n\n",
  54. comm, pid);
  55. }
  56. static enum print_line_t
  57. print_graph_entry(struct ftrace_graph_ent *call, struct trace_seq *s,
  58. struct trace_entry *ent)
  59. {
  60. int i;
  61. int ret;
  62. if (!verif_pid(s, ent->pid))
  63. return TRACE_TYPE_PARTIAL_LINE;
  64. for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
  65. ret = trace_seq_printf(s, " ");
  66. if (!ret)
  67. return TRACE_TYPE_PARTIAL_LINE;
  68. }
  69. ret = seq_print_ip_sym(s, call->func, 0);
  70. if (!ret)
  71. return TRACE_TYPE_PARTIAL_LINE;
  72. ret = trace_seq_printf(s, "() {\n");
  73. if (!ret)
  74. return TRACE_TYPE_PARTIAL_LINE;
  75. return TRACE_TYPE_HANDLED;
  76. }
  77. static enum print_line_t
  78. print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
  79. struct trace_entry *ent)
  80. {
  81. int i;
  82. int ret;
  83. if (!verif_pid(s, ent->pid))
  84. return TRACE_TYPE_PARTIAL_LINE;
  85. for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) {
  86. ret = trace_seq_printf(s, " ");
  87. if (!ret)
  88. return TRACE_TYPE_PARTIAL_LINE;
  89. }
  90. ret = trace_seq_printf(s, "} ");
  91. if (!ret)
  92. return TRACE_TYPE_PARTIAL_LINE;
  93. ret = trace_seq_printf(s, "%llu\n", trace->rettime - trace->calltime);
  94. if (!ret)
  95. return TRACE_TYPE_PARTIAL_LINE;
  96. if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) {
  97. ret = trace_seq_printf(s, " (Overruns: %lu)\n",
  98. trace->overrun);
  99. if (!ret)
  100. return TRACE_TYPE_PARTIAL_LINE;
  101. }
  102. return TRACE_TYPE_HANDLED;
  103. }
  104. enum print_line_t
  105. print_graph_function(struct trace_iterator *iter)
  106. {
  107. struct trace_seq *s = &iter->seq;
  108. struct trace_entry *entry = iter->ent;
  109. switch (entry->type) {
  110. case TRACE_GRAPH_ENT: {
  111. struct ftrace_graph_ent_entry *field;
  112. trace_assign_type(field, entry);
  113. return print_graph_entry(&field->graph_ent, s, entry);
  114. }
  115. case TRACE_GRAPH_RET: {
  116. struct ftrace_graph_ret_entry *field;
  117. trace_assign_type(field, entry);
  118. return print_graph_return(&field->ret, s, entry);
  119. }
  120. default:
  121. return TRACE_TYPE_UNHANDLED;
  122. }
  123. }
  124. static struct tracer graph_trace __read_mostly = {
  125. .name = "function-graph",
  126. .init = graph_trace_init,
  127. .reset = graph_trace_reset,
  128. .print_line = print_graph_function,
  129. .flags = &tracer_flags,
  130. };
  131. static __init int init_graph_trace(void)
  132. {
  133. return register_tracer(&graph_trace);
  134. }
  135. device_initcall(init_graph_trace);