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