diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2008-12-02 20:30:37 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-12-03 03:09:41 -0500 |
commit | 11e84acc400921743cc8d488e4a265cd98a655c7 (patch) | |
tree | 3f252d74a4d474eef1db73c7c6c947159aec3aee /kernel/trace/trace_functions_graph.c | |
parent | 62679efe0a5f02987a621942afc5979a80a6ca5a (diff) |
tracing/function-graph-tracer: display unified style cmdline and pid
Impact: extend function-graph output: let one know which thread called a function
This patch implements a helper function to print the couple cmdline/pid.
Its output is provided during task switching and on each row if the new
"funcgraph-proc" defualt-off option is set through trace_options file.
The output is center aligned and never exceeds 14 characters. The cmdline
is truncated over 7 chars.
But note that if the pid exceeds 6 characters, the column will overflow (but
the situation is abnormal).
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_functions_graph.c')
-rw-r--r-- | kernel/trace/trace_functions_graph.c | 113 |
1 files changed, 99 insertions, 14 deletions
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c index 894b50bca313..23e19d2dbd06 100644 --- a/kernel/trace/trace_functions_graph.c +++ b/kernel/trace/trace_functions_graph.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #define TRACE_GRAPH_PRINT_OVERRUN 0x1 | 19 | #define TRACE_GRAPH_PRINT_OVERRUN 0x1 |
20 | #define TRACE_GRAPH_PRINT_CPU 0x2 | 20 | #define TRACE_GRAPH_PRINT_CPU 0x2 |
21 | #define TRACE_GRAPH_PRINT_OVERHEAD 0x4 | 21 | #define TRACE_GRAPH_PRINT_OVERHEAD 0x4 |
22 | #define TRACE_GRAPH_PRINT_PROC 0x8 | ||
22 | 23 | ||
23 | static struct tracer_opt trace_opts[] = { | 24 | static struct tracer_opt trace_opts[] = { |
24 | /* Display overruns ? */ | 25 | /* Display overruns ? */ |
@@ -27,11 +28,13 @@ static struct tracer_opt trace_opts[] = { | |||
27 | { TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) }, | 28 | { TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) }, |
28 | /* Display Overhead ? */ | 29 | /* Display Overhead ? */ |
29 | { TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) }, | 30 | { TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) }, |
31 | /* Display proc name/pid */ | ||
32 | { TRACER_OPT(funcgraph-proc, TRACE_GRAPH_PRINT_PROC) }, | ||
30 | { } /* Empty entry */ | 33 | { } /* Empty entry */ |
31 | }; | 34 | }; |
32 | 35 | ||
33 | static struct tracer_flags tracer_flags = { | 36 | static struct tracer_flags tracer_flags = { |
34 | /* Don't display overruns by default */ | 37 | /* Don't display overruns and proc by default */ |
35 | .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD, | 38 | .val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD, |
36 | .opts = trace_opts | 39 | .opts = trace_opts |
37 | }; | 40 | }; |
@@ -104,23 +107,63 @@ print_graph_cpu(struct trace_seq *s, int cpu) | |||
104 | return TRACE_TYPE_HANDLED; | 107 | return TRACE_TYPE_HANDLED; |
105 | } | 108 | } |
106 | 109 | ||
110 | #define TRACE_GRAPH_PROCINFO_LENGTH 14 | ||
111 | |||
112 | static enum print_line_t | ||
113 | print_graph_proc(struct trace_seq *s, pid_t pid) | ||
114 | { | ||
115 | int i; | ||
116 | int ret; | ||
117 | int len; | ||
118 | char comm[8]; | ||
119 | int spaces = 0; | ||
120 | /* sign + log10(MAX_INT) + '\0' */ | ||
121 | char pid_str[11]; | ||
122 | |||
123 | strncpy(comm, trace_find_cmdline(pid), 7); | ||
124 | comm[7] = '\0'; | ||
125 | sprintf(pid_str, "%d", pid); | ||
126 | |||
127 | /* 1 stands for the "-" character */ | ||
128 | len = strlen(comm) + strlen(pid_str) + 1; | ||
129 | |||
130 | if (len < TRACE_GRAPH_PROCINFO_LENGTH) | ||
131 | spaces = TRACE_GRAPH_PROCINFO_LENGTH - len; | ||
132 | |||
133 | /* First spaces to align center */ | ||
134 | for (i = 0; i < spaces / 2; i++) { | ||
135 | ret = trace_seq_printf(s, " "); | ||
136 | if (!ret) | ||
137 | return TRACE_TYPE_PARTIAL_LINE; | ||
138 | } | ||
139 | |||
140 | ret = trace_seq_printf(s, "%s-%s", comm, pid_str); | ||
141 | if (!ret) | ||
142 | return TRACE_TYPE_PARTIAL_LINE; | ||
143 | |||
144 | /* Last spaces to align center */ | ||
145 | for (i = 0; i < spaces - (spaces / 2); i++) { | ||
146 | ret = trace_seq_printf(s, " "); | ||
147 | if (!ret) | ||
148 | return TRACE_TYPE_PARTIAL_LINE; | ||
149 | } | ||
150 | return TRACE_TYPE_HANDLED; | ||
151 | } | ||
152 | |||
107 | 153 | ||
108 | /* If the pid changed since the last trace, output this event */ | 154 | /* If the pid changed since the last trace, output this event */ |
109 | static int verif_pid(struct trace_seq *s, pid_t pid, int cpu) | 155 | static enum print_line_t |
156 | verif_pid(struct trace_seq *s, pid_t pid, int cpu) | ||
110 | { | 157 | { |
111 | char *comm, *prev_comm; | ||
112 | pid_t prev_pid; | 158 | pid_t prev_pid; |
113 | int ret; | 159 | int ret; |
114 | 160 | ||
115 | if (last_pid[cpu] != -1 && last_pid[cpu] == pid) | 161 | if (last_pid[cpu] != -1 && last_pid[cpu] == pid) |
116 | return 1; | 162 | return TRACE_TYPE_HANDLED; |
117 | 163 | ||
118 | prev_pid = last_pid[cpu]; | 164 | prev_pid = last_pid[cpu]; |
119 | last_pid[cpu] = pid; | 165 | last_pid[cpu] = pid; |
120 | 166 | ||
121 | comm = trace_find_cmdline(pid); | ||
122 | prev_comm = trace_find_cmdline(prev_pid); | ||
123 | |||
124 | /* | 167 | /* |
125 | * Context-switch trace line: | 168 | * Context-switch trace line: |
126 | 169 | ||
@@ -130,11 +173,31 @@ static int verif_pid(struct trace_seq *s, pid_t pid, int cpu) | |||
130 | 173 | ||
131 | */ | 174 | */ |
132 | ret = trace_seq_printf(s, | 175 | ret = trace_seq_printf(s, |
133 | " ------------------------------------------\n"); | 176 | "\n ------------------------------------------\n |"); |
134 | ret += trace_seq_printf(s, " | %d) %s-%d => %s-%d\n", | 177 | if (!ret) |
135 | cpu, prev_comm, prev_pid, comm, pid); | 178 | TRACE_TYPE_PARTIAL_LINE; |
136 | ret += trace_seq_printf(s, | 179 | |
137 | " ------------------------------------------\n\n"); | 180 | ret = print_graph_cpu(s, cpu); |
181 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
182 | TRACE_TYPE_PARTIAL_LINE; | ||
183 | |||
184 | ret = print_graph_proc(s, prev_pid); | ||
185 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
186 | TRACE_TYPE_PARTIAL_LINE; | ||
187 | |||
188 | ret = trace_seq_printf(s, " => "); | ||
189 | if (!ret) | ||
190 | TRACE_TYPE_PARTIAL_LINE; | ||
191 | |||
192 | ret = print_graph_proc(s, pid); | ||
193 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
194 | TRACE_TYPE_PARTIAL_LINE; | ||
195 | |||
196 | ret = trace_seq_printf(s, | ||
197 | "\n ------------------------------------------\n\n"); | ||
198 | if (!ret) | ||
199 | TRACE_TYPE_PARTIAL_LINE; | ||
200 | |||
138 | return ret; | 201 | return ret; |
139 | } | 202 | } |
140 | 203 | ||
@@ -288,12 +351,23 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s, | |||
288 | struct trace_entry *ent = iter->ent; | 351 | struct trace_entry *ent = iter->ent; |
289 | 352 | ||
290 | /* Pid */ | 353 | /* Pid */ |
291 | if (!verif_pid(s, ent->pid, cpu)) | 354 | if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE) |
292 | return TRACE_TYPE_PARTIAL_LINE; | 355 | return TRACE_TYPE_PARTIAL_LINE; |
293 | 356 | ||
294 | /* Cpu */ | 357 | /* Cpu */ |
295 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { | 358 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { |
296 | ret = print_graph_cpu(s, cpu); | 359 | ret = print_graph_cpu(s, cpu); |
360 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
361 | return TRACE_TYPE_PARTIAL_LINE; | ||
362 | } | ||
363 | |||
364 | /* Proc */ | ||
365 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { | ||
366 | ret = print_graph_proc(s, ent->pid); | ||
367 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
368 | return TRACE_TYPE_PARTIAL_LINE; | ||
369 | |||
370 | ret = trace_seq_printf(s, " | "); | ||
297 | if (!ret) | 371 | if (!ret) |
298 | return TRACE_TYPE_PARTIAL_LINE; | 372 | return TRACE_TYPE_PARTIAL_LINE; |
299 | } | 373 | } |
@@ -318,12 +392,23 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s, | |||
318 | duration = 9999999ULL; | 392 | duration = 9999999ULL; |
319 | 393 | ||
320 | /* Pid */ | 394 | /* Pid */ |
321 | if (!verif_pid(s, ent->pid, cpu)) | 395 | if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE) |
322 | return TRACE_TYPE_PARTIAL_LINE; | 396 | return TRACE_TYPE_PARTIAL_LINE; |
323 | 397 | ||
324 | /* Cpu */ | 398 | /* Cpu */ |
325 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { | 399 | if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) { |
326 | ret = print_graph_cpu(s, cpu); | 400 | ret = print_graph_cpu(s, cpu); |
401 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
402 | return TRACE_TYPE_PARTIAL_LINE; | ||
403 | } | ||
404 | |||
405 | /* Proc */ | ||
406 | if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) { | ||
407 | ret = print_graph_proc(s, ent->pid); | ||
408 | if (ret == TRACE_TYPE_PARTIAL_LINE) | ||
409 | return TRACE_TYPE_PARTIAL_LINE; | ||
410 | |||
411 | ret = trace_seq_printf(s, " | "); | ||
327 | if (!ret) | 412 | if (!ret) |
328 | return TRACE_TYPE_PARTIAL_LINE; | 413 | return TRACE_TYPE_PARTIAL_LINE; |
329 | } | 414 | } |