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