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