trace_functions_graph.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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_PRINT_OVERRUN 0x1
  15. static struct tracer_opt trace_opts[] = {
  16. /* Display overruns or not */
  17. { TRACER_OPT(overrun, TRACE_GRAPH_PRINT_OVERRUN) },
  18. { } /* Empty entry */
  19. };
  20. static struct tracer_flags tracer_flags = {
  21. .val = 0, /* Don't display overruns by default */
  22. .opts = trace_opts
  23. };
  24. static int graph_trace_init(struct trace_array *tr)
  25. {
  26. int cpu;
  27. for_each_online_cpu(cpu)
  28. tracing_reset(tr, cpu);
  29. return register_ftrace_graph(&trace_function_graph);
  30. }
  31. static void graph_trace_reset(struct trace_array *tr)
  32. {
  33. unregister_ftrace_graph();
  34. }
  35. enum print_line_t
  36. print_graph_function(struct trace_iterator *iter)
  37. {
  38. struct trace_seq *s = &iter->seq;
  39. struct trace_entry *entry = iter->ent;
  40. struct ftrace_graph_entry *field;
  41. int ret;
  42. if (entry->type == TRACE_FN_RET) {
  43. trace_assign_type(field, entry);
  44. ret = trace_seq_printf(s, "%pF -> ", (void *)field->parent_ip);
  45. if (!ret)
  46. return TRACE_TYPE_PARTIAL_LINE;
  47. ret = seq_print_ip_sym(s, field->ip,
  48. trace_flags & TRACE_ITER_SYM_MASK);
  49. if (!ret)
  50. return TRACE_TYPE_PARTIAL_LINE;
  51. ret = trace_seq_printf(s, " (%llu ns)",
  52. field->rettime - field->calltime);
  53. if (!ret)
  54. return TRACE_TYPE_PARTIAL_LINE;
  55. if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERRUN) {
  56. ret = trace_seq_printf(s, " (Overruns: %lu)",
  57. field->overrun);
  58. if (!ret)
  59. return TRACE_TYPE_PARTIAL_LINE;
  60. }
  61. ret = trace_seq_printf(s, "\n");
  62. if (!ret)
  63. return TRACE_TYPE_PARTIAL_LINE;
  64. return TRACE_TYPE_HANDLED;
  65. }
  66. return TRACE_TYPE_UNHANDLED;
  67. }
  68. static struct tracer graph_trace __read_mostly = {
  69. .name = "function-graph",
  70. .init = graph_trace_init,
  71. .reset = graph_trace_reset,
  72. .print_line = print_graph_function,
  73. .flags = &tracer_flags,
  74. };
  75. static __init int init_graph_trace(void)
  76. {
  77. return register_tracer(&graph_trace);
  78. }
  79. device_initcall(init_graph_trace);