1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2013 Red Hat Inc, Steven Rostedt <[email protected]>
4 *
5 * Several of the ideas in this file came from Arnaldo Carvalho de Melo's
6 * work on the perf ui.
7 */
8 #define _LARGEFILE64_SOURCE
9 #include <dirent.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <getopt.h>
14 #include <signal.h>
15
16 #include "trace-hash-local.h"
17 #include "trace-local.h"
18 #include "list.h"
19
20 static int sched_wakeup_type;
21 static int sched_wakeup_new_type;
22 static int sched_switch_type;
23 static int function_type;
24 static int function_graph_entry_type;
25 static int function_graph_exit_type;
26 static int kernel_stack_type;
27
28 static int long_size;
29
30 static struct tep_format_field *common_type_hist;
31 static struct tep_format_field *common_pid_field;
32 static struct tep_format_field *sched_wakeup_comm_field;
33 static struct tep_format_field *sched_wakeup_new_comm_field;
34 static struct tep_format_field *sched_wakeup_pid_field;
35 static struct tep_format_field *sched_wakeup_new_pid_field;
36 static struct tep_format_field *sched_switch_prev_field;
37 static struct tep_format_field *sched_switch_next_field;
38 static struct tep_format_field *sched_switch_prev_pid_field;
39 static struct tep_format_field *sched_switch_next_pid_field;
40 static struct tep_format_field *function_ip_field;
41 static struct tep_format_field *function_parent_ip_field;
42 static struct tep_format_field *function_graph_entry_func_field;
43 static struct tep_format_field *function_graph_entry_depth_field;
44 static struct tep_format_field *function_graph_exit_func_field;
45 static struct tep_format_field *function_graph_exit_depth_field;
46 static struct tep_format_field *function_graph_exit_calltime_field;
47 static struct tep_format_field *function_graph_exit_rettime_field;
48 static struct tep_format_field *function_graph_exit_overrun_field;
49 static struct tep_format_field *kernel_stack_caller_field;
50
51 static int compact;
52
zalloc(size_t size)53 static void *zalloc(size_t size)
54 {
55 return calloc(1, size);
56 }
57
58 static const char **ips;
59 static int ips_idx;
60 static int func_depth;
61 static int current_pid = -1;
62
63 struct stack_save {
64 struct stack_save *next;
65 const char **ips;
66 int ips_idx;
67 int func_depth;
68 int pid;
69 };
70
71 struct stack_save *saved_stacks;
72
reset_stack(void)73 static void reset_stack(void)
74 {
75 current_pid = -1;
76 ips_idx = 0;
77 func_depth = 0;
78 /* Don't free here, it may be saved */
79 ips = NULL;
80 }
81
save_stack(void)82 static void save_stack(void)
83 {
84 struct stack_save *stack;
85
86 stack = zalloc(sizeof(*stack));
87 if (!stack)
88 die("malloc");
89
90 stack->pid = current_pid;
91 stack->ips_idx = ips_idx;
92 stack->func_depth = func_depth;
93 stack->ips = ips;
94
95 stack->next = saved_stacks;
96 saved_stacks = stack;
97
98 reset_stack();
99 }
100
restore_stack(int pid)101 static void restore_stack(int pid)
102 {
103 struct stack_save *last = NULL, *stack;
104
105 for (stack = saved_stacks; stack; last = stack, stack = stack->next) {
106 if (stack->pid == pid)
107 break;
108 }
109
110 if (!stack)
111 return;
112
113 if (last)
114 last->next = stack->next;
115 else
116 saved_stacks = stack->next;
117
118 current_pid = stack->pid;
119 ips_idx = stack->ips_idx;
120 func_depth = stack->func_depth;
121 free(ips);
122 ips = stack->ips;
123 free(stack);
124 }
125
126 struct pid_list;
127
128 struct chain {
129 struct chain *next;
130 struct chain *sibling;
131 const char *func;
132 struct chain *parents;
133 struct pid_list *pid_list;
134 int nr_parents;
135 int count;
136 int total;
137 int event;
138 };
139 static struct chain *chains;
140 static int nr_chains;
141 static int total_counts;
142
143 struct pid_list {
144 struct pid_list *next;
145 struct chain chain;
146 int pid;
147 };
148 static struct pid_list *list_pids;
149 static struct pid_list all_pid_list;
150
add_chain(struct chain * chain)151 static void add_chain(struct chain *chain)
152 {
153 if (chain->next)
154 die("chain not null?");
155 chain->next = chains;
156 chains = chain;
157 nr_chains++;
158 }
159
160 static void
insert_chain(struct pid_list * pid_list,struct chain * chain_list,const char ** chain_str,int size,int event)161 insert_chain(struct pid_list *pid_list, struct chain *chain_list,
162 const char **chain_str, int size, int event)
163 {
164 struct chain *chain;
165
166 /* Record all counts */
167 if (!chain_list->func)
168 total_counts++;
169
170 chain_list->count++;
171
172 if (!size--)
173 return;
174
175 for (chain = chain_list->parents; chain; chain = chain->sibling) {
176 if (chain->func == chain_str[size]) {
177 insert_chain(pid_list, chain, chain_str, size, 0);
178 return;
179 }
180 }
181
182 chain_list->nr_parents++;
183 chain = zalloc(sizeof(struct chain));
184 if (!chain)
185 die("malloc");
186 chain->sibling = chain_list->parents;
187 chain_list->parents = chain;
188 chain->func = chain_str[size];
189 chain->pid_list = pid_list;
190 chain->event = event;
191
192 /* NULL func means this is the top level of the chain. Store it */
193 if (!chain_list->func)
194 add_chain(chain);
195
196 insert_chain(pid_list, chain, chain_str, size, 0);
197 }
198
save_call_chain(int pid,const char ** chain,int size,int event)199 static void save_call_chain(int pid, const char **chain, int size, int event)
200 {
201 static struct pid_list *pid_list;
202
203 if (compact)
204 pid_list = &all_pid_list;
205
206 else if (!pid_list || pid_list->pid != pid) {
207 for (pid_list = list_pids; pid_list; pid_list = pid_list->next) {
208 if (pid_list->pid == pid)
209 break;
210 }
211 if (!pid_list) {
212 pid_list = zalloc(sizeof(*pid_list));
213 if (!pid_list)
214 die("malloc");
215 pid_list->pid = pid;
216 pid_list->next = list_pids;
217 list_pids = pid_list;
218 }
219 }
220 insert_chain(pid_list, &pid_list->chain, chain, size, event);
221 }
222
save_stored_stacks(void)223 static void save_stored_stacks(void)
224 {
225 while (saved_stacks) {
226 restore_stack(saved_stacks->pid);
227 save_call_chain(current_pid, ips, ips_idx, 0);
228 }
229 }
230
flush_stack(void)231 static void flush_stack(void)
232 {
233 if (current_pid < 0)
234 return;
235
236 save_call_chain(current_pid, ips, ips_idx, 0);
237 free(ips);
238 reset_stack();
239 }
240
push_stack_func(const char * func)241 static void push_stack_func(const char *func)
242 {
243 ips_idx++;
244 ips = realloc(ips, ips_idx * sizeof(char *));
245 ips[ips_idx - 1] = func;
246 }
247
pop_stack_func(void)248 static void pop_stack_func(void)
249 {
250 ips_idx--;
251 ips[ips_idx] = NULL;
252 }
253
254 static void
process_function(struct tep_handle * pevent,struct tep_record * record)255 process_function(struct tep_handle *pevent, struct tep_record *record)
256 {
257 unsigned long long parent_ip;
258 unsigned long long ip;
259 unsigned long long val;
260 const char *parent;
261 const char *func;
262 int pid;
263 int ret;
264
265 ret = tep_read_number_field(common_pid_field, record->data, &val);
266 if (ret < 0)
267 die("no pid field for function?");
268
269 ret = tep_read_number_field(function_ip_field, record->data, &ip);
270 if (ret < 0)
271 die("no ip field for function?");
272
273 ret = tep_read_number_field(function_parent_ip_field, record->data, &parent_ip);
274 if (ret < 0)
275 die("no parent ip field for function?");
276
277 pid = val;
278
279 func = tep_find_function(pevent, ip);
280 parent = tep_find_function(pevent, parent_ip);
281
282 if (current_pid >= 0 && pid != current_pid) {
283 save_stack();
284 restore_stack(pid);
285 }
286
287 current_pid = pid;
288
289 if (ips_idx) {
290 if (ips[ips_idx - 1] == parent)
291 push_stack_func(func);
292 else {
293 save_call_chain(pid, ips, ips_idx, 0);
294 while (ips_idx) {
295 pop_stack_func();
296 if (ips[ips_idx - 1] == parent) {
297 push_stack_func(func);
298 break;
299 }
300 }
301 }
302 }
303
304 /* The above check can set ips_idx to zero again */
305 if (!ips_idx) {
306 push_stack_func(parent);
307 push_stack_func(func);
308 }
309 }
310
311 static void
process_function_graph_entry(struct tep_handle * pevent,struct tep_record * record)312 process_function_graph_entry(struct tep_handle *pevent, struct tep_record *record)
313 {
314 unsigned long long depth;
315 unsigned long long ip;
316 unsigned long long val;
317 const char *func;
318 int pid;
319 int ret;
320
321 ret = tep_read_number_field(common_pid_field, record->data, &val);
322 if (ret < 0)
323 die("no pid field for function graph entry?");
324
325 ret = tep_read_number_field(function_graph_entry_func_field,
326 record->data, &ip);
327 if (ret < 0)
328 die("no ip field for function graph entry?");
329
330 ret = tep_read_number_field(function_graph_entry_depth_field,
331 record->data, &depth);
332 if (ret < 0)
333 die("no parent ip field for function entry?");
334
335 pid = val;
336
337 func = tep_find_function(pevent, ip);
338
339 if (current_pid >= 0 && pid != current_pid) {
340 save_stack();
341 restore_stack(pid);
342 }
343
344 current_pid = pid;
345
346 if (depth != ips_idx) {
347 save_call_chain(pid, ips, ips_idx, 0);
348 while (ips_idx > depth)
349 pop_stack_func();
350 }
351
352 func_depth = depth;
353
354 push_stack_func(func);
355 }
356
357 static void
process_function_graph_exit(struct tep_handle * pevent,struct tep_record * record)358 process_function_graph_exit(struct tep_handle *pevent, struct tep_record *record)
359 {
360 unsigned long long depth;
361 unsigned long long val;
362 int pid;
363 int ret;
364
365 ret = tep_read_number_field(common_pid_field, record->data, &val);
366 if (ret < 0)
367 die("no pid field for function graph exit?");
368
369 ret = tep_read_number_field(function_graph_exit_depth_field,
370 record->data, &depth);
371 if (ret < 0)
372 die("no parent ip field for function?");
373
374 pid = val;
375
376 if (current_pid >= 0 && pid != current_pid) {
377 save_stack();
378 restore_stack(pid);
379 }
380
381 current_pid = pid;
382
383 if (ips_idx != depth) {
384 save_call_chain(pid, ips, ips_idx, 0);
385 while (ips_idx > depth)
386 pop_stack_func();
387 }
388
389 func_depth = depth - 1;
390 }
391
392 static int pending_pid = -1;
393 static const char **pending_ips;
394 static int pending_ips_idx;
395
reset_pending_stack(void)396 static void reset_pending_stack(void)
397 {
398 pending_pid = -1;
399 pending_ips_idx = 0;
400 free(pending_ips);
401 pending_ips = NULL;
402 }
403
copy_stack_to_pending(int pid)404 static void copy_stack_to_pending(int pid)
405 {
406 pending_pid = pid;
407 pending_ips = zalloc(sizeof(char *) * ips_idx);
408 memcpy(pending_ips, ips, sizeof(char *) * ips_idx);
409 pending_ips_idx = ips_idx;
410 }
411
412 static void
process_kernel_stack(struct tep_handle * pevent,struct tep_record * record)413 process_kernel_stack(struct tep_handle *pevent, struct tep_record *record)
414 {
415 struct tep_format_field *field = kernel_stack_caller_field;
416 unsigned long long val;
417 void *data = record->data;
418 int do_restore = 0;
419 int pid;
420 int ret;
421
422 ret = tep_read_number_field(common_pid_field, record->data, &val);
423 if (ret < 0)
424 die("no pid field for function?");
425 pid = val;
426
427 if (pending_pid >= 0 && pid != pending_pid) {
428 reset_pending_stack();
429 return;
430 }
431
432 if (!field)
433 die("no caller field for kernel stack?");
434
435 if (pending_pid >= 0) {
436 if (current_pid >= 0) {
437 save_stack();
438 do_restore = 1;
439 }
440 } else {
441 /* function stack trace? */
442 if (current_pid >= 0) {
443 copy_stack_to_pending(current_pid);
444 free(ips);
445 reset_stack();
446 }
447 }
448
449 current_pid = pid;
450
451 /* Need to start at the end of the callers and work up */
452 for (data += field->offset; data < record->data + record->size;
453 data += long_size) {
454 unsigned long long addr;
455
456 addr = tep_read_number(pevent, data, long_size);
457
458 if ((long_size == 8 && addr == (unsigned long long)-1) ||
459 ((int)addr == -1))
460 break;
461 }
462
463 for (data -= long_size; data >= record->data + field->offset; data -= long_size) {
464 unsigned long long addr;
465 const char *func;
466
467 addr = tep_read_number(pevent, data, long_size);
468 func = tep_find_function(pevent, addr);
469 if (func)
470 push_stack_func(func);
471 }
472
473 if (pending_pid >= 0) {
474 push_stack_func(pending_ips[pending_ips_idx - 1]);
475 reset_pending_stack();
476 }
477 save_call_chain(current_pid, ips, ips_idx, 1);
478 if (do_restore)
479 restore_stack(current_pid);
480 }
481
482 static void
process_sched_wakeup(struct tep_handle * pevent,struct tep_record * record,int type)483 process_sched_wakeup(struct tep_handle *pevent, struct tep_record *record, int type)
484 {
485 unsigned long long val;
486 const char *comm;
487 int pid;
488 int ret;
489
490 if (type == sched_wakeup_type) {
491 comm = (char *)(record->data + sched_wakeup_comm_field->offset);
492 ret = tep_read_number_field(sched_wakeup_pid_field, record->data, &val);
493 if (ret < 0)
494 die("no pid field in sched_wakeup?");
495 } else {
496 comm = (char *)(record->data + sched_wakeup_new_comm_field->offset);
497 ret = tep_read_number_field(sched_wakeup_new_pid_field, record->data, &val);
498 if (ret < 0)
499 die("no pid field in sched_wakeup_new?");
500 }
501
502 pid = val;
503
504 tep_register_comm(pevent, comm, pid);
505 }
506
507 static void
process_sched_switch(struct tep_handle * pevent,struct tep_record * record)508 process_sched_switch(struct tep_handle *pevent, struct tep_record *record)
509 {
510 unsigned long long val;
511 const char *comm;
512 int pid;
513 int ret;
514
515 comm = (char *)(record->data + sched_switch_prev_field->offset);
516 ret = tep_read_number_field(sched_switch_prev_pid_field, record->data, &val);
517 if (ret < 0)
518 die("no prev_pid field in sched_switch?");
519 pid = val;
520 tep_register_comm(pevent, comm, pid);
521
522 comm = (char *)(record->data + sched_switch_next_field->offset);
523 ret = tep_read_number_field(sched_switch_next_pid_field, record->data, &val);
524 if (ret < 0)
525 die("no next_pid field in sched_switch?");
526 pid = val;
527 tep_register_comm(pevent, comm, pid);
528 }
529
530 static void
process_event(struct tep_handle * pevent,struct tep_record * record,int type)531 process_event(struct tep_handle *pevent, struct tep_record *record, int type)
532 {
533 struct tep_event *event;
534 const char *event_name;
535 unsigned long long val;
536 int pid;
537 int ret;
538
539 if (pending_pid >= 0) {
540 save_call_chain(pending_pid, pending_ips, pending_ips_idx, 1);
541 reset_pending_stack();
542 }
543
544 event = tep_find_event(pevent, type);
545 event_name = event->name;
546
547 ret = tep_read_number_field(common_pid_field, record->data, &val);
548 if (ret < 0)
549 die("no pid field for function?");
550
551 pid = val;
552
553 /*
554 * Even if function or function graph tracer is running,
555 * if the user ran with stack traces on events, we want to use
556 * that instead. But unfortunately, that stack doesn't come
557 * until after the event. Thus, we only add the event into
558 * the pending stack.
559 */
560 push_stack_func(event_name);
561 copy_stack_to_pending(pid);
562 pop_stack_func();
563 }
564
565 static void
process_record(struct tep_handle * pevent,struct tep_record * record)566 process_record(struct tep_handle *pevent, struct tep_record *record)
567 {
568 unsigned long long val;
569 int type;
570
571 tep_read_number_field(common_type_hist, record->data, &val);
572 type = val;
573
574 if (type == function_type)
575 return process_function(pevent, record);
576
577 if (type == function_graph_entry_type)
578 return process_function_graph_entry(pevent, record);
579
580 if (type == function_graph_exit_type)
581 return process_function_graph_exit(pevent, record);
582
583 if (type == kernel_stack_type)
584 return process_kernel_stack(pevent, record);
585
586 if (type == sched_wakeup_type || type == sched_wakeup_new_type)
587 process_sched_wakeup(pevent, record, type);
588
589 else if (type == sched_switch_type)
590 process_sched_switch(pevent, record);
591
592 process_event(pevent, record, type);
593 }
594
595 static struct tep_event *
update_event(struct tep_handle * pevent,const char * sys,const char * name,int * id)596 update_event(struct tep_handle *pevent,
597 const char *sys, const char *name, int *id)
598 {
599 struct tep_event *event;
600
601 event = tep_find_event_by_name(pevent, sys, name);
602 if (!event)
603 return NULL;
604
605 *id = event->id;
606
607 return event;
608 }
609
update_sched_wakeup(struct tep_handle * pevent)610 static void update_sched_wakeup(struct tep_handle *pevent)
611 {
612 struct tep_event *event;
613
614 event = update_event(pevent, "sched", "sched_wakeup", &sched_wakeup_type);
615 if (!event)
616 return;
617
618 sched_wakeup_comm_field = tep_find_field(event, "comm");
619 sched_wakeup_pid_field = tep_find_field(event, "pid");
620 }
621
update_sched_wakeup_new(struct tep_handle * pevent)622 static void update_sched_wakeup_new(struct tep_handle *pevent)
623 {
624 struct tep_event *event;
625
626 event = update_event(pevent, "sched", "sched_wakeup_new", &sched_wakeup_new_type);
627 if (!event)
628 return;
629
630 sched_wakeup_new_comm_field = tep_find_field(event, "comm");
631 sched_wakeup_new_pid_field = tep_find_field(event, "pid");
632 }
633
update_sched_switch(struct tep_handle * pevent)634 static void update_sched_switch(struct tep_handle *pevent)
635 {
636 struct tep_event *event;
637
638 event = update_event(pevent, "sched", "sched_switch", &sched_switch_type);
639 if (!event)
640 return;
641
642 sched_switch_prev_field = tep_find_field(event, "prev_comm");
643 sched_switch_next_field = tep_find_field(event, "next_comm");
644 sched_switch_prev_pid_field = tep_find_field(event, "prev_pid");
645 sched_switch_next_pid_field = tep_find_field(event, "next_pid");
646 }
647
update_function(struct tep_handle * pevent)648 static void update_function(struct tep_handle *pevent)
649 {
650 struct tep_event *event;
651
652 event = update_event(pevent, "ftrace", "function", &function_type);
653 if (!event)
654 return;
655
656 function_ip_field = tep_find_field(event, "ip");
657 function_parent_ip_field = tep_find_field(event, "parent_ip");
658 }
659
update_function_graph_entry(struct tep_handle * pevent)660 static void update_function_graph_entry(struct tep_handle *pevent)
661 {
662 struct tep_event *event;
663
664 event = update_event(pevent, "ftrace", "funcgraph_entry", &function_graph_entry_type);
665 if (!event)
666 return;
667
668 function_graph_entry_func_field = tep_find_field(event, "func");
669 function_graph_entry_depth_field = tep_find_field(event, "depth");
670 }
671
update_function_graph_exit(struct tep_handle * pevent)672 static void update_function_graph_exit(struct tep_handle *pevent)
673 {
674 struct tep_event *event;
675
676 event = update_event(pevent, "ftrace", "funcgraph_exit", &function_graph_exit_type);
677 if (!event)
678 return;
679
680 function_graph_exit_func_field = tep_find_field(event, "func");
681 function_graph_exit_depth_field = tep_find_field(event, "depth");
682 function_graph_exit_calltime_field = tep_find_field(event, "calltime");
683 function_graph_exit_rettime_field = tep_find_field(event, "rettime");
684 function_graph_exit_overrun_field = tep_find_field(event, "overrun");
685 }
686
update_kernel_stack(struct tep_handle * pevent)687 static void update_kernel_stack(struct tep_handle *pevent)
688 {
689 struct tep_event *event;
690
691 event = update_event(pevent, "ftrace", "kernel_stack", &kernel_stack_type);
692 if (!event)
693 return;
694
695 kernel_stack_caller_field = tep_find_field(event, "caller");
696 }
697
698 enum field { NEXT_PTR, SIB_PTR };
699
next_ptr(struct chain * chain,enum field field)700 static struct chain *next_ptr(struct chain *chain, enum field field)
701 {
702 if (field == NEXT_PTR)
703 return chain->next;
704 return chain->sibling;
705 }
706
split_chain(struct chain * orig,int size,enum field field)707 static struct chain *split_chain(struct chain *orig, int size, enum field field)
708 {
709 struct chain *chain;
710 int i;
711
712 if (size < 2)
713 return NULL;
714
715 for (i = 1; i < (size + 1) / 2; i++, orig = next_ptr(orig, field))
716 ;
717
718 if (field == NEXT_PTR) {
719 chain = orig->next;
720 orig->next = NULL;
721 } else {
722 chain = orig->sibling;
723 orig->sibling = NULL;
724 }
725
726 return chain;
727 }
728
729 static struct chain *
merge_chains(struct chain * a,int nr_a,struct chain * b,int nr_b,enum field field)730 merge_chains(struct chain *a, int nr_a, struct chain *b, int nr_b, enum field field)
731 {
732 struct chain *chain;
733 struct chain *final;
734 struct chain **next = &final;
735 int i;
736
737 if (!a)
738 return b;
739 if (!b)
740 return a;
741
742 for (i = 0, chain = a; chain; i++, chain = next_ptr(chain, field))
743 ;
744 if (i != nr_a)
745 die("WTF %d %d", i, nr_a);
746
747 chain = split_chain(a, nr_a, field);
748 a = merge_chains(chain, nr_a / 2, a, (nr_a + 1) / 2, field);
749
750 chain = split_chain(b, nr_b, field);
751 b = merge_chains(chain, nr_b / 2, b, (nr_b + 1) / 2, field);
752
753 while (a && b) {
754 if (a->count > b->count) {
755 *next = a;
756 if (field == NEXT_PTR)
757 next = &a->next;
758 else
759 next = &a->sibling;
760 a = *next;
761 *next = NULL;
762 } else {
763 *next = b;
764 if (field == NEXT_PTR)
765 next = &b->next;
766 else
767 next = &b->sibling;
768 b = *next;
769 *next = NULL;
770 }
771 }
772 if (a)
773 *next = a;
774 else
775 *next = b;
776
777 return final;
778 }
779
sort_chain_parents(struct chain * chain)780 static void sort_chain_parents(struct chain *chain)
781 {
782 struct chain *parent;
783
784 parent = split_chain(chain->parents, chain->nr_parents, SIB_PTR);
785 chain->parents = merge_chains(parent, chain->nr_parents / 2,
786 chain->parents, (chain->nr_parents + 1) / 2,
787 SIB_PTR);
788
789 for (chain = chain->parents; chain; chain = chain->sibling)
790 sort_chain_parents(chain);
791 }
792
sort_chains(void)793 static void sort_chains(void)
794 {
795 struct chain *chain;
796
797 chain = split_chain(chains, nr_chains, NEXT_PTR);
798
799 /* The original always has more or equal to the split */
800 chains = merge_chains(chain, nr_chains / 2, chains, (nr_chains + 1) / 2, NEXT_PTR);
801
802 for (chain = chains; chain; chain = chain->next)
803 sort_chain_parents(chain);
804 }
805
get_percent(int total,int partial)806 static double get_percent(int total, int partial)
807 {
808 return ((double)partial / (double)total) * 100.0;
809 }
810
single_chain(struct chain * chain)811 static int single_chain(struct chain *chain)
812 {
813 if (chain->nr_parents > 1)
814 return 0;
815
816 if (!chain->parents)
817 return 1;
818
819 return single_chain(chain->parents);
820 }
821
822 #define START " |\n"
823 #define TICK " --- "
824 #define BLANK " "
825 #define LINE " |"
826 #define INDENT " "
827
828 unsigned long long line_mask;
make_indent(int indent)829 void make_indent(int indent)
830 {
831 int i;
832
833 for (i = 0; i < indent; i++) {
834 if (line_mask & (1 << i))
835 printf(LINE);
836 else
837 printf(INDENT);
838 }
839 }
840
841 static void
print_single_parent(struct chain * chain,int indent)842 print_single_parent(struct chain *chain, int indent)
843 {
844 make_indent(indent);
845
846 printf(BLANK);
847 printf("%s\n", chain->parents->func);
848 }
849
850 static void
dump_chain(struct tep_handle * pevent,struct chain * chain,int indent)851 dump_chain(struct tep_handle *pevent, struct chain *chain, int indent)
852 {
853 if (!chain->parents)
854 return;
855
856 print_single_parent(chain, indent);
857 dump_chain(pevent, chain->parents, indent);
858 }
859
print_parents(struct tep_handle * pevent,struct chain * chain,int indent)860 static void print_parents(struct tep_handle *pevent, struct chain *chain, int indent)
861 {
862 struct chain *parent = chain->parents;
863 int x;
864
865 if (single_chain(chain)) {
866 dump_chain(pevent, chain, indent);
867 return;
868 }
869
870 line_mask |= 1ULL << (indent);
871
872 for (x = 0; parent; x++, parent = parent->sibling) {
873 struct chain *save_parent;
874
875 make_indent(indent + 1);
876 printf("\n");
877
878 make_indent(indent + 1);
879
880 printf("--%%%.2f-- %s # %d\n",
881 get_percent(chain->count, parent->count),
882 parent->func, parent->count);
883
884 if (x == chain->nr_parents - 1)
885 line_mask &= (1ULL << indent) - 1;
886
887 if (single_chain(parent))
888 dump_chain(pevent, parent, indent + 1);
889 else {
890 save_parent = parent;
891
892 while (parent && parent->parents && parent->nr_parents < 2 &&
893 parent->parents->count == parent->count) {
894 print_single_parent(parent, indent + 1);
895 parent = parent->parents;
896 }
897 if (parent)
898 print_parents(pevent, parent, indent + 1);
899 parent = save_parent;
900 }
901 }
902 }
903
print_chains(struct tep_handle * pevent)904 static void print_chains(struct tep_handle *pevent)
905 {
906 struct chain *chain = chains;
907 int pid;
908
909 for (; chain; chain = chain->next) {
910 pid = chain->pid_list->pid;
911 if (chain != chains)
912 printf("\n");
913 if (compact)
914 printf(" %%%3.2f <all pids> %30s #%d\n",
915 get_percent(total_counts, chain->count),
916 chain->func,
917 chain->count);
918 else
919 printf(" %%%3.2f (%d) %s %30s #%d\n",
920 get_percent(total_counts, chain->count),
921 pid,
922 tep_data_comm_from_pid(pevent, pid),
923 chain->func,
924 chain->count);
925 printf(START);
926 if (chain->event)
927 printf(TICK "*%s*\n", chain->func);
928 else
929 printf(TICK "%s\n", chain->func);
930 print_parents(pevent, chain, 0);
931 }
932 }
933
do_trace_hist(struct tracecmd_input * handle)934 static void do_trace_hist(struct tracecmd_input *handle)
935 {
936 struct tep_handle *pevent = tracecmd_get_tep(handle);
937 struct tep_record *record;
938 struct tep_event *event;
939 int cpus;
940 int cpu;
941 int ret;
942
943 cpus = tracecmd_cpus(handle);
944
945 /* Need to get any event */
946 for (cpu = 0; cpu < cpus; cpu++) {
947 record = tracecmd_peek_data(handle, cpu);
948 if (record)
949 break;
950 }
951 if (!record)
952 die("No records found in file");
953
954 ret = tep_data_type(pevent, record);
955 event = tep_find_event(pevent, ret);
956
957 long_size = tracecmd_long_size(handle);
958
959 common_type_hist = tep_find_common_field(event, "common_type");
960 if (!common_type_hist)
961 die("Can't find a 'type' field?");
962
963 common_pid_field = tep_find_common_field(event, "common_pid");
964 if (!common_pid_field)
965 die("Can't find a 'pid' field?");
966
967 update_sched_wakeup(pevent);
968 update_sched_wakeup_new(pevent);
969 update_sched_switch(pevent);
970 update_function(pevent);
971 update_function_graph_entry(pevent);
972 update_function_graph_exit(pevent);
973 update_kernel_stack(pevent);
974
975 for (cpu = 0; cpu < cpus; cpu++) {
976 for (;;) {
977 struct tep_record *record;
978
979 record = tracecmd_read_data(handle, cpu);
980 if (!record)
981 break;
982
983 /* If we missed events, just flush out the current stack */
984 if (record->missed_events)
985 flush_stack();
986
987 process_record(pevent, record);
988 tracecmd_free_record(record);
989 }
990 }
991
992 if (current_pid >= 0)
993 save_call_chain(current_pid, ips, ips_idx, 0);
994 if (pending_pid >= 0)
995 save_call_chain(pending_pid, pending_ips, pending_ips_idx, 1);
996
997 save_stored_stacks();
998
999 sort_chains();
1000 print_chains(pevent);
1001 }
1002
trace_hist(int argc,char ** argv)1003 void trace_hist(int argc, char **argv)
1004 {
1005 struct tracecmd_input *handle;
1006 const char *input_file = NULL;
1007 int instances;
1008 int ret;
1009
1010 for (;;) {
1011 int c;
1012
1013 c = getopt(argc-1, argv+1, "+hi:P");
1014 if (c == -1)
1015 break;
1016 switch (c) {
1017 case 'h':
1018 usage(argv);
1019 break;
1020 case 'i':
1021 if (input_file)
1022 die("Only one input for historgram");
1023 input_file = optarg;
1024 break;
1025 case 'P':
1026 compact = 1;
1027 break;
1028 default:
1029 usage(argv);
1030 }
1031 }
1032
1033 if ((argc - optind) >= 2) {
1034 if (input_file)
1035 usage(argv);
1036 input_file = argv[optind + 1];
1037 }
1038
1039 if (!input_file)
1040 input_file = DEFAULT_INPUT_FILE;
1041
1042 handle = tracecmd_alloc(input_file, 0);
1043 if (!handle)
1044 die("can't open %s\n", input_file);
1045
1046 ret = tracecmd_read_headers(handle, 0);
1047 if (ret)
1048 return;
1049
1050 ret = tracecmd_init_data(handle);
1051 if (ret < 0)
1052 die("failed to init data");
1053
1054 if (ret > 0)
1055 die("trace-cmd hist does not work with latency traces\n");
1056
1057 instances = tracecmd_buffer_instances(handle);
1058 if (instances) {
1059 struct tracecmd_input *new_handle;
1060 int i;
1061
1062 for (i = 0; i < instances; i++) {
1063 new_handle = tracecmd_buffer_instance_handle(handle, i);
1064 if (!new_handle) {
1065 warning("could not retrieve handle %d", i);
1066 continue;
1067 }
1068 do_trace_hist(new_handle);
1069 tracecmd_close(new_handle);
1070 }
1071 } else {
1072 do_trace_hist(handle);
1073 }
1074
1075 tracecmd_close(handle);
1076 }
1077