xref: /aosp_15_r20/external/trace-cmd/tracecmd/trace-hist.c (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
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