aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_functions_graph.c142
1 files changed, 93 insertions, 49 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index b958d60377b3..596a3ee43053 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -14,20 +14,25 @@
14#include "trace.h" 14#include "trace.h"
15 15
16#define TRACE_GRAPH_INDENT 2 16#define TRACE_GRAPH_INDENT 2
17/* Spaces between function call and time duration */
18#define TRACE_GRAPH_TIMESPACE_ENTRY " "
19/* Spaces between function call and closing braces */
20#define TRACE_GRAPH_TIMESPACE_RET " "
21 17
18/* Flag options */
22#define TRACE_GRAPH_PRINT_OVERRUN 0x1 19#define TRACE_GRAPH_PRINT_OVERRUN 0x1
20#define TRACE_GRAPH_PRINT_CPU 0x2
21#define TRACE_GRAPH_PRINT_OVERHEAD 0x4
22
23static struct tracer_opt trace_opts[] = { 23static struct tracer_opt trace_opts[] = {
24 /* Display overruns or not */ 24 /* Display overruns ? */
25 { TRACER_OPT(overrun, TRACE_GRAPH_PRINT_OVERRUN) }, 25 { TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
26 /* Display CPU ? */
27 { TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) },
28 /* Display Overhead ? */
29 { TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) },
26 { } /* Empty entry */ 30 { } /* Empty entry */
27}; 31};
28 32
29static struct tracer_flags tracer_flags = { 33static struct tracer_flags tracer_flags = {
30 .val = 0, /* Don't display overruns by default */ 34 /* Don't display overruns by default */
35 .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD,
31 .opts = trace_opts 36 .opts = trace_opts
32}; 37};
33 38
@@ -56,6 +61,36 @@ static void graph_trace_reset(struct trace_array *tr)
56 unregister_ftrace_graph(); 61 unregister_ftrace_graph();
57} 62}
58 63
64static inline int log10_cpu(int nb)
65{
66 if (nb / 100)
67 return 3;
68 if (nb / 10)
69 return 2;
70 return 1;
71}
72
73static enum print_line_t
74print_graph_cpu(struct trace_seq *s, int cpu)
75{
76 int i;
77 int ret;
78 int log10_this = log10_cpu(cpu);
79 int log10_all = log10_cpu(cpus_weight_nr(cpu_online_map));
80
81
82 for (i = 0; i < log10_all - log10_this; i++) {
83 ret = trace_seq_printf(s, " ");
84 if (!ret)
85 return TRACE_TYPE_PARTIAL_LINE;
86 }
87 ret = trace_seq_printf(s, "%d) ", cpu);
88 if (!ret)
89 return TRACE_TYPE_PARTIAL_LINE;
90 return TRACE_TYPE_HANDLED;
91}
92
93
59/* If the pid changed since the last trace, output this event */ 94/* If the pid changed since the last trace, output this event */
60static int verif_pid(struct trace_seq *s, pid_t pid, int cpu) 95static int verif_pid(struct trace_seq *s, pid_t pid, int cpu)
61{ 96{
@@ -67,8 +102,7 @@ static int verif_pid(struct trace_seq *s, pid_t pid, int cpu)
67 last_pid[cpu] = pid; 102 last_pid[cpu] = pid;
68 comm = trace_find_cmdline(pid); 103 comm = trace_find_cmdline(pid);
69 104
70 return trace_seq_printf(s, "\nCPU[%03d] " 105 return trace_seq_printf(s, "\n------------8<---------- thread %s-%d"
71 " ------------8<---------- thread %s-%d"
72 " ------------8<----------\n\n", 106 " ------------8<----------\n\n",
73 cpu, comm, pid); 107 cpu, comm, pid);
74} 108}
@@ -86,7 +120,7 @@ trace_branch_is_leaf(struct trace_iterator *iter,
86 if (!ring_iter) 120 if (!ring_iter)
87 return false; 121 return false;
88 122
89 event = ring_buffer_iter_peek(iter->buffer_iter[iter->cpu], NULL); 123 event = ring_buffer_iter_peek(ring_iter, NULL);
90 124
91 if (!event) 125 if (!event)
92 return false; 126 return false;
@@ -108,7 +142,7 @@ static inline int
108print_graph_duration(unsigned long long duration, struct trace_seq *s) 142print_graph_duration(unsigned long long duration, struct trace_seq *s)
109{ 143{
110 unsigned long nsecs_rem = do_div(duration, 1000); 144 unsigned long nsecs_rem = do_div(duration, 1000);
111 return trace_seq_printf(s, "+ %llu.%lu us\n", duration, nsecs_rem); 145 return trace_seq_printf(s, "%4llu.%3lu us | ", duration, nsecs_rem);
112} 146}
113 147
114/* Signal a overhead of time execution to the output */ 148/* Signal a overhead of time execution to the output */
@@ -136,8 +170,8 @@ print_graph_entry_leaf(struct trace_iterator *iter,
136 struct ring_buffer_event *event; 170 struct ring_buffer_event *event;
137 struct ftrace_graph_ent *call; 171 struct ftrace_graph_ent *call;
138 unsigned long long duration; 172 unsigned long long duration;
139 int i;
140 int ret; 173 int ret;
174 int i;
141 175
142 event = ring_buffer_read(iter->buffer_iter[iter->cpu], NULL); 176 event = ring_buffer_read(iter->buffer_iter[iter->cpu], NULL);
143 ret_entry = ring_buffer_event_data(event); 177 ret_entry = ring_buffer_event_data(event);
@@ -145,8 +179,19 @@ print_graph_entry_leaf(struct trace_iterator *iter,
145 call = &entry->graph_ent; 179 call = &entry->graph_ent;
146 duration = graph_ret->rettime - graph_ret->calltime; 180 duration = graph_ret->rettime - graph_ret->calltime;
147 181
182 /* Must not exceed 8 characters: 9999.999 us */
183 if (duration > 10000000ULL)
184 duration = 9999999ULL;
185
148 /* Overhead */ 186 /* Overhead */
149 ret = print_graph_overhead(duration, s); 187 if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
188 ret = print_graph_overhead(duration, s);
189 if (!ret)
190 return TRACE_TYPE_PARTIAL_LINE;
191 }
192
193 /* Duration */
194 ret = print_graph_duration(duration, s);
150 if (!ret) 195 if (!ret)
151 return TRACE_TYPE_PARTIAL_LINE; 196 return TRACE_TYPE_PARTIAL_LINE;
152 197
@@ -161,16 +206,7 @@ print_graph_entry_leaf(struct trace_iterator *iter,
161 if (!ret) 206 if (!ret)
162 return TRACE_TYPE_PARTIAL_LINE; 207 return TRACE_TYPE_PARTIAL_LINE;
163 208
164 ret = trace_seq_printf(s, "();"); 209 ret = trace_seq_printf(s, "();\n");
165 if (!ret)
166 return TRACE_TYPE_PARTIAL_LINE;
167
168 /* Duration */
169 ret = trace_seq_printf(s, TRACE_GRAPH_TIMESPACE_ENTRY);
170 if (!ret)
171 return TRACE_TYPE_PARTIAL_LINE;
172
173 ret = print_graph_duration(duration, s);
174 if (!ret) 210 if (!ret)
175 return TRACE_TYPE_PARTIAL_LINE; 211 return TRACE_TYPE_PARTIAL_LINE;
176 212
@@ -186,9 +222,14 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
186 struct ftrace_graph_ent *call = &entry->graph_ent; 222 struct ftrace_graph_ent *call = &entry->graph_ent;
187 223
188 /* No overhead */ 224 /* No overhead */
189 ret = trace_seq_printf(s, " "); 225 if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
190 if (!ret) 226 ret = trace_seq_printf(s, " ");
191 return TRACE_TYPE_PARTIAL_LINE; 227 if (!ret)
228 return TRACE_TYPE_PARTIAL_LINE;
229 }
230
231 /* No time */
232 ret = trace_seq_printf(s, " | ");
192 233
193 /* Function */ 234 /* Function */
194 for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) { 235 for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
@@ -201,12 +242,7 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
201 if (!ret) 242 if (!ret)
202 return TRACE_TYPE_PARTIAL_LINE; 243 return TRACE_TYPE_PARTIAL_LINE;
203 244
204 ret = trace_seq_printf(s, "() {"); 245 ret = trace_seq_printf(s, "() {\n");
205 if (!ret)
206 return TRACE_TYPE_PARTIAL_LINE;
207
208 /* No duration to print at this state */
209 ret = trace_seq_printf(s, TRACE_GRAPH_TIMESPACE_ENTRY "-\n");
210 if (!ret) 246 if (!ret)
211 return TRACE_TYPE_PARTIAL_LINE; 247 return TRACE_TYPE_PARTIAL_LINE;
212 248
@@ -220,12 +256,16 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
220 int ret; 256 int ret;
221 struct trace_entry *ent = iter->ent; 257 struct trace_entry *ent = iter->ent;
222 258
259 /* Pid */
223 if (!verif_pid(s, ent->pid, cpu)) 260 if (!verif_pid(s, ent->pid, cpu))
224 return TRACE_TYPE_PARTIAL_LINE; 261 return TRACE_TYPE_PARTIAL_LINE;
225 262
226 ret = trace_seq_printf(s, "CPU[%03d] ", cpu); 263 /* Cpu */
227 if (!ret) 264 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
228 return TRACE_TYPE_PARTIAL_LINE; 265 ret = print_graph_cpu(s, cpu);
266 if (!ret)
267 return TRACE_TYPE_PARTIAL_LINE;
268 }
229 269
230 if (trace_branch_is_leaf(iter, field)) 270 if (trace_branch_is_leaf(iter, field))
231 return print_graph_entry_leaf(iter, field, s); 271 return print_graph_entry_leaf(iter, field, s);
@@ -242,17 +282,30 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
242 int ret; 282 int ret;
243 unsigned long long duration = trace->rettime - trace->calltime; 283 unsigned long long duration = trace->rettime - trace->calltime;
244 284
285 /* Must not exceed 8 characters: xxxx.yyy us */
286 if (duration > 10000000ULL)
287 duration = 9999999ULL;
288
245 /* Pid */ 289 /* Pid */
246 if (!verif_pid(s, ent->pid, cpu)) 290 if (!verif_pid(s, ent->pid, cpu))
247 return TRACE_TYPE_PARTIAL_LINE; 291 return TRACE_TYPE_PARTIAL_LINE;
248 292
249 /* Cpu */ 293 /* Cpu */
250 ret = trace_seq_printf(s, "CPU[%03d] ", cpu); 294 if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
251 if (!ret) 295 ret = print_graph_cpu(s, cpu);
252 return TRACE_TYPE_PARTIAL_LINE; 296 if (!ret)
297 return TRACE_TYPE_PARTIAL_LINE;
298 }
253 299
254 /* Overhead */ 300 /* Overhead */
255 ret = print_graph_overhead(duration, s); 301 if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
302 ret = print_graph_overhead(duration, s);
303 if (!ret)
304 return TRACE_TYPE_PARTIAL_LINE;
305 }
306
307 /* Duration */
308 ret = print_graph_duration(duration, s);
256 if (!ret) 309 if (!ret)
257 return TRACE_TYPE_PARTIAL_LINE; 310 return TRACE_TYPE_PARTIAL_LINE;
258 311
@@ -263,16 +316,7 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
263 return TRACE_TYPE_PARTIAL_LINE; 316 return TRACE_TYPE_PARTIAL_LINE;
264 } 317 }
265 318
266 ret = trace_seq_printf(s, "} "); 319 ret = trace_seq_printf(s, "}\n");
267 if (!ret)
268 return TRACE_TYPE_PARTIAL_LINE;
269
270 /* Duration */
271 ret = trace_seq_printf(s, TRACE_GRAPH_TIMESPACE_RET);
272 if (!ret)
273 return TRACE_TYPE_PARTIAL_LINE;
274
275 ret = print_graph_duration(duration, s);
276 if (!ret) 320 if (!ret)
277 return TRACE_TYPE_PARTIAL_LINE; 321 return TRACE_TYPE_PARTIAL_LINE;
278 322