xref: /aosp_15_r20/external/trace-cmd/tracecmd/trace-profile.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) 2014 Red Hat Inc, Steven Rostedt <[email protected]>
4*58e6ee5fSAndroid Build Coastguard Worker  *
5*58e6ee5fSAndroid Build Coastguard Worker  */
6*58e6ee5fSAndroid Build Coastguard Worker 
7*58e6ee5fSAndroid Build Coastguard Worker /** FIXME: Convert numbers based on machine and file */
8*58e6ee5fSAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE
9*58e6ee5fSAndroid Build Coastguard Worker #include <stdio.h>
10*58e6ee5fSAndroid Build Coastguard Worker #include <stdlib.h>
11*58e6ee5fSAndroid Build Coastguard Worker #include <string.h>
12*58e6ee5fSAndroid Build Coastguard Worker #ifndef NO_AUDIT
13*58e6ee5fSAndroid Build Coastguard Worker #include <libaudit.h>
14*58e6ee5fSAndroid Build Coastguard Worker #endif
15*58e6ee5fSAndroid Build Coastguard Worker #include "trace-local.h"
16*58e6ee5fSAndroid Build Coastguard Worker #include "trace-hash.h"
17*58e6ee5fSAndroid Build Coastguard Worker #include "trace-hash-local.h"
18*58e6ee5fSAndroid Build Coastguard Worker #include "list.h"
19*58e6ee5fSAndroid Build Coastguard Worker 
20*58e6ee5fSAndroid Build Coastguard Worker #include <linux/time64.h>
21*58e6ee5fSAndroid Build Coastguard Worker 
22*58e6ee5fSAndroid Build Coastguard Worker #ifdef WARN_NO_AUDIT
23*58e6ee5fSAndroid Build Coastguard Worker # warning "lib audit not found, using raw syscalls "	\
24*58e6ee5fSAndroid Build Coastguard Worker 	"(install audit-libs-devel(for fedora) or libaudit-dev(for debian/ubuntu) and try again)"
25*58e6ee5fSAndroid Build Coastguard Worker #endif
26*58e6ee5fSAndroid Build Coastguard Worker 
27*58e6ee5fSAndroid Build Coastguard Worker #define TASK_STATE_TO_CHAR_STR "RSDTtXZxKWP"
28*58e6ee5fSAndroid Build Coastguard Worker #define TASK_STATE_MAX		1024
29*58e6ee5fSAndroid Build Coastguard Worker 
30*58e6ee5fSAndroid Build Coastguard Worker #define task_from_item(item)	container_of(item, struct task_data, hash)
31*58e6ee5fSAndroid Build Coastguard Worker #define start_from_item(item)	container_of(item, struct start_data, hash)
32*58e6ee5fSAndroid Build Coastguard Worker #define event_from_item(item)	container_of(item, struct event_hash, hash)
33*58e6ee5fSAndroid Build Coastguard Worker #define stack_from_item(item)	container_of(item, struct stack_data, hash)
34*58e6ee5fSAndroid Build Coastguard Worker #define group_from_item(item)	container_of(item, struct group_data, hash)
35*58e6ee5fSAndroid Build Coastguard Worker #define event_data_from_item(item)	container_of(item, struct event_data, hash)
36*58e6ee5fSAndroid Build Coastguard Worker 
nsecs_per_sec(unsigned long long ts)37*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long nsecs_per_sec(unsigned long long ts)
38*58e6ee5fSAndroid Build Coastguard Worker {
39*58e6ee5fSAndroid Build Coastguard Worker 	return ts / NSEC_PER_SEC;
40*58e6ee5fSAndroid Build Coastguard Worker }
41*58e6ee5fSAndroid Build Coastguard Worker 
mod_to_usec(unsigned long long ts)42*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long mod_to_usec(unsigned long long ts)
43*58e6ee5fSAndroid Build Coastguard Worker {
44*58e6ee5fSAndroid Build Coastguard Worker 	return ((ts % NSEC_PER_SEC) + NSEC_PER_USEC / 2) / NSEC_PER_USEC;
45*58e6ee5fSAndroid Build Coastguard Worker }
46*58e6ee5fSAndroid Build Coastguard Worker 
47*58e6ee5fSAndroid Build Coastguard Worker struct handle_data;
48*58e6ee5fSAndroid Build Coastguard Worker struct event_hash;
49*58e6ee5fSAndroid Build Coastguard Worker struct event_data;
50*58e6ee5fSAndroid Build Coastguard Worker 
51*58e6ee5fSAndroid Build Coastguard Worker typedef void (*event_data_print)(struct trace_seq *s, struct event_hash *hash);
52*58e6ee5fSAndroid Build Coastguard Worker typedef int (*handle_event_func)(struct handle_data *h, unsigned long long pid,
53*58e6ee5fSAndroid Build Coastguard Worker 				 struct event_data *data,
54*58e6ee5fSAndroid Build Coastguard Worker 				 struct tep_record *record, int cpu);
55*58e6ee5fSAndroid Build Coastguard Worker 
56*58e6ee5fSAndroid Build Coastguard Worker enum event_data_type {
57*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_UNDEFINED,
58*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_STACK,
59*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_SCHED_SWITCH,
60*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_WAKEUP,
61*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_FUNC,
62*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_SYSCALL,
63*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_IRQ,
64*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_SOFTIRQ,
65*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_SOFTIRQ_RAISE,
66*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_PROCESS_EXEC,
67*58e6ee5fSAndroid Build Coastguard Worker 	EVENT_TYPE_USER_MATE,
68*58e6ee5fSAndroid Build Coastguard Worker };
69*58e6ee5fSAndroid Build Coastguard Worker 
70*58e6ee5fSAndroid Build Coastguard Worker struct event_data {
71*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item	hash;
72*58e6ee5fSAndroid Build Coastguard Worker 	int			id;
73*58e6ee5fSAndroid Build Coastguard Worker 	int			trace;
74*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_event	*event;
75*58e6ee5fSAndroid Build Coastguard Worker 
76*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data	*end;
77*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data	*start;
78*58e6ee5fSAndroid Build Coastguard Worker 
79*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*pid_field;
80*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*start_match_field;	/* match with start */
81*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*end_match_field;	/* match with end */
82*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*data_field;	/* optional */
83*58e6ee5fSAndroid Build Coastguard Worker 
84*58e6ee5fSAndroid Build Coastguard Worker 	event_data_print	print_func;
85*58e6ee5fSAndroid Build Coastguard Worker 	handle_event_func	handle_event;
86*58e6ee5fSAndroid Build Coastguard Worker 	void			*private;
87*58e6ee5fSAndroid Build Coastguard Worker 	int			migrate;	/* start/end pairs can migrate cpus */
88*58e6ee5fSAndroid Build Coastguard Worker 	int			global;		/* use global tasks */
89*58e6ee5fSAndroid Build Coastguard Worker 	enum event_data_type	type;
90*58e6ee5fSAndroid Build Coastguard Worker };
91*58e6ee5fSAndroid Build Coastguard Worker 
92*58e6ee5fSAndroid Build Coastguard Worker struct stack_data {
93*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item  hash;
94*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	count;
95*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time;
96*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_min;
97*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_min;
98*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_max;
99*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_max;
100*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_avg;
101*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long		size;
102*58e6ee5fSAndroid Build Coastguard Worker 	char			caller[];
103*58e6ee5fSAndroid Build Coastguard Worker };
104*58e6ee5fSAndroid Build Coastguard Worker 
105*58e6ee5fSAndroid Build Coastguard Worker struct stack_holder {
106*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long		size;
107*58e6ee5fSAndroid Build Coastguard Worker 	void			*caller;
108*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record	*record;
109*58e6ee5fSAndroid Build Coastguard Worker };
110*58e6ee5fSAndroid Build Coastguard Worker 
111*58e6ee5fSAndroid Build Coastguard Worker struct start_data {
112*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item	hash;
113*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data	*event_data;
114*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	list;
115*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data	*task;
116*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long 	timestamp;
117*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long 	search_val;
118*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	val;
119*58e6ee5fSAndroid Build Coastguard Worker 	int			cpu;
120*58e6ee5fSAndroid Build Coastguard Worker 
121*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_holder	stack;
122*58e6ee5fSAndroid Build Coastguard Worker };
123*58e6ee5fSAndroid Build Coastguard Worker 
124*58e6ee5fSAndroid Build Coastguard Worker struct event_hash {
125*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item	hash;
126*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data	*event_data;
127*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	search_val;
128*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	val;
129*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	count;
130*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_total;
131*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_avg;
132*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_max;
133*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_max;
134*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_min;
135*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_min;
136*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_std;
137*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	last_time;
138*58e6ee5fSAndroid Build Coastguard Worker 
139*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	stacks;
140*58e6ee5fSAndroid Build Coastguard Worker };
141*58e6ee5fSAndroid Build Coastguard Worker 
142*58e6ee5fSAndroid Build Coastguard Worker struct group_data {
143*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item	hash;
144*58e6ee5fSAndroid Build Coastguard Worker 	char			*comm;
145*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	event_hash;
146*58e6ee5fSAndroid Build Coastguard Worker };
147*58e6ee5fSAndroid Build Coastguard Worker 
148*58e6ee5fSAndroid Build Coastguard Worker struct task_data {
149*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item	hash;
150*58e6ee5fSAndroid Build Coastguard Worker 	int			pid;
151*58e6ee5fSAndroid Build Coastguard Worker 	int			sleeping;
152*58e6ee5fSAndroid Build Coastguard Worker 
153*58e6ee5fSAndroid Build Coastguard Worker 	char			*comm;
154*58e6ee5fSAndroid Build Coastguard Worker 
155*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	start_hash;
156*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	event_hash;
157*58e6ee5fSAndroid Build Coastguard Worker 
158*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data	*proxy;
159*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data	*last_start;
160*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash	*last_event;
161*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record	*last_stack;
162*58e6ee5fSAndroid Build Coastguard Worker 	struct handle_data	*handle;
163*58e6ee5fSAndroid Build Coastguard Worker 	struct group_data	*group;
164*58e6ee5fSAndroid Build Coastguard Worker };
165*58e6ee5fSAndroid Build Coastguard Worker 
166*58e6ee5fSAndroid Build Coastguard Worker struct cpu_info {
167*58e6ee5fSAndroid Build Coastguard Worker 	int			current;
168*58e6ee5fSAndroid Build Coastguard Worker };
169*58e6ee5fSAndroid Build Coastguard Worker 
170*58e6ee5fSAndroid Build Coastguard Worker struct sched_switch_data {
171*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*prev_state;
172*58e6ee5fSAndroid Build Coastguard Worker 	int			match_state;
173*58e6ee5fSAndroid Build Coastguard Worker };
174*58e6ee5fSAndroid Build Coastguard Worker 
175*58e6ee5fSAndroid Build Coastguard Worker struct handle_data {
176*58e6ee5fSAndroid Build Coastguard Worker 	struct handle_data	*next;
177*58e6ee5fSAndroid Build Coastguard Worker 	struct tracecmd_input	*handle;
178*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle	*pevent;
179*58e6ee5fSAndroid Build Coastguard Worker 
180*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	events;
181*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	group_hash;
182*58e6ee5fSAndroid Build Coastguard Worker 
183*58e6ee5fSAndroid Build Coastguard Worker 	struct cpu_info		**cpu_data;
184*58e6ee5fSAndroid Build Coastguard Worker 
185*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*common_pid;
186*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*wakeup_comm;
187*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*switch_prev_comm;
188*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field	*switch_next_comm;
189*58e6ee5fSAndroid Build Coastguard Worker 
190*58e6ee5fSAndroid Build Coastguard Worker 	struct sched_switch_data sched_switch_blocked;
191*58e6ee5fSAndroid Build Coastguard Worker 	struct sched_switch_data sched_switch_preempt;
192*58e6ee5fSAndroid Build Coastguard Worker 
193*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash	task_hash;
194*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	*cpu_starts;
195*58e6ee5fSAndroid Build Coastguard Worker 	struct list_head	migrate_starts;
196*58e6ee5fSAndroid Build Coastguard Worker 
197*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data	*global_task;
198*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data	*global_percpu_tasks;
199*58e6ee5fSAndroid Build Coastguard Worker 
200*58e6ee5fSAndroid Build Coastguard Worker 	int			cpus;
201*58e6ee5fSAndroid Build Coastguard Worker };
202*58e6ee5fSAndroid Build Coastguard Worker 
203*58e6ee5fSAndroid Build Coastguard Worker static struct handle_data *handles;
204*58e6ee5fSAndroid Build Coastguard Worker static struct event_data *stacktrace_event;
205*58e6ee5fSAndroid Build Coastguard Worker static bool merge_like_comms = false;
206*58e6ee5fSAndroid Build Coastguard Worker 
trace_profile_set_merge_like_comms(void)207*58e6ee5fSAndroid Build Coastguard Worker void trace_profile_set_merge_like_comms(void)
208*58e6ee5fSAndroid Build Coastguard Worker {
209*58e6ee5fSAndroid Build Coastguard Worker 	merge_like_comms = true;
210*58e6ee5fSAndroid Build Coastguard Worker }
211*58e6ee5fSAndroid Build Coastguard Worker 
212*58e6ee5fSAndroid Build Coastguard Worker static struct start_data *
add_start(struct task_data * task,struct event_data * event_data,struct tep_record * record,unsigned long long search_val,unsigned long long val)213*58e6ee5fSAndroid Build Coastguard Worker add_start(struct task_data *task,
214*58e6ee5fSAndroid Build Coastguard Worker 	  struct event_data *event_data, struct tep_record *record,
215*58e6ee5fSAndroid Build Coastguard Worker 	  unsigned long long search_val, unsigned long long val)
216*58e6ee5fSAndroid Build Coastguard Worker {
217*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
218*58e6ee5fSAndroid Build Coastguard Worker 
219*58e6ee5fSAndroid Build Coastguard Worker 	start = malloc(sizeof(*start));
220*58e6ee5fSAndroid Build Coastguard Worker 	if (!start)
221*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
222*58e6ee5fSAndroid Build Coastguard Worker 	memset(start, 0, sizeof(*start));
223*58e6ee5fSAndroid Build Coastguard Worker 	start->hash.key = trace_hash(search_val);
224*58e6ee5fSAndroid Build Coastguard Worker 	start->search_val = search_val;
225*58e6ee5fSAndroid Build Coastguard Worker 	start->val = val;
226*58e6ee5fSAndroid Build Coastguard Worker 	start->timestamp = record->ts;
227*58e6ee5fSAndroid Build Coastguard Worker 	start->event_data = event_data;
228*58e6ee5fSAndroid Build Coastguard Worker 	start->cpu = record->cpu;
229*58e6ee5fSAndroid Build Coastguard Worker 	start->task = task;
230*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_add(&task->start_hash, &start->hash);
231*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->migrate)
232*58e6ee5fSAndroid Build Coastguard Worker 		list_add(&start->list, &task->handle->migrate_starts);
233*58e6ee5fSAndroid Build Coastguard Worker 	else
234*58e6ee5fSAndroid Build Coastguard Worker 		list_add(&start->list, &task->handle->cpu_starts[record->cpu]);
235*58e6ee5fSAndroid Build Coastguard Worker 	return start;
236*58e6ee5fSAndroid Build Coastguard Worker }
237*58e6ee5fSAndroid Build Coastguard Worker 
238*58e6ee5fSAndroid Build Coastguard Worker struct event_data_match {
239*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data	*event_data;
240*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	search_val;
241*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	val;
242*58e6ee5fSAndroid Build Coastguard Worker };
243*58e6ee5fSAndroid Build Coastguard Worker 
match_start(struct trace_hash_item * item,void * data)244*58e6ee5fSAndroid Build Coastguard Worker static int match_start(struct trace_hash_item *item, void *data)
245*58e6ee5fSAndroid Build Coastguard Worker {
246*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start = start_from_item(item);
247*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data_match *edata = data;
248*58e6ee5fSAndroid Build Coastguard Worker 
249*58e6ee5fSAndroid Build Coastguard Worker 	return start->event_data == edata->event_data &&
250*58e6ee5fSAndroid Build Coastguard Worker 		start->search_val == edata->search_val;
251*58e6ee5fSAndroid Build Coastguard Worker }
252*58e6ee5fSAndroid Build Coastguard Worker 
match_event(struct trace_hash_item * item,void * data)253*58e6ee5fSAndroid Build Coastguard Worker static int match_event(struct trace_hash_item *item, void *data)
254*58e6ee5fSAndroid Build Coastguard Worker {
255*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data_match *edata = data;
256*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event = event_from_item(item);
257*58e6ee5fSAndroid Build Coastguard Worker 
258*58e6ee5fSAndroid Build Coastguard Worker 	return event->event_data == edata->event_data &&
259*58e6ee5fSAndroid Build Coastguard Worker 		event->search_val == edata->search_val &&
260*58e6ee5fSAndroid Build Coastguard Worker 		event->val == edata->val;
261*58e6ee5fSAndroid Build Coastguard Worker }
262*58e6ee5fSAndroid Build Coastguard Worker 
263*58e6ee5fSAndroid Build Coastguard Worker static struct event_hash *
find_event_hash(struct task_data * task,struct event_data_match * edata)264*58e6ee5fSAndroid Build Coastguard Worker find_event_hash(struct task_data *task, struct event_data_match *edata)
265*58e6ee5fSAndroid Build Coastguard Worker {
266*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
267*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
268*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key;
269*58e6ee5fSAndroid Build Coastguard Worker 
270*58e6ee5fSAndroid Build Coastguard Worker 	key = (unsigned long)edata->event_data +
271*58e6ee5fSAndroid Build Coastguard Worker 		(unsigned long)edata->search_val +
272*58e6ee5fSAndroid Build Coastguard Worker 		(unsigned long)edata->val;
273*58e6ee5fSAndroid Build Coastguard Worker 	key = trace_hash(key);
274*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&task->event_hash, key, match_event, edata);
275*58e6ee5fSAndroid Build Coastguard Worker 	if (item)
276*58e6ee5fSAndroid Build Coastguard Worker 		return event_from_item(item);
277*58e6ee5fSAndroid Build Coastguard Worker 
278*58e6ee5fSAndroid Build Coastguard Worker 	event_hash = malloc(sizeof(*event_hash));
279*58e6ee5fSAndroid Build Coastguard Worker 	if (!event_hash)
280*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
281*58e6ee5fSAndroid Build Coastguard Worker 	memset(event_hash, 0, sizeof(*event_hash));
282*58e6ee5fSAndroid Build Coastguard Worker 
283*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->event_data = edata->event_data;
284*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->search_val = edata->search_val;
285*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->val = edata->val;
286*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->hash.key = key;
287*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_init(&event_hash->stacks, 32);
288*58e6ee5fSAndroid Build Coastguard Worker 
289*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_add(&task->event_hash, &event_hash->hash);
290*58e6ee5fSAndroid Build Coastguard Worker 
291*58e6ee5fSAndroid Build Coastguard Worker 	return event_hash;
292*58e6ee5fSAndroid Build Coastguard Worker }
293*58e6ee5fSAndroid Build Coastguard Worker 
294*58e6ee5fSAndroid Build Coastguard Worker static struct event_hash *
find_start_event_hash(struct task_data * task,struct event_data * event_data,struct start_data * start)295*58e6ee5fSAndroid Build Coastguard Worker find_start_event_hash(struct task_data *task, struct event_data *event_data,
296*58e6ee5fSAndroid Build Coastguard Worker 		      struct start_data *start)
297*58e6ee5fSAndroid Build Coastguard Worker {
298*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data_match edata;
299*58e6ee5fSAndroid Build Coastguard Worker 
300*58e6ee5fSAndroid Build Coastguard Worker 	edata.event_data = event_data;
301*58e6ee5fSAndroid Build Coastguard Worker 	edata.search_val = start->search_val;
302*58e6ee5fSAndroid Build Coastguard Worker 	edata.val = start->val;
303*58e6ee5fSAndroid Build Coastguard Worker 
304*58e6ee5fSAndroid Build Coastguard Worker 	return find_event_hash(task, &edata);
305*58e6ee5fSAndroid Build Coastguard Worker }
306*58e6ee5fSAndroid Build Coastguard Worker 
307*58e6ee5fSAndroid Build Coastguard Worker static struct start_data *
find_start(struct task_data * task,struct event_data * event_data,unsigned long long search_val)308*58e6ee5fSAndroid Build Coastguard Worker find_start(struct task_data *task, struct event_data *event_data,
309*58e6ee5fSAndroid Build Coastguard Worker 	   unsigned long long search_val)
310*58e6ee5fSAndroid Build Coastguard Worker {
311*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key = trace_hash(search_val);
312*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data_match edata;
313*58e6ee5fSAndroid Build Coastguard Worker 	void *data = &edata;
314*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
315*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
316*58e6ee5fSAndroid Build Coastguard Worker 
317*58e6ee5fSAndroid Build Coastguard Worker 	edata.event_data = event_data;
318*58e6ee5fSAndroid Build Coastguard Worker 	edata.search_val = search_val;
319*58e6ee5fSAndroid Build Coastguard Worker 
320*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&task->start_hash, key, match_start, data);
321*58e6ee5fSAndroid Build Coastguard Worker 	if (!item)
322*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
323*58e6ee5fSAndroid Build Coastguard Worker 
324*58e6ee5fSAndroid Build Coastguard Worker 	start = start_from_item(item);
325*58e6ee5fSAndroid Build Coastguard Worker 	return start;
326*58e6ee5fSAndroid Build Coastguard Worker }
327*58e6ee5fSAndroid Build Coastguard Worker 
328*58e6ee5fSAndroid Build Coastguard Worker struct stack_match {
329*58e6ee5fSAndroid Build Coastguard Worker 	void		*caller;
330*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long	size;
331*58e6ee5fSAndroid Build Coastguard Worker };
332*58e6ee5fSAndroid Build Coastguard Worker 
match_stack(struct trace_hash_item * item,void * data)333*58e6ee5fSAndroid Build Coastguard Worker static int match_stack(struct trace_hash_item *item, void *data)
334*58e6ee5fSAndroid Build Coastguard Worker {
335*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data *stack = stack_from_item(item);
336*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_match *match = data;
337*58e6ee5fSAndroid Build Coastguard Worker 
338*58e6ee5fSAndroid Build Coastguard Worker 	if (match->size != stack->size)
339*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
340*58e6ee5fSAndroid Build Coastguard Worker 
341*58e6ee5fSAndroid Build Coastguard Worker 	return memcmp(stack->caller, match->caller, stack->size) == 0;
342*58e6ee5fSAndroid Build Coastguard Worker }
343*58e6ee5fSAndroid Build Coastguard Worker 
344*58e6ee5fSAndroid Build Coastguard Worker 
add_event_stack(struct event_hash * event_hash,void * caller,unsigned long size,unsigned long long time,unsigned long long ts)345*58e6ee5fSAndroid Build Coastguard Worker static void add_event_stack(struct event_hash *event_hash,
346*58e6ee5fSAndroid Build Coastguard Worker 			    void *caller, unsigned long size,
347*58e6ee5fSAndroid Build Coastguard Worker 			    unsigned long long time, unsigned long long ts)
348*58e6ee5fSAndroid Build Coastguard Worker {
349*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key;
350*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data *stack;
351*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_match match;
352*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
353*58e6ee5fSAndroid Build Coastguard Worker 	int i;
354*58e6ee5fSAndroid Build Coastguard Worker 
355*58e6ee5fSAndroid Build Coastguard Worker 	match.caller = caller;
356*58e6ee5fSAndroid Build Coastguard Worker 	match.size = size;
357*58e6ee5fSAndroid Build Coastguard Worker 
358*58e6ee5fSAndroid Build Coastguard Worker 	if (size < sizeof(int))
359*58e6ee5fSAndroid Build Coastguard Worker 		die("Stack size of less than sizeof(int)??");
360*58e6ee5fSAndroid Build Coastguard Worker 
361*58e6ee5fSAndroid Build Coastguard Worker 	for (key = 0, i = 0; i <= size - sizeof(int); i += sizeof(int))
362*58e6ee5fSAndroid Build Coastguard Worker 		key += trace_hash(*(int *)(caller + i));
363*58e6ee5fSAndroid Build Coastguard Worker 
364*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&event_hash->stacks, key, match_stack, &match);
365*58e6ee5fSAndroid Build Coastguard Worker 	if (!item) {
366*58e6ee5fSAndroid Build Coastguard Worker 		stack = malloc(sizeof(*stack) + size);
367*58e6ee5fSAndroid Build Coastguard Worker 		if (!stack) {
368*58e6ee5fSAndroid Build Coastguard Worker 			warning("Could not allocate stack");
369*58e6ee5fSAndroid Build Coastguard Worker 			return;
370*58e6ee5fSAndroid Build Coastguard Worker 		}
371*58e6ee5fSAndroid Build Coastguard Worker 		memset(stack, 0, sizeof(*stack));
372*58e6ee5fSAndroid Build Coastguard Worker 		memcpy(&stack->caller, caller, size);
373*58e6ee5fSAndroid Build Coastguard Worker 		stack->size = size;
374*58e6ee5fSAndroid Build Coastguard Worker 		stack->hash.key = key;
375*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_add(&event_hash->stacks, &stack->hash);
376*58e6ee5fSAndroid Build Coastguard Worker 	} else
377*58e6ee5fSAndroid Build Coastguard Worker 		stack = stack_from_item(item);
378*58e6ee5fSAndroid Build Coastguard Worker 
379*58e6ee5fSAndroid Build Coastguard Worker 	stack->count++;
380*58e6ee5fSAndroid Build Coastguard Worker 	stack->time += time;
381*58e6ee5fSAndroid Build Coastguard Worker 	if (stack->count == 1 || time < stack->time_min) {
382*58e6ee5fSAndroid Build Coastguard Worker 		stack->time_min = time;
383*58e6ee5fSAndroid Build Coastguard Worker 		stack->ts_min = ts;
384*58e6ee5fSAndroid Build Coastguard Worker 	}
385*58e6ee5fSAndroid Build Coastguard Worker 	if (time > stack->time_max) {
386*58e6ee5fSAndroid Build Coastguard Worker 		stack->time_max = time;
387*58e6ee5fSAndroid Build Coastguard Worker 		stack->ts_max = ts;
388*58e6ee5fSAndroid Build Coastguard Worker 	}
389*58e6ee5fSAndroid Build Coastguard Worker }
390*58e6ee5fSAndroid Build Coastguard Worker 
free_start(struct start_data * start)391*58e6ee5fSAndroid Build Coastguard Worker static void free_start(struct start_data *start)
392*58e6ee5fSAndroid Build Coastguard Worker {
393*58e6ee5fSAndroid Build Coastguard Worker 	if (start->task->last_start == start)
394*58e6ee5fSAndroid Build Coastguard Worker 		start->task->last_start = NULL;
395*58e6ee5fSAndroid Build Coastguard Worker 	if (start->stack.record)
396*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(start->stack.record);
397*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_del(&start->hash);
398*58e6ee5fSAndroid Build Coastguard Worker 	list_del(&start->list);
399*58e6ee5fSAndroid Build Coastguard Worker 	free(start);
400*58e6ee5fSAndroid Build Coastguard Worker }
401*58e6ee5fSAndroid Build Coastguard Worker 
402*58e6ee5fSAndroid Build Coastguard Worker static struct event_hash *
add_and_free_start(struct task_data * task,struct start_data * start,struct event_data * event_data,unsigned long long ts)403*58e6ee5fSAndroid Build Coastguard Worker add_and_free_start(struct task_data *task, struct start_data *start,
404*58e6ee5fSAndroid Build Coastguard Worker 		   struct event_data *event_data, unsigned long long ts)
405*58e6ee5fSAndroid Build Coastguard Worker {
406*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
407*58e6ee5fSAndroid Build Coastguard Worker 	long long delta;
408*58e6ee5fSAndroid Build Coastguard Worker 
409*58e6ee5fSAndroid Build Coastguard Worker 	delta = ts - start->timestamp;
410*58e6ee5fSAndroid Build Coastguard Worker 
411*58e6ee5fSAndroid Build Coastguard Worker 	/*
412*58e6ee5fSAndroid Build Coastguard Worker 	 * It's possible on a live trace, because of timestamps being
413*58e6ee5fSAndroid Build Coastguard Worker 	 * different on different CPUs, we can go back in time. When
414*58e6ee5fSAndroid Build Coastguard Worker 	 * that happens, just zero out the delta.
415*58e6ee5fSAndroid Build Coastguard Worker 	 */
416*58e6ee5fSAndroid Build Coastguard Worker 	if (delta < 0)
417*58e6ee5fSAndroid Build Coastguard Worker 		delta = 0;
418*58e6ee5fSAndroid Build Coastguard Worker 
419*58e6ee5fSAndroid Build Coastguard Worker 	event_hash = find_start_event_hash(task, event_data, start);
420*58e6ee5fSAndroid Build Coastguard Worker 	if (!event_hash)
421*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
422*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->count++;
423*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->time_total += delta;
424*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->last_time = delta;
425*58e6ee5fSAndroid Build Coastguard Worker 
426*58e6ee5fSAndroid Build Coastguard Worker 	if (delta > event_hash->time_max) {
427*58e6ee5fSAndroid Build Coastguard Worker 		event_hash->time_max = delta;
428*58e6ee5fSAndroid Build Coastguard Worker 		event_hash->ts_max = ts;
429*58e6ee5fSAndroid Build Coastguard Worker 	}
430*58e6ee5fSAndroid Build Coastguard Worker 
431*58e6ee5fSAndroid Build Coastguard Worker 	if (event_hash->count == 1 || delta < event_hash->time_min) {
432*58e6ee5fSAndroid Build Coastguard Worker 		event_hash->time_min = delta;
433*58e6ee5fSAndroid Build Coastguard Worker 		event_hash->ts_min = ts;
434*58e6ee5fSAndroid Build Coastguard Worker 	}
435*58e6ee5fSAndroid Build Coastguard Worker 
436*58e6ee5fSAndroid Build Coastguard Worker 	if (start->stack.record) {
437*58e6ee5fSAndroid Build Coastguard Worker 		unsigned long size;
438*58e6ee5fSAndroid Build Coastguard Worker 		void *caller;
439*58e6ee5fSAndroid Build Coastguard Worker 
440*58e6ee5fSAndroid Build Coastguard Worker 		size = start->stack.size;
441*58e6ee5fSAndroid Build Coastguard Worker 		caller = start->stack.caller;
442*58e6ee5fSAndroid Build Coastguard Worker 
443*58e6ee5fSAndroid Build Coastguard Worker 		add_event_stack(event_hash, caller, size, delta,
444*58e6ee5fSAndroid Build Coastguard Worker 				start->stack.record->ts);
445*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(start->stack.record);
446*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.record = NULL;
447*58e6ee5fSAndroid Build Coastguard Worker 	}
448*58e6ee5fSAndroid Build Coastguard Worker 
449*58e6ee5fSAndroid Build Coastguard Worker 	free_start(start);
450*58e6ee5fSAndroid Build Coastguard Worker 
451*58e6ee5fSAndroid Build Coastguard Worker 	return event_hash;
452*58e6ee5fSAndroid Build Coastguard Worker }
453*58e6ee5fSAndroid Build Coastguard Worker 
454*58e6ee5fSAndroid Build Coastguard Worker static struct event_hash *
find_and_update_start(struct task_data * task,struct event_data * event_data,unsigned long long ts,unsigned long long search_val)455*58e6ee5fSAndroid Build Coastguard Worker find_and_update_start(struct task_data *task, struct event_data *event_data,
456*58e6ee5fSAndroid Build Coastguard Worker 		      unsigned long long ts, unsigned long long search_val)
457*58e6ee5fSAndroid Build Coastguard Worker {
458*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
459*58e6ee5fSAndroid Build Coastguard Worker 
460*58e6ee5fSAndroid Build Coastguard Worker 	start = find_start(task, event_data, search_val);
461*58e6ee5fSAndroid Build Coastguard Worker 	if (!start)
462*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
463*58e6ee5fSAndroid Build Coastguard Worker 	return add_and_free_start(task, start, event_data, ts);
464*58e6ee5fSAndroid Build Coastguard Worker }
465*58e6ee5fSAndroid Build Coastguard Worker 
match_task(struct trace_hash_item * item,void * data)466*58e6ee5fSAndroid Build Coastguard Worker static int match_task(struct trace_hash_item *item, void *data)
467*58e6ee5fSAndroid Build Coastguard Worker {
468*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task = task_from_item(item);
469*58e6ee5fSAndroid Build Coastguard Worker 	int pid = *(unsigned long *)data;
470*58e6ee5fSAndroid Build Coastguard Worker 
471*58e6ee5fSAndroid Build Coastguard Worker 	return task->pid == pid;
472*58e6ee5fSAndroid Build Coastguard Worker }
473*58e6ee5fSAndroid Build Coastguard Worker 
init_task(struct handle_data * h,struct task_data * task)474*58e6ee5fSAndroid Build Coastguard Worker static void init_task(struct handle_data *h, struct task_data *task)
475*58e6ee5fSAndroid Build Coastguard Worker {
476*58e6ee5fSAndroid Build Coastguard Worker 	task->handle = h;
477*58e6ee5fSAndroid Build Coastguard Worker 
478*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_init(&task->start_hash, 16);
479*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_init(&task->event_hash, 32);
480*58e6ee5fSAndroid Build Coastguard Worker }
481*58e6ee5fSAndroid Build Coastguard Worker 
482*58e6ee5fSAndroid Build Coastguard Worker static struct task_data *
add_task(struct handle_data * h,int pid)483*58e6ee5fSAndroid Build Coastguard Worker add_task(struct handle_data *h, int pid)
484*58e6ee5fSAndroid Build Coastguard Worker {
485*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key = trace_hash(pid);
486*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
487*58e6ee5fSAndroid Build Coastguard Worker 
488*58e6ee5fSAndroid Build Coastguard Worker 	task = malloc(sizeof(*task));
489*58e6ee5fSAndroid Build Coastguard Worker 	if (!task) {
490*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate task");
491*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
492*58e6ee5fSAndroid Build Coastguard Worker 	}
493*58e6ee5fSAndroid Build Coastguard Worker 	memset(task, 0, sizeof(*task));
494*58e6ee5fSAndroid Build Coastguard Worker 
495*58e6ee5fSAndroid Build Coastguard Worker 	task->pid = pid;
496*58e6ee5fSAndroid Build Coastguard Worker 	task->hash.key = key;
497*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_add(&h->task_hash, &task->hash);
498*58e6ee5fSAndroid Build Coastguard Worker 
499*58e6ee5fSAndroid Build Coastguard Worker 	init_task(h, task);
500*58e6ee5fSAndroid Build Coastguard Worker 
501*58e6ee5fSAndroid Build Coastguard Worker 	return task;
502*58e6ee5fSAndroid Build Coastguard Worker }
503*58e6ee5fSAndroid Build Coastguard Worker 
504*58e6ee5fSAndroid Build Coastguard Worker static struct task_data *
find_task(struct handle_data * h,int pid)505*58e6ee5fSAndroid Build Coastguard Worker find_task(struct handle_data *h, int pid)
506*58e6ee5fSAndroid Build Coastguard Worker {
507*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key = trace_hash(pid);
508*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
509*58e6ee5fSAndroid Build Coastguard Worker 	static struct task_data *last_task;
510*58e6ee5fSAndroid Build Coastguard Worker 	void *data = (unsigned long *)&pid;
511*58e6ee5fSAndroid Build Coastguard Worker 
512*58e6ee5fSAndroid Build Coastguard Worker 	if (last_task && last_task->pid == pid)
513*58e6ee5fSAndroid Build Coastguard Worker 		return last_task;
514*58e6ee5fSAndroid Build Coastguard Worker 
515*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&h->task_hash, key, match_task, data);
516*58e6ee5fSAndroid Build Coastguard Worker 
517*58e6ee5fSAndroid Build Coastguard Worker 	if (item)
518*58e6ee5fSAndroid Build Coastguard Worker 		last_task = task_from_item(item);
519*58e6ee5fSAndroid Build Coastguard Worker 	else
520*58e6ee5fSAndroid Build Coastguard Worker 		last_task = add_task(h, pid);
521*58e6ee5fSAndroid Build Coastguard Worker 
522*58e6ee5fSAndroid Build Coastguard Worker 	return last_task;
523*58e6ee5fSAndroid Build Coastguard Worker }
524*58e6ee5fSAndroid Build Coastguard Worker 
match_group(struct trace_hash_item * item,void * data)525*58e6ee5fSAndroid Build Coastguard Worker static int match_group(struct trace_hash_item *item, void *data)
526*58e6ee5fSAndroid Build Coastguard Worker {
527*58e6ee5fSAndroid Build Coastguard Worker 	struct group_data *group = group_from_item(item);
528*58e6ee5fSAndroid Build Coastguard Worker 
529*58e6ee5fSAndroid Build Coastguard Worker 	return strcmp(group->comm, (char *)data) == 0;
530*58e6ee5fSAndroid Build Coastguard Worker }
531*58e6ee5fSAndroid Build Coastguard Worker 
532*58e6ee5fSAndroid Build Coastguard Worker 
533*58e6ee5fSAndroid Build Coastguard Worker static void
add_task_comm(struct task_data * task,struct tep_format_field * field,struct tep_record * record)534*58e6ee5fSAndroid Build Coastguard Worker add_task_comm(struct task_data *task, struct tep_format_field *field,
535*58e6ee5fSAndroid Build Coastguard Worker 	      struct tep_record *record)
536*58e6ee5fSAndroid Build Coastguard Worker {
537*58e6ee5fSAndroid Build Coastguard Worker 	const char *comm;
538*58e6ee5fSAndroid Build Coastguard Worker 
539*58e6ee5fSAndroid Build Coastguard Worker 	task->comm = malloc(field->size + 1);
540*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->comm) {
541*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate task comm");
542*58e6ee5fSAndroid Build Coastguard Worker 		return;
543*58e6ee5fSAndroid Build Coastguard Worker 	}
544*58e6ee5fSAndroid Build Coastguard Worker 	comm = record->data + field->offset;
545*58e6ee5fSAndroid Build Coastguard Worker 	memcpy(task->comm, comm, field->size);
546*58e6ee5fSAndroid Build Coastguard Worker 	task->comm[field->size] = 0;
547*58e6ee5fSAndroid Build Coastguard Worker }
548*58e6ee5fSAndroid Build Coastguard Worker 
549*58e6ee5fSAndroid Build Coastguard Worker /* Account for tasks that don't have starts */
account_task(struct task_data * task,struct event_data * event_data,struct tep_record * record)550*58e6ee5fSAndroid Build Coastguard Worker static void account_task(struct task_data *task, struct event_data *event_data,
551*58e6ee5fSAndroid Build Coastguard Worker 			 struct tep_record *record)
552*58e6ee5fSAndroid Build Coastguard Worker {
553*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data_match edata;
554*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
555*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *proxy = NULL;
556*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long search_val = 0;
557*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val = 0;
558*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long pid;
559*58e6ee5fSAndroid Build Coastguard Worker 
560*58e6ee5fSAndroid Build Coastguard Worker 	/*
561*58e6ee5fSAndroid Build Coastguard Worker 	 * If an event has the pid_field set, then find that task for
562*58e6ee5fSAndroid Build Coastguard Worker 	 * this event instead. Let this task proxy for it to handle
563*58e6ee5fSAndroid Build Coastguard Worker 	 * stack traces on this event.
564*58e6ee5fSAndroid Build Coastguard Worker 	 */
565*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->pid_field) {
566*58e6ee5fSAndroid Build Coastguard Worker 		tep_read_number_field(event_data->pid_field,
567*58e6ee5fSAndroid Build Coastguard Worker 				      record->data, &pid);
568*58e6ee5fSAndroid Build Coastguard Worker 		proxy = task;
569*58e6ee5fSAndroid Build Coastguard Worker 		task = find_task(task->handle, pid);
570*58e6ee5fSAndroid Build Coastguard Worker 		if (!task)
571*58e6ee5fSAndroid Build Coastguard Worker 			return;
572*58e6ee5fSAndroid Build Coastguard Worker 		proxy->proxy = task;
573*58e6ee5fSAndroid Build Coastguard Worker 	}
574*58e6ee5fSAndroid Build Coastguard Worker 
575*58e6ee5fSAndroid Build Coastguard Worker 	/*
576*58e6ee5fSAndroid Build Coastguard Worker 	 * If data_field is defined, use that for val,
577*58e6ee5fSAndroid Build Coastguard Worker 	 * if the start_field is defined, use that for search_val.
578*58e6ee5fSAndroid Build Coastguard Worker 	 */
579*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->data_field) {
580*58e6ee5fSAndroid Build Coastguard Worker 		tep_read_number_field(event_data->data_field,
581*58e6ee5fSAndroid Build Coastguard Worker 				      record->data, &val);
582*58e6ee5fSAndroid Build Coastguard Worker 	}
583*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->start_match_field) {
584*58e6ee5fSAndroid Build Coastguard Worker 		tep_read_number_field(event_data->start_match_field,
585*58e6ee5fSAndroid Build Coastguard Worker 				      record->data, &search_val);
586*58e6ee5fSAndroid Build Coastguard Worker 	}
587*58e6ee5fSAndroid Build Coastguard Worker 
588*58e6ee5fSAndroid Build Coastguard Worker 	edata.event_data = event_data;
589*58e6ee5fSAndroid Build Coastguard Worker 	edata.search_val = val;
590*58e6ee5fSAndroid Build Coastguard Worker 	edata.val = val;
591*58e6ee5fSAndroid Build Coastguard Worker 
592*58e6ee5fSAndroid Build Coastguard Worker 	event_hash = find_event_hash(task, &edata);
593*58e6ee5fSAndroid Build Coastguard Worker 	if (!event_hash) {
594*58e6ee5fSAndroid Build Coastguard Worker 		warning("failed to allocate event_hash");
595*58e6ee5fSAndroid Build Coastguard Worker 		return;
596*58e6ee5fSAndroid Build Coastguard Worker 	}
597*58e6ee5fSAndroid Build Coastguard Worker 
598*58e6ee5fSAndroid Build Coastguard Worker 	event_hash->count++;
599*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = event_hash;
600*58e6ee5fSAndroid Build Coastguard Worker }
601*58e6ee5fSAndroid Build Coastguard Worker 
602*58e6ee5fSAndroid Build Coastguard Worker static struct task_data *
find_event_task(struct handle_data * h,struct event_data * event_data,struct tep_record * record,unsigned long long pid)603*58e6ee5fSAndroid Build Coastguard Worker find_event_task(struct handle_data *h, struct event_data *event_data,
604*58e6ee5fSAndroid Build Coastguard Worker 		struct tep_record *record, unsigned long long pid)
605*58e6ee5fSAndroid Build Coastguard Worker {
606*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->global) {
607*58e6ee5fSAndroid Build Coastguard Worker 		if (event_data->migrate)
608*58e6ee5fSAndroid Build Coastguard Worker 			return h->global_task;
609*58e6ee5fSAndroid Build Coastguard Worker 		else
610*58e6ee5fSAndroid Build Coastguard Worker 			return &h->global_percpu_tasks[record->cpu];
611*58e6ee5fSAndroid Build Coastguard Worker 	}
612*58e6ee5fSAndroid Build Coastguard Worker 
613*58e6ee5fSAndroid Build Coastguard Worker 	/* If pid_field is defined, use that to find the task */
614*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->pid_field)
615*58e6ee5fSAndroid Build Coastguard Worker 		tep_read_number_field(event_data->pid_field,
616*58e6ee5fSAndroid Build Coastguard Worker 				      record->data, &pid);
617*58e6ee5fSAndroid Build Coastguard Worker 	return find_task(h, pid);
618*58e6ee5fSAndroid Build Coastguard Worker }
619*58e6ee5fSAndroid Build Coastguard Worker 
620*58e6ee5fSAndroid Build Coastguard Worker static struct task_data *
handle_end_event(struct handle_data * h,struct event_data * event_data,struct tep_record * record,int pid)621*58e6ee5fSAndroid Build Coastguard Worker handle_end_event(struct handle_data *h, struct event_data *event_data,
622*58e6ee5fSAndroid Build Coastguard Worker 		 struct tep_record *record, int pid)
623*58e6ee5fSAndroid Build Coastguard Worker {
624*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
625*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
626*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val;
627*58e6ee5fSAndroid Build Coastguard Worker 
628*58e6ee5fSAndroid Build Coastguard Worker 	task = find_event_task(h, event_data, record, pid);
629*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
630*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
631*58e6ee5fSAndroid Build Coastguard Worker 
632*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(event_data->start_match_field, record->data,
633*58e6ee5fSAndroid Build Coastguard Worker 			      &val);
634*58e6ee5fSAndroid Build Coastguard Worker 	event_hash = find_and_update_start(task, event_data->start, record->ts, val);
635*58e6ee5fSAndroid Build Coastguard Worker 	task->last_start = NULL;
636*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = event_hash;
637*58e6ee5fSAndroid Build Coastguard Worker 
638*58e6ee5fSAndroid Build Coastguard Worker 	return task;
639*58e6ee5fSAndroid Build Coastguard Worker }
640*58e6ee5fSAndroid Build Coastguard Worker 
641*58e6ee5fSAndroid Build Coastguard Worker static struct task_data *
handle_start_event(struct handle_data * h,struct event_data * event_data,struct tep_record * record,unsigned long long pid)642*58e6ee5fSAndroid Build Coastguard Worker handle_start_event(struct handle_data *h, struct event_data *event_data,
643*58e6ee5fSAndroid Build Coastguard Worker 		   struct tep_record *record, unsigned long long pid)
644*58e6ee5fSAndroid Build Coastguard Worker {
645*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
646*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
647*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val;
648*58e6ee5fSAndroid Build Coastguard Worker 
649*58e6ee5fSAndroid Build Coastguard Worker 	task = find_event_task(h, event_data, record, pid);
650*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
651*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
652*58e6ee5fSAndroid Build Coastguard Worker 
653*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(event_data->end_match_field, record->data,
654*58e6ee5fSAndroid Build Coastguard Worker 				 &val);
655*58e6ee5fSAndroid Build Coastguard Worker 	start = add_start(task, event_data, record, val, val);
656*58e6ee5fSAndroid Build Coastguard Worker 	if (!start) {
657*58e6ee5fSAndroid Build Coastguard Worker 		warning("Failed to allocate start of task");
658*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
659*58e6ee5fSAndroid Build Coastguard Worker 	}
660*58e6ee5fSAndroid Build Coastguard Worker 
661*58e6ee5fSAndroid Build Coastguard Worker 	task->last_start = start;
662*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = NULL;
663*58e6ee5fSAndroid Build Coastguard Worker 
664*58e6ee5fSAndroid Build Coastguard Worker 	return task;
665*58e6ee5fSAndroid Build Coastguard Worker }
666*58e6ee5fSAndroid Build Coastguard Worker 
handle_event_data(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)667*58e6ee5fSAndroid Build Coastguard Worker static int handle_event_data(struct handle_data *h,
668*58e6ee5fSAndroid Build Coastguard Worker 			     unsigned long long pid,
669*58e6ee5fSAndroid Build Coastguard Worker 			     struct event_data *event_data,
670*58e6ee5fSAndroid Build Coastguard Worker 			     struct tep_record *record, int cpu)
671*58e6ee5fSAndroid Build Coastguard Worker {
672*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task = NULL;
673*58e6ee5fSAndroid Build Coastguard Worker 
674*58e6ee5fSAndroid Build Coastguard Worker 	/* If this is the end of a event pair (start is set) */
675*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->start)
676*58e6ee5fSAndroid Build Coastguard Worker 		task = handle_end_event(h, event_data, record, pid);
677*58e6ee5fSAndroid Build Coastguard Worker 
678*58e6ee5fSAndroid Build Coastguard Worker 	/* If this is the start of a event pair (end is set) */
679*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->end) {
680*58e6ee5fSAndroid Build Coastguard Worker 		task = handle_start_event(h, event_data, record, pid);
681*58e6ee5fSAndroid Build Coastguard Worker 		/* handle_start_event only returns NULL on error */
682*58e6ee5fSAndroid Build Coastguard Worker 		if (!task)
683*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
684*58e6ee5fSAndroid Build Coastguard Worker 	}
685*58e6ee5fSAndroid Build Coastguard Worker 
686*58e6ee5fSAndroid Build Coastguard Worker 	if (!task) {
687*58e6ee5fSAndroid Build Coastguard Worker 		task = find_task(h, pid);
688*58e6ee5fSAndroid Build Coastguard Worker 		if (!task)
689*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
690*58e6ee5fSAndroid Build Coastguard Worker 		task->proxy = NULL;
691*58e6ee5fSAndroid Build Coastguard Worker 		task->last_start = NULL;
692*58e6ee5fSAndroid Build Coastguard Worker 		task->last_event = NULL;
693*58e6ee5fSAndroid Build Coastguard Worker 		account_task(task, event_data, record);
694*58e6ee5fSAndroid Build Coastguard Worker 	}
695*58e6ee5fSAndroid Build Coastguard Worker 
696*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
697*58e6ee5fSAndroid Build Coastguard Worker }
698*58e6ee5fSAndroid Build Coastguard Worker 
handle_missed_events(struct handle_data * h,int cpu)699*58e6ee5fSAndroid Build Coastguard Worker static void handle_missed_events(struct handle_data *h, int cpu)
700*58e6ee5fSAndroid Build Coastguard Worker {
701*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
702*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *n;
703*58e6ee5fSAndroid Build Coastguard Worker 
704*58e6ee5fSAndroid Build Coastguard Worker 	/* Clear all starts on this CPU */
705*58e6ee5fSAndroid Build Coastguard Worker 	list_for_each_entry_safe(start, n, &h->cpu_starts[cpu], list) {
706*58e6ee5fSAndroid Build Coastguard Worker 		free_start(start);
707*58e6ee5fSAndroid Build Coastguard Worker 	}
708*58e6ee5fSAndroid Build Coastguard Worker 
709*58e6ee5fSAndroid Build Coastguard Worker 	/* Now clear all starts whose events can migrate */
710*58e6ee5fSAndroid Build Coastguard Worker 	list_for_each_entry_safe(start, n, &h->migrate_starts, list) {
711*58e6ee5fSAndroid Build Coastguard Worker 		free_start(start);
712*58e6ee5fSAndroid Build Coastguard Worker 	}
713*58e6ee5fSAndroid Build Coastguard Worker }
714*58e6ee5fSAndroid Build Coastguard Worker 
match_event_data(struct trace_hash_item * item,void * data)715*58e6ee5fSAndroid Build Coastguard Worker static int match_event_data(struct trace_hash_item *item, void *data)
716*58e6ee5fSAndroid Build Coastguard Worker {
717*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *event_data = event_data_from_item(item);
718*58e6ee5fSAndroid Build Coastguard Worker 	int id = (int)(unsigned long)data;
719*58e6ee5fSAndroid Build Coastguard Worker 
720*58e6ee5fSAndroid Build Coastguard Worker 	return event_data->id == id;
721*58e6ee5fSAndroid Build Coastguard Worker }
722*58e6ee5fSAndroid Build Coastguard Worker 
723*58e6ee5fSAndroid Build Coastguard Worker static struct event_data *
find_event_data(struct handle_data * h,int id)724*58e6ee5fSAndroid Build Coastguard Worker find_event_data(struct handle_data *h, int id)
725*58e6ee5fSAndroid Build Coastguard Worker {
726*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
727*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key = trace_hash(id);
728*58e6ee5fSAndroid Build Coastguard Worker 	void *data = (void *)(unsigned long)id;
729*58e6ee5fSAndroid Build Coastguard Worker 
730*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&h->events, key, match_event_data, data);
731*58e6ee5fSAndroid Build Coastguard Worker 	if (item)
732*58e6ee5fSAndroid Build Coastguard Worker 		return event_data_from_item(item);
733*58e6ee5fSAndroid Build Coastguard Worker 	return NULL;
734*58e6ee5fSAndroid Build Coastguard Worker }
735*58e6ee5fSAndroid Build Coastguard Worker 
trace_profile_record(struct tracecmd_input * handle,struct tep_record * record)736*58e6ee5fSAndroid Build Coastguard Worker static void trace_profile_record(struct tracecmd_input *handle,
737*58e6ee5fSAndroid Build Coastguard Worker 				 struct tep_record *record)
738*58e6ee5fSAndroid Build Coastguard Worker {
739*58e6ee5fSAndroid Build Coastguard Worker 	static struct handle_data *last_handle;
740*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_record *stack_record;
741*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *event_data;
742*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
743*58e6ee5fSAndroid Build Coastguard Worker 	struct handle_data *h;
744*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent;
745*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long pid;
746*58e6ee5fSAndroid Build Coastguard Worker 	int cpu = record->cpu;
747*58e6ee5fSAndroid Build Coastguard Worker 	int id;
748*58e6ee5fSAndroid Build Coastguard Worker 
749*58e6ee5fSAndroid Build Coastguard Worker 	if (last_handle && last_handle->handle == handle)
750*58e6ee5fSAndroid Build Coastguard Worker 		h = last_handle;
751*58e6ee5fSAndroid Build Coastguard Worker 	else {
752*58e6ee5fSAndroid Build Coastguard Worker 		for (h = handles; h; h = h->next) {
753*58e6ee5fSAndroid Build Coastguard Worker 			if (h->handle == handle)
754*58e6ee5fSAndroid Build Coastguard Worker 				break;
755*58e6ee5fSAndroid Build Coastguard Worker 		}
756*58e6ee5fSAndroid Build Coastguard Worker 		if (!h)
757*58e6ee5fSAndroid Build Coastguard Worker 			die("Handle not found?");
758*58e6ee5fSAndroid Build Coastguard Worker 		last_handle = h;
759*58e6ee5fSAndroid Build Coastguard Worker 	}
760*58e6ee5fSAndroid Build Coastguard Worker 
761*58e6ee5fSAndroid Build Coastguard Worker 	if (record->missed_events)
762*58e6ee5fSAndroid Build Coastguard Worker 		handle_missed_events(h, cpu);
763*58e6ee5fSAndroid Build Coastguard Worker 
764*58e6ee5fSAndroid Build Coastguard Worker 	pevent = h->pevent;
765*58e6ee5fSAndroid Build Coastguard Worker 
766*58e6ee5fSAndroid Build Coastguard Worker 	id = tep_data_type(pevent, record);
767*58e6ee5fSAndroid Build Coastguard Worker 
768*58e6ee5fSAndroid Build Coastguard Worker 	event_data = find_event_data(h, id);
769*58e6ee5fSAndroid Build Coastguard Worker 
770*58e6ee5fSAndroid Build Coastguard Worker 	if (!event_data)
771*58e6ee5fSAndroid Build Coastguard Worker 		return;
772*58e6ee5fSAndroid Build Coastguard Worker 
773*58e6ee5fSAndroid Build Coastguard Worker 
774*58e6ee5fSAndroid Build Coastguard Worker 	/* Get this current PID */
775*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(h->common_pid, record->data, &pid);
776*58e6ee5fSAndroid Build Coastguard Worker 
777*58e6ee5fSAndroid Build Coastguard Worker 	task = find_task(h, pid);
778*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
779*58e6ee5fSAndroid Build Coastguard Worker 		return;
780*58e6ee5fSAndroid Build Coastguard Worker 	stack_record = task->last_stack;
781*58e6ee5fSAndroid Build Coastguard Worker 
782*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->handle_event)
783*58e6ee5fSAndroid Build Coastguard Worker 		event_data->handle_event(h, pid, event_data, record, cpu);
784*58e6ee5fSAndroid Build Coastguard Worker 	else
785*58e6ee5fSAndroid Build Coastguard Worker 		handle_event_data(h, pid, event_data, record, cpu);
786*58e6ee5fSAndroid Build Coastguard Worker 
787*58e6ee5fSAndroid Build Coastguard Worker 	/* If the last stack hasn't changed, free it */
788*58e6ee5fSAndroid Build Coastguard Worker 	if (stack_record && task->last_stack == stack_record) {
789*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(stack_record);
790*58e6ee5fSAndroid Build Coastguard Worker 		task->last_stack = NULL;
791*58e6ee5fSAndroid Build Coastguard Worker 	}
792*58e6ee5fSAndroid Build Coastguard Worker }
793*58e6ee5fSAndroid Build Coastguard Worker 
794*58e6ee5fSAndroid Build Coastguard Worker static struct event_data *
add_event(struct handle_data * h,const char * system,const char * event_name,enum event_data_type type)795*58e6ee5fSAndroid Build Coastguard Worker add_event(struct handle_data *h, const char *system, const char *event_name,
796*58e6ee5fSAndroid Build Coastguard Worker 	  enum event_data_type type)
797*58e6ee5fSAndroid Build Coastguard Worker {
798*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *event_data;
799*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_event *event;
800*58e6ee5fSAndroid Build Coastguard Worker 
801*58e6ee5fSAndroid Build Coastguard Worker 	event = tep_find_event_by_name(h->pevent, system, event_name);
802*58e6ee5fSAndroid Build Coastguard Worker 	if (!event)
803*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
804*58e6ee5fSAndroid Build Coastguard Worker 
805*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->common_pid) {
806*58e6ee5fSAndroid Build Coastguard Worker 		h->common_pid = tep_find_common_field(event, "common_pid");
807*58e6ee5fSAndroid Build Coastguard Worker 		if (!h->common_pid)
808*58e6ee5fSAndroid Build Coastguard Worker 			die("No 'common_pid' found in event");
809*58e6ee5fSAndroid Build Coastguard Worker 	}
810*58e6ee5fSAndroid Build Coastguard Worker 
811*58e6ee5fSAndroid Build Coastguard Worker 	event_data = malloc(sizeof(*event_data));
812*58e6ee5fSAndroid Build Coastguard Worker 	if (!event_data) {
813*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate event_data");
814*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
815*58e6ee5fSAndroid Build Coastguard Worker 	}
816*58e6ee5fSAndroid Build Coastguard Worker 	memset(event_data, 0, sizeof(*event_data));
817*58e6ee5fSAndroid Build Coastguard Worker 	event_data->id = event->id;
818*58e6ee5fSAndroid Build Coastguard Worker 	event_data->event = event;
819*58e6ee5fSAndroid Build Coastguard Worker 	event_data->type = type;
820*58e6ee5fSAndroid Build Coastguard Worker 	event_data->hash.key = trace_hash(event_data->event->id);
821*58e6ee5fSAndroid Build Coastguard Worker 
822*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_add(&h->events, &event_data->hash);
823*58e6ee5fSAndroid Build Coastguard Worker 
824*58e6ee5fSAndroid Build Coastguard Worker 	return event_data;
825*58e6ee5fSAndroid Build Coastguard Worker }
826*58e6ee5fSAndroid Build Coastguard Worker 
827*58e6ee5fSAndroid Build Coastguard Worker static void
mate_events(struct handle_data * h,struct event_data * start,const char * pid_field,const char * end_match_field,struct event_data * end,const char * start_match_field,int migrate,int global)828*58e6ee5fSAndroid Build Coastguard Worker mate_events(struct handle_data *h, struct event_data *start,
829*58e6ee5fSAndroid Build Coastguard Worker 	    const char *pid_field, const char *end_match_field,
830*58e6ee5fSAndroid Build Coastguard Worker 	    struct event_data *end, const char *start_match_field,
831*58e6ee5fSAndroid Build Coastguard Worker 	    int migrate, int global)
832*58e6ee5fSAndroid Build Coastguard Worker {
833*58e6ee5fSAndroid Build Coastguard Worker 	start->end = end;
834*58e6ee5fSAndroid Build Coastguard Worker 	end->start = start;
835*58e6ee5fSAndroid Build Coastguard Worker 
836*58e6ee5fSAndroid Build Coastguard Worker 	if (pid_field) {
837*58e6ee5fSAndroid Build Coastguard Worker 		start->pid_field = tep_find_field(start->event, pid_field);
838*58e6ee5fSAndroid Build Coastguard Worker 		if (!start->pid_field)
839*58e6ee5fSAndroid Build Coastguard Worker 			die("Event: %s does not have field %s",
840*58e6ee5fSAndroid Build Coastguard Worker 			    start->event->name, pid_field);
841*58e6ee5fSAndroid Build Coastguard Worker 	}
842*58e6ee5fSAndroid Build Coastguard Worker 
843*58e6ee5fSAndroid Build Coastguard Worker 	/* Field to match with end */
844*58e6ee5fSAndroid Build Coastguard Worker 	start->end_match_field = tep_find_field(start->event, end_match_field);
845*58e6ee5fSAndroid Build Coastguard Worker 	if (!start->end_match_field)
846*58e6ee5fSAndroid Build Coastguard Worker 		die("Event: %s does not have field %s",
847*58e6ee5fSAndroid Build Coastguard Worker 		    start->event->name, end_match_field);
848*58e6ee5fSAndroid Build Coastguard Worker 
849*58e6ee5fSAndroid Build Coastguard Worker 	/* Field to match with start */
850*58e6ee5fSAndroid Build Coastguard Worker 	end->start_match_field = tep_find_field(end->event, start_match_field);
851*58e6ee5fSAndroid Build Coastguard Worker 	if (!end->start_match_field)
852*58e6ee5fSAndroid Build Coastguard Worker 		die("Event: %s does not have field %s",
853*58e6ee5fSAndroid Build Coastguard Worker 		    end->event->name, start_match_field);
854*58e6ee5fSAndroid Build Coastguard Worker 
855*58e6ee5fSAndroid Build Coastguard Worker 	start->migrate = migrate;
856*58e6ee5fSAndroid Build Coastguard Worker 	start->global = global;
857*58e6ee5fSAndroid Build Coastguard Worker 	end->migrate = migrate;
858*58e6ee5fSAndroid Build Coastguard Worker 	end->global = global;
859*58e6ee5fSAndroid Build Coastguard Worker }
860*58e6ee5fSAndroid Build Coastguard Worker 
861*58e6ee5fSAndroid Build Coastguard Worker /**
862*58e6ee5fSAndroid Build Coastguard Worker  * tracecmd_mate_events - match events to profile against
863*58e6ee5fSAndroid Build Coastguard Worker  * @handle: The input handle where the events exist.
864*58e6ee5fSAndroid Build Coastguard Worker  * @start_event: The event that starts the transaction
865*58e6ee5fSAndroid Build Coastguard Worker  * @pid_field: Use this over common_pid (may be NULL to use common_pid)
866*58e6ee5fSAndroid Build Coastguard Worker  * @end_match_field: The field that matches the end events @start_match_field
867*58e6ee5fSAndroid Build Coastguard Worker  * @end_event: The event that ends the transaction
868*58e6ee5fSAndroid Build Coastguard Worker  * @start_match_field: The end event field that matches start's @end_match_field
869*58e6ee5fSAndroid Build Coastguard Worker  * @migrate: Can the transaction switch CPUs? 1 for yes, 0 for no
870*58e6ee5fSAndroid Build Coastguard Worker  * @global: The events are global and not per task
871*58e6ee5fSAndroid Build Coastguard Worker  */
tracecmd_mate_events(struct tracecmd_input * handle,struct tep_event * start_event,const char * pid_field,const char * end_match_field,struct tep_event * end_event,const char * start_match_field,int migrate,int global)872*58e6ee5fSAndroid Build Coastguard Worker void tracecmd_mate_events(struct tracecmd_input *handle,
873*58e6ee5fSAndroid Build Coastguard Worker 			  struct tep_event *start_event,
874*58e6ee5fSAndroid Build Coastguard Worker 			  const char *pid_field, const char *end_match_field,
875*58e6ee5fSAndroid Build Coastguard Worker 			  struct tep_event *end_event,
876*58e6ee5fSAndroid Build Coastguard Worker 			  const char *start_match_field,
877*58e6ee5fSAndroid Build Coastguard Worker 			  int migrate, int global)
878*58e6ee5fSAndroid Build Coastguard Worker {
879*58e6ee5fSAndroid Build Coastguard Worker 	struct handle_data *h;
880*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *start;
881*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *end;
882*58e6ee5fSAndroid Build Coastguard Worker 
883*58e6ee5fSAndroid Build Coastguard Worker 	for (h = handles; h; h = h->next) {
884*58e6ee5fSAndroid Build Coastguard Worker 		if (h->handle == handle)
885*58e6ee5fSAndroid Build Coastguard Worker 			break;
886*58e6ee5fSAndroid Build Coastguard Worker 	}
887*58e6ee5fSAndroid Build Coastguard Worker 	if (!h)
888*58e6ee5fSAndroid Build Coastguard Worker 		die("Handle not found for trace profile");
889*58e6ee5fSAndroid Build Coastguard Worker 
890*58e6ee5fSAndroid Build Coastguard Worker 	start = add_event(h, start_event->system, start_event->name,
891*58e6ee5fSAndroid Build Coastguard Worker 			  EVENT_TYPE_USER_MATE);
892*58e6ee5fSAndroid Build Coastguard Worker 
893*58e6ee5fSAndroid Build Coastguard Worker 	end = add_event(h, end_event->system, end_event->name,
894*58e6ee5fSAndroid Build Coastguard Worker 			EVENT_TYPE_USER_MATE);
895*58e6ee5fSAndroid Build Coastguard Worker 
896*58e6ee5fSAndroid Build Coastguard Worker 	if (!start || !end)
897*58e6ee5fSAndroid Build Coastguard Worker 		return;
898*58e6ee5fSAndroid Build Coastguard Worker 
899*58e6ee5fSAndroid Build Coastguard Worker 	mate_events(h, start, pid_field, end_match_field, end, start_match_field,
900*58e6ee5fSAndroid Build Coastguard Worker 		    migrate, global);
901*58e6ee5fSAndroid Build Coastguard Worker }
902*58e6ee5fSAndroid Build Coastguard Worker 
func_print(struct trace_seq * s,struct event_hash * event_hash)903*58e6ee5fSAndroid Build Coastguard Worker static void func_print(struct trace_seq *s, struct event_hash *event_hash)
904*58e6ee5fSAndroid Build Coastguard Worker {
905*58e6ee5fSAndroid Build Coastguard Worker 	const char *func;
906*58e6ee5fSAndroid Build Coastguard Worker 
907*58e6ee5fSAndroid Build Coastguard Worker 	func = tep_find_function(event_hash->event_data->event->tep,
908*58e6ee5fSAndroid Build Coastguard Worker 				 event_hash->val);
909*58e6ee5fSAndroid Build Coastguard Worker 	if (func)
910*58e6ee5fSAndroid Build Coastguard Worker 		trace_seq_printf(s, "func: %s()", func);
911*58e6ee5fSAndroid Build Coastguard Worker 	else
912*58e6ee5fSAndroid Build Coastguard Worker 		trace_seq_printf(s, "func: 0x%llx", event_hash->val);
913*58e6ee5fSAndroid Build Coastguard Worker }
914*58e6ee5fSAndroid Build Coastguard Worker 
syscall_print(struct trace_seq * s,struct event_hash * event_hash)915*58e6ee5fSAndroid Build Coastguard Worker static void syscall_print(struct trace_seq *s, struct event_hash *event_hash)
916*58e6ee5fSAndroid Build Coastguard Worker {
917*58e6ee5fSAndroid Build Coastguard Worker #ifndef NO_AUDIT
918*58e6ee5fSAndroid Build Coastguard Worker 	const char *name = NULL;
919*58e6ee5fSAndroid Build Coastguard Worker 	int machine;
920*58e6ee5fSAndroid Build Coastguard Worker 
921*58e6ee5fSAndroid Build Coastguard Worker 	machine = audit_detect_machine();
922*58e6ee5fSAndroid Build Coastguard Worker 	if (machine < 0)
923*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
924*58e6ee5fSAndroid Build Coastguard Worker 	name = audit_syscall_to_name(event_hash->val, machine);
925*58e6ee5fSAndroid Build Coastguard Worker 	if (!name)
926*58e6ee5fSAndroid Build Coastguard Worker 		goto fail;
927*58e6ee5fSAndroid Build Coastguard Worker 	trace_seq_printf(s, "syscall:%s", name);
928*58e6ee5fSAndroid Build Coastguard Worker 	return;
929*58e6ee5fSAndroid Build Coastguard Worker fail:
930*58e6ee5fSAndroid Build Coastguard Worker #endif
931*58e6ee5fSAndroid Build Coastguard Worker 	trace_seq_printf(s, "%s:%d", event_hash->event_data->event->name,
932*58e6ee5fSAndroid Build Coastguard Worker 			 (int)event_hash->val);
933*58e6ee5fSAndroid Build Coastguard Worker }
934*58e6ee5fSAndroid Build Coastguard Worker 
935*58e6ee5fSAndroid Build Coastguard Worker /* From Linux include/linux/interrupt.h */
936*58e6ee5fSAndroid Build Coastguard Worker #define SOFTIRQS				\
937*58e6ee5fSAndroid Build Coastguard Worker 		C(HI),				\
938*58e6ee5fSAndroid Build Coastguard Worker 		C(TIMER),			\
939*58e6ee5fSAndroid Build Coastguard Worker 		C(NET_TX),			\
940*58e6ee5fSAndroid Build Coastguard Worker 		C(NET_RX),			\
941*58e6ee5fSAndroid Build Coastguard Worker 		C(BLOCK),			\
942*58e6ee5fSAndroid Build Coastguard Worker 		C(BLOCK_IOPOLL),		\
943*58e6ee5fSAndroid Build Coastguard Worker 		C(TASKLET),			\
944*58e6ee5fSAndroid Build Coastguard Worker 		C(SCHED),			\
945*58e6ee5fSAndroid Build Coastguard Worker 		C(HRTIMER),			\
946*58e6ee5fSAndroid Build Coastguard Worker 		C(RCU),				\
947*58e6ee5fSAndroid Build Coastguard Worker 		C(NR),
948*58e6ee5fSAndroid Build Coastguard Worker 
949*58e6ee5fSAndroid Build Coastguard Worker #undef C
950*58e6ee5fSAndroid Build Coastguard Worker #define C(a)	a##_SOFTIRQ
951*58e6ee5fSAndroid Build Coastguard Worker 
952*58e6ee5fSAndroid Build Coastguard Worker enum { SOFTIRQS };
953*58e6ee5fSAndroid Build Coastguard Worker 
954*58e6ee5fSAndroid Build Coastguard Worker #undef C
955*58e6ee5fSAndroid Build Coastguard Worker #define C(a)	#a
956*58e6ee5fSAndroid Build Coastguard Worker 
957*58e6ee5fSAndroid Build Coastguard Worker static const char *softirq_map[] = { SOFTIRQS };
958*58e6ee5fSAndroid Build Coastguard Worker 
softirq_print(struct trace_seq * s,struct event_hash * event_hash)959*58e6ee5fSAndroid Build Coastguard Worker static void softirq_print(struct trace_seq *s, struct event_hash *event_hash)
960*58e6ee5fSAndroid Build Coastguard Worker {
961*58e6ee5fSAndroid Build Coastguard Worker 	int softirq = (int)event_hash->val;
962*58e6ee5fSAndroid Build Coastguard Worker 
963*58e6ee5fSAndroid Build Coastguard Worker 	if (softirq < NR_SOFTIRQ)
964*58e6ee5fSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%s:%s", event_hash->event_data->event->name,
965*58e6ee5fSAndroid Build Coastguard Worker 				 softirq_map[softirq]);
966*58e6ee5fSAndroid Build Coastguard Worker 	else
967*58e6ee5fSAndroid Build Coastguard Worker 		trace_seq_printf(s, "%s:%d", event_hash->event_data->event->name,
968*58e6ee5fSAndroid Build Coastguard Worker 				 softirq);
969*58e6ee5fSAndroid Build Coastguard Worker }
970*58e6ee5fSAndroid Build Coastguard Worker 
sched_switch_print(struct trace_seq * s,struct event_hash * event_hash)971*58e6ee5fSAndroid Build Coastguard Worker static void sched_switch_print(struct trace_seq *s, struct event_hash *event_hash)
972*58e6ee5fSAndroid Build Coastguard Worker {
973*58e6ee5fSAndroid Build Coastguard Worker 	const char states[] = TASK_STATE_TO_CHAR_STR;
974*58e6ee5fSAndroid Build Coastguard Worker 	int i;
975*58e6ee5fSAndroid Build Coastguard Worker 
976*58e6ee5fSAndroid Build Coastguard Worker 	trace_seq_printf(s, "%s:", event_hash->event_data->event->name);
977*58e6ee5fSAndroid Build Coastguard Worker 
978*58e6ee5fSAndroid Build Coastguard Worker 	if (event_hash->val) {
979*58e6ee5fSAndroid Build Coastguard Worker 		int val = event_hash->val;
980*58e6ee5fSAndroid Build Coastguard Worker 
981*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; val && i < sizeof(states) - 1; i++, val >>= 1) {
982*58e6ee5fSAndroid Build Coastguard Worker 			if (val & 1)
983*58e6ee5fSAndroid Build Coastguard Worker 				trace_seq_putc(s, states[i+1]);
984*58e6ee5fSAndroid Build Coastguard Worker 		}
985*58e6ee5fSAndroid Build Coastguard Worker 	} else
986*58e6ee5fSAndroid Build Coastguard Worker 		trace_seq_putc(s, 'R');
987*58e6ee5fSAndroid Build Coastguard Worker }
988*58e6ee5fSAndroid Build Coastguard Worker 
handle_sched_switch_event(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)989*58e6ee5fSAndroid Build Coastguard Worker static int handle_sched_switch_event(struct handle_data *h,
990*58e6ee5fSAndroid Build Coastguard Worker 				     unsigned long long pid,
991*58e6ee5fSAndroid Build Coastguard Worker 				     struct event_data *event_data,
992*58e6ee5fSAndroid Build Coastguard Worker 				     struct tep_record *record, int cpu)
993*58e6ee5fSAndroid Build Coastguard Worker {
994*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
995*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long prev_pid;
996*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long prev_state;
997*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long next_pid;
998*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
999*58e6ee5fSAndroid Build Coastguard Worker 
1000*58e6ee5fSAndroid Build Coastguard Worker 	/* pid_field holds prev_pid, data_field holds prev_state */
1001*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(event_data->pid_field,
1002*58e6ee5fSAndroid Build Coastguard Worker 			      record->data, &prev_pid);
1003*58e6ee5fSAndroid Build Coastguard Worker 
1004*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(event_data->data_field,
1005*58e6ee5fSAndroid Build Coastguard Worker 				 record->data, &prev_state);
1006*58e6ee5fSAndroid Build Coastguard Worker 
1007*58e6ee5fSAndroid Build Coastguard Worker 	/* only care about real states */
1008*58e6ee5fSAndroid Build Coastguard Worker 	prev_state &= TASK_STATE_MAX - 1;
1009*58e6ee5fSAndroid Build Coastguard Worker 
1010*58e6ee5fSAndroid Build Coastguard Worker 	/* end_match_field holds next_pid */
1011*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(event_data->end_match_field,
1012*58e6ee5fSAndroid Build Coastguard Worker 			      record->data, &next_pid);
1013*58e6ee5fSAndroid Build Coastguard Worker 
1014*58e6ee5fSAndroid Build Coastguard Worker 	task = find_task(h, prev_pid);
1015*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1016*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1017*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->comm)
1018*58e6ee5fSAndroid Build Coastguard Worker 		add_task_comm(task, h->switch_prev_comm, record);
1019*58e6ee5fSAndroid Build Coastguard Worker 
1020*58e6ee5fSAndroid Build Coastguard Worker 	if (prev_state)
1021*58e6ee5fSAndroid Build Coastguard Worker 		task->sleeping = 1;
1022*58e6ee5fSAndroid Build Coastguard Worker 	else
1023*58e6ee5fSAndroid Build Coastguard Worker 		task->sleeping = 0;
1024*58e6ee5fSAndroid Build Coastguard Worker 
1025*58e6ee5fSAndroid Build Coastguard Worker 	/* task is being scheduled out. prev_state tells why */
1026*58e6ee5fSAndroid Build Coastguard Worker 	start = add_start(task, event_data, record, prev_pid, prev_state);
1027*58e6ee5fSAndroid Build Coastguard Worker 	task->last_start = start;
1028*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = NULL;
1029*58e6ee5fSAndroid Build Coastguard Worker 
1030*58e6ee5fSAndroid Build Coastguard Worker 	task = find_task(h, next_pid);
1031*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1032*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1033*58e6ee5fSAndroid Build Coastguard Worker 
1034*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->comm)
1035*58e6ee5fSAndroid Build Coastguard Worker 		add_task_comm(task, h->switch_next_comm, record);
1036*58e6ee5fSAndroid Build Coastguard Worker 
1037*58e6ee5fSAndroid Build Coastguard Worker 	/*
1038*58e6ee5fSAndroid Build Coastguard Worker 	 * If the next task was blocked, it required a wakeup to
1039*58e6ee5fSAndroid Build Coastguard Worker 	 * restart, and there should be one.
1040*58e6ee5fSAndroid Build Coastguard Worker 	 * But if it was preempted, we look for the previous sched switch.
1041*58e6ee5fSAndroid Build Coastguard Worker 	 * Unfortunately, we have to look for both types of events as
1042*58e6ee5fSAndroid Build Coastguard Worker 	 * we do not know why next_pid scheduled out.
1043*58e6ee5fSAndroid Build Coastguard Worker 	 *
1044*58e6ee5fSAndroid Build Coastguard Worker 	 * event_data->start holds the sched_wakeup event data.
1045*58e6ee5fSAndroid Build Coastguard Worker 	 */
1046*58e6ee5fSAndroid Build Coastguard Worker 	find_and_update_start(task, event_data->start, record->ts, next_pid);
1047*58e6ee5fSAndroid Build Coastguard Worker 
1048*58e6ee5fSAndroid Build Coastguard Worker 	/* Look for this task if it was preempted (no wakeup found). */
1049*58e6ee5fSAndroid Build Coastguard Worker 	find_and_update_start(task, event_data, record->ts, next_pid);
1050*58e6ee5fSAndroid Build Coastguard Worker 
1051*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1052*58e6ee5fSAndroid Build Coastguard Worker }
1053*58e6ee5fSAndroid Build Coastguard Worker 
handle_stacktrace_event(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)1054*58e6ee5fSAndroid Build Coastguard Worker static int handle_stacktrace_event(struct handle_data *h,
1055*58e6ee5fSAndroid Build Coastguard Worker 				   unsigned long long pid,
1056*58e6ee5fSAndroid Build Coastguard Worker 				   struct event_data *event_data,
1057*58e6ee5fSAndroid Build Coastguard Worker 				   struct tep_record *record, int cpu)
1058*58e6ee5fSAndroid Build Coastguard Worker {
1059*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *orig_task;
1060*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *proxy;
1061*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
1062*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
1063*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
1064*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
1065*58e6ee5fSAndroid Build Coastguard Worker 	void *caller;
1066*58e6ee5fSAndroid Build Coastguard Worker 
1067*58e6ee5fSAndroid Build Coastguard Worker 	task = find_task(h, pid);
1068*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1069*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1070*58e6ee5fSAndroid Build Coastguard Worker 
1071*58e6ee5fSAndroid Build Coastguard Worker 	if (task->last_stack) {
1072*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(task->last_stack);
1073*58e6ee5fSAndroid Build Coastguard Worker 		task->last_stack = NULL;
1074*58e6ee5fSAndroid Build Coastguard Worker 	}
1075*58e6ee5fSAndroid Build Coastguard Worker 
1076*58e6ee5fSAndroid Build Coastguard Worker 	if ((proxy = task->proxy)) {
1077*58e6ee5fSAndroid Build Coastguard Worker 		task->proxy = NULL;
1078*58e6ee5fSAndroid Build Coastguard Worker 		orig_task = task;
1079*58e6ee5fSAndroid Build Coastguard Worker 		task = proxy;
1080*58e6ee5fSAndroid Build Coastguard Worker 	}
1081*58e6ee5fSAndroid Build Coastguard Worker 
1082*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->last_start && !task->last_event) {
1083*58e6ee5fSAndroid Build Coastguard Worker 		/*
1084*58e6ee5fSAndroid Build Coastguard Worker 		 * Save this stack in case function graph needs it.
1085*58e6ee5fSAndroid Build Coastguard Worker 		 * Need the original task, not a proxy.
1086*58e6ee5fSAndroid Build Coastguard Worker 		 */
1087*58e6ee5fSAndroid Build Coastguard Worker 		if (proxy)
1088*58e6ee5fSAndroid Build Coastguard Worker 			task = orig_task;
1089*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_record_ref(record);
1090*58e6ee5fSAndroid Build Coastguard Worker 		task->last_stack = record;
1091*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1092*58e6ee5fSAndroid Build Coastguard Worker 	}
1093*58e6ee5fSAndroid Build Coastguard Worker 
1094*58e6ee5fSAndroid Build Coastguard Worker 	/*
1095*58e6ee5fSAndroid Build Coastguard Worker 	 * start_match_field holds the size.
1096*58e6ee5fSAndroid Build Coastguard Worker 	 * data_field holds the caller location.
1097*58e6ee5fSAndroid Build Coastguard Worker 	 */
1098*58e6ee5fSAndroid Build Coastguard Worker 	size = record->size - event_data->data_field->offset;
1099*58e6ee5fSAndroid Build Coastguard Worker 	caller = record->data + event_data->data_field->offset;
1100*58e6ee5fSAndroid Build Coastguard Worker 
1101*58e6ee5fSAndroid Build Coastguard Worker 	/*
1102*58e6ee5fSAndroid Build Coastguard Worker 	 * If there's a "start" then don't add the stack until
1103*58e6ee5fSAndroid Build Coastguard Worker 	 * it finds a matching "end".
1104*58e6ee5fSAndroid Build Coastguard Worker 	 */
1105*58e6ee5fSAndroid Build Coastguard Worker 	if ((start = task->last_start)) {
1106*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_record_ref(record);
1107*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.record = record;
1108*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.size = size;
1109*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.caller = caller;
1110*58e6ee5fSAndroid Build Coastguard Worker 		task->last_start = NULL;
1111*58e6ee5fSAndroid Build Coastguard Worker 		task->last_event = NULL;
1112*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1113*58e6ee5fSAndroid Build Coastguard Worker 	}
1114*58e6ee5fSAndroid Build Coastguard Worker 
1115*58e6ee5fSAndroid Build Coastguard Worker 	event_hash = task->last_event;
1116*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = NULL;
1117*58e6ee5fSAndroid Build Coastguard Worker 
1118*58e6ee5fSAndroid Build Coastguard Worker 	add_event_stack(event_hash, caller, size, event_hash->last_time,
1119*58e6ee5fSAndroid Build Coastguard Worker 			record->ts);
1120*58e6ee5fSAndroid Build Coastguard Worker 
1121*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1122*58e6ee5fSAndroid Build Coastguard Worker }
1123*58e6ee5fSAndroid Build Coastguard Worker 
handle_fgraph_entry_event(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)1124*58e6ee5fSAndroid Build Coastguard Worker static int handle_fgraph_entry_event(struct handle_data *h,
1125*58e6ee5fSAndroid Build Coastguard Worker 				    unsigned long long pid,
1126*58e6ee5fSAndroid Build Coastguard Worker 				    struct event_data *event_data,
1127*58e6ee5fSAndroid Build Coastguard Worker 				    struct tep_record *record, int cpu)
1128*58e6ee5fSAndroid Build Coastguard Worker {
1129*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long size;
1130*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
1131*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
1132*58e6ee5fSAndroid Build Coastguard Worker 	void *caller;
1133*58e6ee5fSAndroid Build Coastguard Worker 
1134*58e6ee5fSAndroid Build Coastguard Worker 	task = handle_start_event(h, event_data, record, pid);
1135*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1136*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1137*58e6ee5fSAndroid Build Coastguard Worker 
1138*58e6ee5fSAndroid Build Coastguard Worker 	/*
1139*58e6ee5fSAndroid Build Coastguard Worker 	 * If a stack trace hasn't been used for a previous task,
1140*58e6ee5fSAndroid Build Coastguard Worker 	 * then it could be a function trace that we can use for
1141*58e6ee5fSAndroid Build Coastguard Worker 	 * the function graph. But stack traces come before the function
1142*58e6ee5fSAndroid Build Coastguard Worker 	 * graph events (unfortunately). So we need to attach the previous
1143*58e6ee5fSAndroid Build Coastguard Worker 	 * stack trace (if there is one) to this start event.
1144*58e6ee5fSAndroid Build Coastguard Worker 	 */
1145*58e6ee5fSAndroid Build Coastguard Worker 	if (task->last_stack) {
1146*58e6ee5fSAndroid Build Coastguard Worker 		start = task->last_start;
1147*58e6ee5fSAndroid Build Coastguard Worker 		record = task->last_stack;
1148*58e6ee5fSAndroid Build Coastguard Worker 		size = record->size - stacktrace_event->data_field->offset;
1149*58e6ee5fSAndroid Build Coastguard Worker 		caller = record->data + stacktrace_event->data_field->offset;
1150*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.record = record;
1151*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.size = size;
1152*58e6ee5fSAndroid Build Coastguard Worker 		start->stack.caller = caller;
1153*58e6ee5fSAndroid Build Coastguard Worker 		task->last_stack = NULL;
1154*58e6ee5fSAndroid Build Coastguard Worker 		task->last_event = NULL;
1155*58e6ee5fSAndroid Build Coastguard Worker 	}
1156*58e6ee5fSAndroid Build Coastguard Worker 
1157*58e6ee5fSAndroid Build Coastguard Worker 	/* Do not map stacks after this event to this event */
1158*58e6ee5fSAndroid Build Coastguard Worker 	task->last_start = NULL;
1159*58e6ee5fSAndroid Build Coastguard Worker 
1160*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1161*58e6ee5fSAndroid Build Coastguard Worker }
1162*58e6ee5fSAndroid Build Coastguard Worker 
handle_fgraph_exit_event(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)1163*58e6ee5fSAndroid Build Coastguard Worker static int handle_fgraph_exit_event(struct handle_data *h,
1164*58e6ee5fSAndroid Build Coastguard Worker 				    unsigned long long pid,
1165*58e6ee5fSAndroid Build Coastguard Worker 				    struct event_data *event_data,
1166*58e6ee5fSAndroid Build Coastguard Worker 				    struct tep_record *record, int cpu)
1167*58e6ee5fSAndroid Build Coastguard Worker {
1168*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
1169*58e6ee5fSAndroid Build Coastguard Worker 
1170*58e6ee5fSAndroid Build Coastguard Worker 	task = handle_end_event(h, event_data, record, pid);
1171*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1172*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1173*58e6ee5fSAndroid Build Coastguard Worker 	/* Do not match stacks with function graph exit events */
1174*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = NULL;
1175*58e6ee5fSAndroid Build Coastguard Worker 
1176*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1177*58e6ee5fSAndroid Build Coastguard Worker }
1178*58e6ee5fSAndroid Build Coastguard Worker 
handle_process_exec(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)1179*58e6ee5fSAndroid Build Coastguard Worker static int handle_process_exec(struct handle_data *h,
1180*58e6ee5fSAndroid Build Coastguard Worker 			       unsigned long long pid,
1181*58e6ee5fSAndroid Build Coastguard Worker 			       struct event_data *event_data,
1182*58e6ee5fSAndroid Build Coastguard Worker 			       struct tep_record *record, int cpu)
1183*58e6ee5fSAndroid Build Coastguard Worker {
1184*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task;
1185*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val;
1186*58e6ee5fSAndroid Build Coastguard Worker 
1187*58e6ee5fSAndroid Build Coastguard Worker 	/* Task has execed, remove the comm for it */
1188*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->data_field) {
1189*58e6ee5fSAndroid Build Coastguard Worker 		tep_read_number_field(event_data->data_field,
1190*58e6ee5fSAndroid Build Coastguard Worker 				      record->data, &val);
1191*58e6ee5fSAndroid Build Coastguard Worker 		pid = val;
1192*58e6ee5fSAndroid Build Coastguard Worker 	}
1193*58e6ee5fSAndroid Build Coastguard Worker 
1194*58e6ee5fSAndroid Build Coastguard Worker 	task = find_task(h, pid);
1195*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1196*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1197*58e6ee5fSAndroid Build Coastguard Worker 
1198*58e6ee5fSAndroid Build Coastguard Worker 	free(task->comm);
1199*58e6ee5fSAndroid Build Coastguard Worker 	task->comm = NULL;
1200*58e6ee5fSAndroid Build Coastguard Worker 
1201*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1202*58e6ee5fSAndroid Build Coastguard Worker }
1203*58e6ee5fSAndroid Build Coastguard Worker 
handle_sched_wakeup_event(struct handle_data * h,unsigned long long pid,struct event_data * event_data,struct tep_record * record,int cpu)1204*58e6ee5fSAndroid Build Coastguard Worker static int handle_sched_wakeup_event(struct handle_data *h,
1205*58e6ee5fSAndroid Build Coastguard Worker 				     unsigned long long pid,
1206*58e6ee5fSAndroid Build Coastguard Worker 				     struct event_data *event_data,
1207*58e6ee5fSAndroid Build Coastguard Worker 				     struct tep_record *record, int cpu)
1208*58e6ee5fSAndroid Build Coastguard Worker {
1209*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *proxy;
1210*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data *task = NULL;
1211*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
1212*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long success;
1213*58e6ee5fSAndroid Build Coastguard Worker 
1214*58e6ee5fSAndroid Build Coastguard Worker 	proxy = find_task(h, pid);
1215*58e6ee5fSAndroid Build Coastguard Worker 	if (!proxy)
1216*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1217*58e6ee5fSAndroid Build Coastguard Worker 
1218*58e6ee5fSAndroid Build Coastguard Worker 	/* If present, data_field holds "success" */
1219*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->data_field) {
1220*58e6ee5fSAndroid Build Coastguard Worker 		tep_read_number_field(event_data->data_field,
1221*58e6ee5fSAndroid Build Coastguard Worker 				      record->data, &success);
1222*58e6ee5fSAndroid Build Coastguard Worker 
1223*58e6ee5fSAndroid Build Coastguard Worker 		/* If not a successful wakeup, ignore this */
1224*58e6ee5fSAndroid Build Coastguard Worker 		if (!success)
1225*58e6ee5fSAndroid Build Coastguard Worker 			return 0;
1226*58e6ee5fSAndroid Build Coastguard Worker 	}
1227*58e6ee5fSAndroid Build Coastguard Worker 
1228*58e6ee5fSAndroid Build Coastguard Worker 	tep_read_number_field(event_data->pid_field,
1229*58e6ee5fSAndroid Build Coastguard Worker 			      record->data, &pid);
1230*58e6ee5fSAndroid Build Coastguard Worker 
1231*58e6ee5fSAndroid Build Coastguard Worker 	task = find_task(h, pid);
1232*58e6ee5fSAndroid Build Coastguard Worker 	if (!task)
1233*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1234*58e6ee5fSAndroid Build Coastguard Worker 
1235*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->comm)
1236*58e6ee5fSAndroid Build Coastguard Worker 		add_task_comm(task, h->wakeup_comm, record);
1237*58e6ee5fSAndroid Build Coastguard Worker 
1238*58e6ee5fSAndroid Build Coastguard Worker 	/* if the task isn't sleeping, then ignore the wake up */
1239*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->sleeping) {
1240*58e6ee5fSAndroid Build Coastguard Worker 		/* Ignore any following stack traces */
1241*58e6ee5fSAndroid Build Coastguard Worker 		proxy->proxy = NULL;
1242*58e6ee5fSAndroid Build Coastguard Worker 		proxy->last_start = NULL;
1243*58e6ee5fSAndroid Build Coastguard Worker 		proxy->last_event = NULL;
1244*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1245*58e6ee5fSAndroid Build Coastguard Worker 	}
1246*58e6ee5fSAndroid Build Coastguard Worker 
1247*58e6ee5fSAndroid Build Coastguard Worker 	/* It's being woken up */
1248*58e6ee5fSAndroid Build Coastguard Worker 	task->sleeping = 0;
1249*58e6ee5fSAndroid Build Coastguard Worker 
1250*58e6ee5fSAndroid Build Coastguard Worker 	/*
1251*58e6ee5fSAndroid Build Coastguard Worker 	 * We need the stack trace to be hooked to the woken up
1252*58e6ee5fSAndroid Build Coastguard Worker 	 * task, not the waker.
1253*58e6ee5fSAndroid Build Coastguard Worker 	 */
1254*58e6ee5fSAndroid Build Coastguard Worker 	proxy->proxy = task;
1255*58e6ee5fSAndroid Build Coastguard Worker 
1256*58e6ee5fSAndroid Build Coastguard Worker 	/* There should be a blocked schedule out of this task */
1257*58e6ee5fSAndroid Build Coastguard Worker 	find_and_update_start(task, event_data->start, record->ts, pid);
1258*58e6ee5fSAndroid Build Coastguard Worker 
1259*58e6ee5fSAndroid Build Coastguard Worker 	/* Set this up for timing how long the wakeup takes */
1260*58e6ee5fSAndroid Build Coastguard Worker 	start = add_start(task, event_data, record, pid, pid);
1261*58e6ee5fSAndroid Build Coastguard Worker 	task->last_event = NULL;
1262*58e6ee5fSAndroid Build Coastguard Worker 	task->last_start = start;
1263*58e6ee5fSAndroid Build Coastguard Worker 
1264*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1265*58e6ee5fSAndroid Build Coastguard Worker }
1266*58e6ee5fSAndroid Build Coastguard Worker 
trace_init_profile(struct tracecmd_input * handle,struct hook_list * hook,int global)1267*58e6ee5fSAndroid Build Coastguard Worker void trace_init_profile(struct tracecmd_input *handle, struct hook_list *hook,
1268*58e6ee5fSAndroid Build Coastguard Worker 			int global)
1269*58e6ee5fSAndroid Build Coastguard Worker {
1270*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = tracecmd_get_tep(handle);
1271*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_format_field **fields;
1272*58e6ee5fSAndroid Build Coastguard Worker 	struct handle_data *h;
1273*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *event_data;
1274*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *sched_switch;
1275*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *sched_wakeup;
1276*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *irq_entry;
1277*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *irq_exit;
1278*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *softirq_entry;
1279*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *softirq_exit;
1280*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *softirq_raise;
1281*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *fgraph_entry;
1282*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *fgraph_exit;
1283*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *syscall_enter;
1284*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *syscall_exit;
1285*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *process_exec;
1286*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *start_event;
1287*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *end_event;
1288*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_event **events;
1289*58e6ee5fSAndroid Build Coastguard Worker 	int ret;
1290*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1291*58e6ee5fSAndroid Build Coastguard Worker 
1292*58e6ee5fSAndroid Build Coastguard Worker 	tracecmd_set_show_data_func(handle, trace_profile_record);
1293*58e6ee5fSAndroid Build Coastguard Worker 	h = malloc(sizeof(*h));
1294*58e6ee5fSAndroid Build Coastguard Worker 	if (!h) {
1295*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate handle");
1296*58e6ee5fSAndroid Build Coastguard Worker 		return;
1297*58e6ee5fSAndroid Build Coastguard Worker 	};
1298*58e6ee5fSAndroid Build Coastguard Worker 	memset(h, 0, sizeof(*h));
1299*58e6ee5fSAndroid Build Coastguard Worker 	h->next = handles;
1300*58e6ee5fSAndroid Build Coastguard Worker 	handles = h;
1301*58e6ee5fSAndroid Build Coastguard Worker 
1302*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_init(&h->task_hash, 1024);
1303*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_init(&h->events, 1024);
1304*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_init(&h->group_hash, 512);
1305*58e6ee5fSAndroid Build Coastguard Worker 
1306*58e6ee5fSAndroid Build Coastguard Worker 	h->handle = handle;
1307*58e6ee5fSAndroid Build Coastguard Worker 	h->pevent = pevent;
1308*58e6ee5fSAndroid Build Coastguard Worker 
1309*58e6ee5fSAndroid Build Coastguard Worker 	h->cpus = tracecmd_cpus(handle);
1310*58e6ee5fSAndroid Build Coastguard Worker 
1311*58e6ee5fSAndroid Build Coastguard Worker 	/*
1312*58e6ee5fSAndroid Build Coastguard Worker 	 * For streaming profiling, cpus will not be set up yet.
1313*58e6ee5fSAndroid Build Coastguard Worker 	 * In this case, we simply use the number of cpus on the
1314*58e6ee5fSAndroid Build Coastguard Worker 	 * system.
1315*58e6ee5fSAndroid Build Coastguard Worker 	 */
1316*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->cpus)
1317*58e6ee5fSAndroid Build Coastguard Worker 		h->cpus = tracecmd_count_cpus();
1318*58e6ee5fSAndroid Build Coastguard Worker 
1319*58e6ee5fSAndroid Build Coastguard Worker 	list_head_init(&h->migrate_starts);
1320*58e6ee5fSAndroid Build Coastguard Worker 	h->cpu_starts = malloc(sizeof(*h->cpu_starts) * h->cpus);
1321*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->cpu_starts)
1322*58e6ee5fSAndroid Build Coastguard Worker 		goto free_handle;
1323*58e6ee5fSAndroid Build Coastguard Worker 
1324*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < h->cpus; i++)
1325*58e6ee5fSAndroid Build Coastguard Worker 		list_head_init(&h->cpu_starts[i]);
1326*58e6ee5fSAndroid Build Coastguard Worker 
1327*58e6ee5fSAndroid Build Coastguard Worker 	h->cpu_data = malloc(h->cpus * sizeof(*h->cpu_data));
1328*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->cpu_data)
1329*58e6ee5fSAndroid Build Coastguard Worker 		goto free_starts;
1330*58e6ee5fSAndroid Build Coastguard Worker 
1331*58e6ee5fSAndroid Build Coastguard Worker 	memset(h->cpu_data, 0, h->cpus * sizeof(h->cpu_data));
1332*58e6ee5fSAndroid Build Coastguard Worker 
1333*58e6ee5fSAndroid Build Coastguard Worker 	h->global_task = malloc(sizeof(struct task_data));
1334*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->global_task)
1335*58e6ee5fSAndroid Build Coastguard Worker 		goto free_data;
1336*58e6ee5fSAndroid Build Coastguard Worker 
1337*58e6ee5fSAndroid Build Coastguard Worker 	memset(h->global_task, 0, sizeof(struct task_data));
1338*58e6ee5fSAndroid Build Coastguard Worker 	init_task(h, h->global_task);
1339*58e6ee5fSAndroid Build Coastguard Worker 	h->global_task->comm = strdup("Global Events");
1340*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->global_task->comm)
1341*58e6ee5fSAndroid Build Coastguard Worker 		die("malloc");
1342*58e6ee5fSAndroid Build Coastguard Worker 	h->global_task->pid = -1;
1343*58e6ee5fSAndroid Build Coastguard Worker 
1344*58e6ee5fSAndroid Build Coastguard Worker 	h->global_percpu_tasks = calloc(h->cpus, sizeof(struct task_data));
1345*58e6ee5fSAndroid Build Coastguard Worker 	if (!h->global_percpu_tasks)
1346*58e6ee5fSAndroid Build Coastguard Worker 		die("malloc");
1347*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < h->cpus; i++) {
1348*58e6ee5fSAndroid Build Coastguard Worker 		init_task(h, &h->global_percpu_tasks[i]);
1349*58e6ee5fSAndroid Build Coastguard Worker 		ret = asprintf(&h->global_percpu_tasks[i].comm,
1350*58e6ee5fSAndroid Build Coastguard Worker 			       "Global CPU[%d] Events", i);
1351*58e6ee5fSAndroid Build Coastguard Worker 		if (ret < 0)
1352*58e6ee5fSAndroid Build Coastguard Worker 			die("malloc");
1353*58e6ee5fSAndroid Build Coastguard Worker 		h->global_percpu_tasks[i].pid = -1 - i;
1354*58e6ee5fSAndroid Build Coastguard Worker 	}
1355*58e6ee5fSAndroid Build Coastguard Worker 
1356*58e6ee5fSAndroid Build Coastguard Worker 	irq_entry = add_event(h, "irq", "irq_handler_entry", EVENT_TYPE_IRQ);
1357*58e6ee5fSAndroid Build Coastguard Worker 	irq_exit = add_event(h, "irq", "irq_handler_exit", EVENT_TYPE_IRQ);
1358*58e6ee5fSAndroid Build Coastguard Worker 	softirq_entry = add_event(h, "irq", "softirq_entry", EVENT_TYPE_SOFTIRQ);
1359*58e6ee5fSAndroid Build Coastguard Worker 	softirq_exit = add_event(h, "irq", "softirq_exit", EVENT_TYPE_SOFTIRQ);
1360*58e6ee5fSAndroid Build Coastguard Worker 	softirq_raise = add_event(h, "irq", "softirq_raise", EVENT_TYPE_SOFTIRQ_RAISE);
1361*58e6ee5fSAndroid Build Coastguard Worker 	sched_wakeup = add_event(h, "sched", "sched_wakeup", EVENT_TYPE_WAKEUP);
1362*58e6ee5fSAndroid Build Coastguard Worker 	sched_switch = add_event(h, "sched", "sched_switch", EVENT_TYPE_SCHED_SWITCH);
1363*58e6ee5fSAndroid Build Coastguard Worker 	fgraph_entry = add_event(h, "ftrace", "funcgraph_entry", EVENT_TYPE_FUNC);
1364*58e6ee5fSAndroid Build Coastguard Worker 	fgraph_exit = add_event(h, "ftrace", "funcgraph_exit", EVENT_TYPE_FUNC);
1365*58e6ee5fSAndroid Build Coastguard Worker 	syscall_enter = add_event(h, "raw_syscalls", "sys_enter", EVENT_TYPE_SYSCALL);
1366*58e6ee5fSAndroid Build Coastguard Worker 	syscall_exit = add_event(h, "raw_syscalls", "sys_exit", EVENT_TYPE_SYSCALL);
1367*58e6ee5fSAndroid Build Coastguard Worker 
1368*58e6ee5fSAndroid Build Coastguard Worker 	process_exec = add_event(h, "sched", "sched_process_exec",
1369*58e6ee5fSAndroid Build Coastguard Worker 				 EVENT_TYPE_PROCESS_EXEC);
1370*58e6ee5fSAndroid Build Coastguard Worker 
1371*58e6ee5fSAndroid Build Coastguard Worker 	stacktrace_event = add_event(h, "ftrace", "kernel_stack", EVENT_TYPE_STACK);
1372*58e6ee5fSAndroid Build Coastguard Worker 	if (stacktrace_event) {
1373*58e6ee5fSAndroid Build Coastguard Worker 		stacktrace_event->handle_event = handle_stacktrace_event;
1374*58e6ee5fSAndroid Build Coastguard Worker 
1375*58e6ee5fSAndroid Build Coastguard Worker 		stacktrace_event->data_field = tep_find_field(stacktrace_event->event,
1376*58e6ee5fSAndroid Build Coastguard Worker 							    "caller");
1377*58e6ee5fSAndroid Build Coastguard Worker 		if (!stacktrace_event->data_field)
1378*58e6ee5fSAndroid Build Coastguard Worker 			die("Event: %s does not have field caller",
1379*58e6ee5fSAndroid Build Coastguard Worker 			    stacktrace_event->event->name);
1380*58e6ee5fSAndroid Build Coastguard Worker 	}
1381*58e6ee5fSAndroid Build Coastguard Worker 
1382*58e6ee5fSAndroid Build Coastguard Worker 	if (process_exec) {
1383*58e6ee5fSAndroid Build Coastguard Worker 		process_exec->handle_event = handle_process_exec;
1384*58e6ee5fSAndroid Build Coastguard Worker 		process_exec->data_field = tep_find_field(process_exec->event,
1385*58e6ee5fSAndroid Build Coastguard Worker 							     "old_pid");
1386*58e6ee5fSAndroid Build Coastguard Worker 	}
1387*58e6ee5fSAndroid Build Coastguard Worker 
1388*58e6ee5fSAndroid Build Coastguard Worker 	if (sched_switch) {
1389*58e6ee5fSAndroid Build Coastguard Worker 		sched_switch->handle_event = handle_sched_switch_event;
1390*58e6ee5fSAndroid Build Coastguard Worker 		sched_switch->data_field = tep_find_field(sched_switch->event,
1391*58e6ee5fSAndroid Build Coastguard Worker 							     "prev_state");
1392*58e6ee5fSAndroid Build Coastguard Worker 		if (!sched_switch->data_field)
1393*58e6ee5fSAndroid Build Coastguard Worker 			die("Event: %s does not have field prev_state",
1394*58e6ee5fSAndroid Build Coastguard Worker 			    sched_switch->event->name);
1395*58e6ee5fSAndroid Build Coastguard Worker 
1396*58e6ee5fSAndroid Build Coastguard Worker 		h->switch_prev_comm = tep_find_field(sched_switch->event,
1397*58e6ee5fSAndroid Build Coastguard Worker 							"prev_comm");
1398*58e6ee5fSAndroid Build Coastguard Worker 		if (!h->switch_prev_comm)
1399*58e6ee5fSAndroid Build Coastguard Worker 			die("Event: %s does not have field prev_comm",
1400*58e6ee5fSAndroid Build Coastguard Worker 			    sched_switch->event->name);
1401*58e6ee5fSAndroid Build Coastguard Worker 
1402*58e6ee5fSAndroid Build Coastguard Worker 		h->switch_next_comm = tep_find_field(sched_switch->event,
1403*58e6ee5fSAndroid Build Coastguard Worker 							"next_comm");
1404*58e6ee5fSAndroid Build Coastguard Worker 		if (!h->switch_next_comm)
1405*58e6ee5fSAndroid Build Coastguard Worker 			die("Event: %s does not have field next_comm",
1406*58e6ee5fSAndroid Build Coastguard Worker 			    sched_switch->event->name);
1407*58e6ee5fSAndroid Build Coastguard Worker 
1408*58e6ee5fSAndroid Build Coastguard Worker 		sched_switch->print_func = sched_switch_print;
1409*58e6ee5fSAndroid Build Coastguard Worker 	}
1410*58e6ee5fSAndroid Build Coastguard Worker 
1411*58e6ee5fSAndroid Build Coastguard Worker 	if (sched_switch && sched_wakeup) {
1412*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, sched_switch, "prev_pid", "next_pid",
1413*58e6ee5fSAndroid Build Coastguard Worker 			    sched_wakeup, "pid", 1, 0);
1414*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, sched_wakeup, "pid", "pid",
1415*58e6ee5fSAndroid Build Coastguard Worker 			    sched_switch, "prev_pid", 1, 0);
1416*58e6ee5fSAndroid Build Coastguard Worker 		sched_wakeup->handle_event = handle_sched_wakeup_event;
1417*58e6ee5fSAndroid Build Coastguard Worker 
1418*58e6ee5fSAndroid Build Coastguard Worker 		/* The 'success' field may or may not be present */
1419*58e6ee5fSAndroid Build Coastguard Worker 		sched_wakeup->data_field = tep_find_field(sched_wakeup->event,
1420*58e6ee5fSAndroid Build Coastguard Worker 							     "success");
1421*58e6ee5fSAndroid Build Coastguard Worker 
1422*58e6ee5fSAndroid Build Coastguard Worker 		h->wakeup_comm = tep_find_field(sched_wakeup->event, "comm");
1423*58e6ee5fSAndroid Build Coastguard Worker 		if (!h->wakeup_comm)
1424*58e6ee5fSAndroid Build Coastguard Worker 			die("Event: %s does not have field comm",
1425*58e6ee5fSAndroid Build Coastguard Worker 			    sched_wakeup->event->name);
1426*58e6ee5fSAndroid Build Coastguard Worker 	}
1427*58e6ee5fSAndroid Build Coastguard Worker 
1428*58e6ee5fSAndroid Build Coastguard Worker 	if (irq_entry && irq_exit)
1429*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, irq_entry, NULL, "irq", irq_exit, "irq", 0, global);
1430*58e6ee5fSAndroid Build Coastguard Worker 
1431*58e6ee5fSAndroid Build Coastguard Worker 	if (softirq_entry)
1432*58e6ee5fSAndroid Build Coastguard Worker 		softirq_entry->print_func = softirq_print;
1433*58e6ee5fSAndroid Build Coastguard Worker 
1434*58e6ee5fSAndroid Build Coastguard Worker 	if (softirq_exit)
1435*58e6ee5fSAndroid Build Coastguard Worker 		softirq_exit->print_func = softirq_print;
1436*58e6ee5fSAndroid Build Coastguard Worker 
1437*58e6ee5fSAndroid Build Coastguard Worker 	if (softirq_raise)
1438*58e6ee5fSAndroid Build Coastguard Worker 		softirq_raise->print_func = softirq_print;
1439*58e6ee5fSAndroid Build Coastguard Worker 
1440*58e6ee5fSAndroid Build Coastguard Worker 	if (softirq_entry && softirq_exit)
1441*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, softirq_entry, NULL, "vec", softirq_exit, "vec",
1442*58e6ee5fSAndroid Build Coastguard Worker 			    0, global);
1443*58e6ee5fSAndroid Build Coastguard Worker 
1444*58e6ee5fSAndroid Build Coastguard Worker 	if (softirq_entry && softirq_raise)
1445*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, softirq_raise, NULL, "vec", softirq_entry, "vec",
1446*58e6ee5fSAndroid Build Coastguard Worker 			    0, global);
1447*58e6ee5fSAndroid Build Coastguard Worker 
1448*58e6ee5fSAndroid Build Coastguard Worker 	if (fgraph_entry && fgraph_exit) {
1449*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, fgraph_entry, NULL, "func", fgraph_exit, "func", 1, 0);
1450*58e6ee5fSAndroid Build Coastguard Worker 		fgraph_entry->handle_event = handle_fgraph_entry_event;
1451*58e6ee5fSAndroid Build Coastguard Worker 		fgraph_exit->handle_event = handle_fgraph_exit_event;
1452*58e6ee5fSAndroid Build Coastguard Worker 		fgraph_entry->print_func = func_print;
1453*58e6ee5fSAndroid Build Coastguard Worker 	}
1454*58e6ee5fSAndroid Build Coastguard Worker 
1455*58e6ee5fSAndroid Build Coastguard Worker 	if (syscall_enter && syscall_exit) {
1456*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, syscall_enter, NULL, "id", syscall_exit, "id", 1, 0);
1457*58e6ee5fSAndroid Build Coastguard Worker 		syscall_enter->print_func = syscall_print;
1458*58e6ee5fSAndroid Build Coastguard Worker 		syscall_exit->print_func = syscall_print;
1459*58e6ee5fSAndroid Build Coastguard Worker 	}
1460*58e6ee5fSAndroid Build Coastguard Worker 
1461*58e6ee5fSAndroid Build Coastguard Worker 	events = tep_list_events(pevent, TEP_EVENT_SORT_ID);
1462*58e6ee5fSAndroid Build Coastguard Worker 	if (!events)
1463*58e6ee5fSAndroid Build Coastguard Worker 		die("malloc");
1464*58e6ee5fSAndroid Build Coastguard Worker 
1465*58e6ee5fSAndroid Build Coastguard Worker 	/* Add some other events */
1466*58e6ee5fSAndroid Build Coastguard Worker 	event_data = add_event(h, "ftrace", "function", EVENT_TYPE_FUNC);
1467*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data) {
1468*58e6ee5fSAndroid Build Coastguard Worker 		event_data->data_field =
1469*58e6ee5fSAndroid Build Coastguard Worker 			tep_find_field(event_data->event, "ip");
1470*58e6ee5fSAndroid Build Coastguard Worker 	}
1471*58e6ee5fSAndroid Build Coastguard Worker 
1472*58e6ee5fSAndroid Build Coastguard Worker 	/* Add any user defined hooks */
1473*58e6ee5fSAndroid Build Coastguard Worker 	for (; hook; hook = hook->next) {
1474*58e6ee5fSAndroid Build Coastguard Worker 		start_event = add_event(h, hook->start_system, hook->start_event,
1475*58e6ee5fSAndroid Build Coastguard Worker 					EVENT_TYPE_USER_MATE);
1476*58e6ee5fSAndroid Build Coastguard Worker 		end_event = add_event(h, hook->end_system, hook->end_event,
1477*58e6ee5fSAndroid Build Coastguard Worker 				      EVENT_TYPE_USER_MATE);
1478*58e6ee5fSAndroid Build Coastguard Worker 		if (!start_event) {
1479*58e6ee5fSAndroid Build Coastguard Worker 			warning("Event %s not found", hook->start_event);
1480*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1481*58e6ee5fSAndroid Build Coastguard Worker 		}
1482*58e6ee5fSAndroid Build Coastguard Worker 		if (!end_event) {
1483*58e6ee5fSAndroid Build Coastguard Worker 			warning("Event %s not found", hook->end_event);
1484*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1485*58e6ee5fSAndroid Build Coastguard Worker 		}
1486*58e6ee5fSAndroid Build Coastguard Worker 		mate_events(h, start_event, hook->pid, hook->start_match,
1487*58e6ee5fSAndroid Build Coastguard Worker 			    end_event, hook->end_match, hook->migrate,
1488*58e6ee5fSAndroid Build Coastguard Worker 			    hook->global);
1489*58e6ee5fSAndroid Build Coastguard Worker 	}
1490*58e6ee5fSAndroid Build Coastguard Worker 
1491*58e6ee5fSAndroid Build Coastguard Worker 	/* Now add any defined event that we haven't processed */
1492*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; events[i]; i++) {
1493*58e6ee5fSAndroid Build Coastguard Worker 		event_data = find_event_data(h, events[i]->id);
1494*58e6ee5fSAndroid Build Coastguard Worker 		if (event_data)
1495*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1496*58e6ee5fSAndroid Build Coastguard Worker 
1497*58e6ee5fSAndroid Build Coastguard Worker 		event_data = add_event(h, events[i]->system, events[i]->name,
1498*58e6ee5fSAndroid Build Coastguard Worker 				       EVENT_TYPE_UNDEFINED);
1499*58e6ee5fSAndroid Build Coastguard Worker 
1500*58e6ee5fSAndroid Build Coastguard Worker 		fields = tep_event_fields(events[i]);
1501*58e6ee5fSAndroid Build Coastguard Worker 		if (!fields)
1502*58e6ee5fSAndroid Build Coastguard Worker 			die("malloc");
1503*58e6ee5fSAndroid Build Coastguard Worker 
1504*58e6ee5fSAndroid Build Coastguard Worker 		if (fields[0])
1505*58e6ee5fSAndroid Build Coastguard Worker 			event_data->data_field = fields[0];
1506*58e6ee5fSAndroid Build Coastguard Worker 
1507*58e6ee5fSAndroid Build Coastguard Worker 		free(fields);
1508*58e6ee5fSAndroid Build Coastguard Worker 	}
1509*58e6ee5fSAndroid Build Coastguard Worker 	return;
1510*58e6ee5fSAndroid Build Coastguard Worker 
1511*58e6ee5fSAndroid Build Coastguard Worker  free_data:
1512*58e6ee5fSAndroid Build Coastguard Worker 	free(h->cpu_data);
1513*58e6ee5fSAndroid Build Coastguard Worker  free_starts:
1514*58e6ee5fSAndroid Build Coastguard Worker 	free(h->cpu_starts);
1515*58e6ee5fSAndroid Build Coastguard Worker  free_handle:
1516*58e6ee5fSAndroid Build Coastguard Worker 	handles = h->next;
1517*58e6ee5fSAndroid Build Coastguard Worker 	free(h);
1518*58e6ee5fSAndroid Build Coastguard Worker 	warning("Failed handle allocations");
1519*58e6ee5fSAndroid Build Coastguard Worker }
1520*58e6ee5fSAndroid Build Coastguard Worker 
output_event_stack(struct tep_handle * pevent,struct stack_data * stack)1521*58e6ee5fSAndroid Build Coastguard Worker static void output_event_stack(struct tep_handle *pevent, struct stack_data *stack)
1522*58e6ee5fSAndroid Build Coastguard Worker {
1523*58e6ee5fSAndroid Build Coastguard Worker 	int longsize = tep_get_long_size(pevent);
1524*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val;
1525*58e6ee5fSAndroid Build Coastguard Worker 	const char *func;
1526*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long stop = -1ULL;
1527*58e6ee5fSAndroid Build Coastguard Worker 	void *ptr;
1528*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1529*58e6ee5fSAndroid Build Coastguard Worker 
1530*58e6ee5fSAndroid Build Coastguard Worker 	if (longsize < 8)
1531*58e6ee5fSAndroid Build Coastguard Worker 		stop &= (1ULL << (longsize * 8)) - 1;
1532*58e6ee5fSAndroid Build Coastguard Worker 
1533*58e6ee5fSAndroid Build Coastguard Worker 	if (stack->count)
1534*58e6ee5fSAndroid Build Coastguard Worker 		stack->time_avg = stack->time / stack->count;
1535*58e6ee5fSAndroid Build Coastguard Worker 
1536*58e6ee5fSAndroid Build Coastguard Worker 	printf("     <stack> %lld total:%lld min:%lld(ts:%lld.%06lld) max:%lld(ts:%lld.%06lld) avg=%lld\n",
1537*58e6ee5fSAndroid Build Coastguard Worker 	       stack->count, stack->time, stack->time_min,
1538*58e6ee5fSAndroid Build Coastguard Worker 	       nsecs_per_sec(stack->ts_min), mod_to_usec(stack->ts_min),
1539*58e6ee5fSAndroid Build Coastguard Worker 	       stack->time_max,
1540*58e6ee5fSAndroid Build Coastguard Worker 	       nsecs_per_sec(stack->ts_max), mod_to_usec(stack->ts_max),
1541*58e6ee5fSAndroid Build Coastguard Worker 	       stack->time_avg);
1542*58e6ee5fSAndroid Build Coastguard Worker 
1543*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < stack->size; i += longsize) {
1544*58e6ee5fSAndroid Build Coastguard Worker 		ptr = stack->caller + i;
1545*58e6ee5fSAndroid Build Coastguard Worker 		switch (longsize) {
1546*58e6ee5fSAndroid Build Coastguard Worker 		case 4:
1547*58e6ee5fSAndroid Build Coastguard Worker 			/* todo, read value from pevent */
1548*58e6ee5fSAndroid Build Coastguard Worker 			val = *(unsigned int *)ptr;
1549*58e6ee5fSAndroid Build Coastguard Worker 			break;
1550*58e6ee5fSAndroid Build Coastguard Worker 		case 8:
1551*58e6ee5fSAndroid Build Coastguard Worker 			val = *(unsigned long long *)ptr;
1552*58e6ee5fSAndroid Build Coastguard Worker 			break;
1553*58e6ee5fSAndroid Build Coastguard Worker 		default:
1554*58e6ee5fSAndroid Build Coastguard Worker 			die("Strange long size %d", longsize);
1555*58e6ee5fSAndroid Build Coastguard Worker 		}
1556*58e6ee5fSAndroid Build Coastguard Worker 		if (val == stop)
1557*58e6ee5fSAndroid Build Coastguard Worker 			break;
1558*58e6ee5fSAndroid Build Coastguard Worker 		func = tep_find_function(pevent, val);
1559*58e6ee5fSAndroid Build Coastguard Worker 		if (func)
1560*58e6ee5fSAndroid Build Coastguard Worker 			printf("       => %s (0x%llx)\n", func, val);
1561*58e6ee5fSAndroid Build Coastguard Worker 		else
1562*58e6ee5fSAndroid Build Coastguard Worker 			printf("       => 0x%llx\n", val);
1563*58e6ee5fSAndroid Build Coastguard Worker 	}
1564*58e6ee5fSAndroid Build Coastguard Worker }
1565*58e6ee5fSAndroid Build Coastguard Worker 
1566*58e6ee5fSAndroid Build Coastguard Worker struct stack_chain {
1567*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_chain *children;
1568*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	val;
1569*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time;
1570*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_min;
1571*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_min;
1572*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_max;
1573*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_max;
1574*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_avg;
1575*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	count;
1576*58e6ee5fSAndroid Build Coastguard Worker 	int			percent;
1577*58e6ee5fSAndroid Build Coastguard Worker 	int			nr_children;
1578*58e6ee5fSAndroid Build Coastguard Worker };
1579*58e6ee5fSAndroid Build Coastguard Worker 
compare_chains(const void * a,const void * b)1580*58e6ee5fSAndroid Build Coastguard Worker static int compare_chains(const void *a, const void *b)
1581*58e6ee5fSAndroid Build Coastguard Worker {
1582*58e6ee5fSAndroid Build Coastguard Worker 	const struct stack_chain * A = a;
1583*58e6ee5fSAndroid Build Coastguard Worker 	const struct stack_chain * B = b;
1584*58e6ee5fSAndroid Build Coastguard Worker 
1585*58e6ee5fSAndroid Build Coastguard Worker 	if (A->time > B->time)
1586*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1587*58e6ee5fSAndroid Build Coastguard Worker 	if (A->time < B->time)
1588*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
1589*58e6ee5fSAndroid Build Coastguard Worker 	/* If stacks don't use time, then use count */
1590*58e6ee5fSAndroid Build Coastguard Worker 	if (A->count > B->count)
1591*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1592*58e6ee5fSAndroid Build Coastguard Worker 	if (A->count < B->count)
1593*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
1594*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1595*58e6ee5fSAndroid Build Coastguard Worker }
1596*58e6ee5fSAndroid Build Coastguard Worker 
calc_percent(unsigned long long val,unsigned long long total)1597*58e6ee5fSAndroid Build Coastguard Worker static int calc_percent(unsigned long long val, unsigned long long total)
1598*58e6ee5fSAndroid Build Coastguard Worker {
1599*58e6ee5fSAndroid Build Coastguard Worker 	return (val * 100 + total / 2) / total;
1600*58e6ee5fSAndroid Build Coastguard Worker }
1601*58e6ee5fSAndroid Build Coastguard Worker 
stack_overflows(struct stack_data * stack,int longsize,int level)1602*58e6ee5fSAndroid Build Coastguard Worker static int stack_overflows(struct stack_data *stack, int longsize, int level)
1603*58e6ee5fSAndroid Build Coastguard Worker {
1604*58e6ee5fSAndroid Build Coastguard Worker 	return longsize * level > stack->size - longsize;
1605*58e6ee5fSAndroid Build Coastguard Worker }
1606*58e6ee5fSAndroid Build Coastguard Worker 
1607*58e6ee5fSAndroid Build Coastguard Worker static unsigned long long
stack_value(struct stack_data * stack,int longsize,int level)1608*58e6ee5fSAndroid Build Coastguard Worker stack_value(struct stack_data *stack, int longsize, int level)
1609*58e6ee5fSAndroid Build Coastguard Worker {
1610*58e6ee5fSAndroid Build Coastguard Worker 	void *ptr;
1611*58e6ee5fSAndroid Build Coastguard Worker 
1612*58e6ee5fSAndroid Build Coastguard Worker 	ptr = &stack->caller[longsize * level];
1613*58e6ee5fSAndroid Build Coastguard Worker 	return longsize == 8 ? *(u64 *)ptr : *(unsigned *)ptr;
1614*58e6ee5fSAndroid Build Coastguard Worker }
1615*58e6ee5fSAndroid Build Coastguard Worker 
1616*58e6ee5fSAndroid Build Coastguard Worker static struct stack_chain *
make_stack_chain(struct stack_data ** stacks,int cnt,int longsize,int level,int * nr_children)1617*58e6ee5fSAndroid Build Coastguard Worker make_stack_chain(struct stack_data **stacks, int cnt, int longsize, int level,
1618*58e6ee5fSAndroid Build Coastguard Worker 		 int *nr_children)
1619*58e6ee5fSAndroid Build Coastguard Worker {
1620*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_chain *chain;
1621*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	total_time = 0;
1622*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	total_count = 0;
1623*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time;
1624*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_min;
1625*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_min;
1626*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	time_max;
1627*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	ts_max;
1628*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	count;
1629*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long	stop = -1ULL;
1630*58e6ee5fSAndroid Build Coastguard Worker 	int nr_chains = 0;
1631*58e6ee5fSAndroid Build Coastguard Worker 	u64 last = 0;
1632*58e6ee5fSAndroid Build Coastguard Worker 	u64 val;
1633*58e6ee5fSAndroid Build Coastguard Worker 	int start;
1634*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1635*58e6ee5fSAndroid Build Coastguard Worker 	int x;
1636*58e6ee5fSAndroid Build Coastguard Worker 
1637*58e6ee5fSAndroid Build Coastguard Worker 	if (longsize < 8)
1638*58e6ee5fSAndroid Build Coastguard Worker 		stop &= (1ULL << (longsize * 8)) - 1;
1639*58e6ee5fSAndroid Build Coastguard Worker 
1640*58e6ee5fSAndroid Build Coastguard Worker 	/* First find out how many diffs there are */
1641*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < cnt; i++) {
1642*58e6ee5fSAndroid Build Coastguard Worker 		if (stack_overflows(stacks[i], longsize, level))
1643*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1644*58e6ee5fSAndroid Build Coastguard Worker 
1645*58e6ee5fSAndroid Build Coastguard Worker 		val = stack_value(stacks[i], longsize, level);
1646*58e6ee5fSAndroid Build Coastguard Worker 
1647*58e6ee5fSAndroid Build Coastguard Worker 		if (val == stop)
1648*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1649*58e6ee5fSAndroid Build Coastguard Worker 
1650*58e6ee5fSAndroid Build Coastguard Worker 		if (!nr_chains || val != last)
1651*58e6ee5fSAndroid Build Coastguard Worker 			nr_chains++;
1652*58e6ee5fSAndroid Build Coastguard Worker 		last = val;
1653*58e6ee5fSAndroid Build Coastguard Worker 	}
1654*58e6ee5fSAndroid Build Coastguard Worker 
1655*58e6ee5fSAndroid Build Coastguard Worker 	if (!nr_chains) {
1656*58e6ee5fSAndroid Build Coastguard Worker 		*nr_children = 0;
1657*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1658*58e6ee5fSAndroid Build Coastguard Worker 	}
1659*58e6ee5fSAndroid Build Coastguard Worker 
1660*58e6ee5fSAndroid Build Coastguard Worker 	chain = malloc(sizeof(*chain) * nr_chains);
1661*58e6ee5fSAndroid Build Coastguard Worker 	if (!chain) {
1662*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate chain");
1663*58e6ee5fSAndroid Build Coastguard Worker 		return NULL;
1664*58e6ee5fSAndroid Build Coastguard Worker 	}
1665*58e6ee5fSAndroid Build Coastguard Worker 	memset(chain, 0, sizeof(*chain) * nr_chains);
1666*58e6ee5fSAndroid Build Coastguard Worker 
1667*58e6ee5fSAndroid Build Coastguard Worker 	x = 0;
1668*58e6ee5fSAndroid Build Coastguard Worker 	count = 0;
1669*58e6ee5fSAndroid Build Coastguard Worker 	start = 0;
1670*58e6ee5fSAndroid Build Coastguard Worker 	time = 0;
1671*58e6ee5fSAndroid Build Coastguard Worker 	time_min = 0;
1672*58e6ee5fSAndroid Build Coastguard Worker 	time_max = 0;
1673*58e6ee5fSAndroid Build Coastguard Worker 
1674*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < cnt; i++) {
1675*58e6ee5fSAndroid Build Coastguard Worker 		if (stack_overflows(stacks[i], longsize, level)) {
1676*58e6ee5fSAndroid Build Coastguard Worker 			start = i+1;
1677*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1678*58e6ee5fSAndroid Build Coastguard Worker 		}
1679*58e6ee5fSAndroid Build Coastguard Worker 
1680*58e6ee5fSAndroid Build Coastguard Worker 		val = stack_value(stacks[i], longsize, level);
1681*58e6ee5fSAndroid Build Coastguard Worker 
1682*58e6ee5fSAndroid Build Coastguard Worker 		if (val == stop) {
1683*58e6ee5fSAndroid Build Coastguard Worker 			start = i+1;
1684*58e6ee5fSAndroid Build Coastguard Worker 			continue;
1685*58e6ee5fSAndroid Build Coastguard Worker 		}
1686*58e6ee5fSAndroid Build Coastguard Worker 
1687*58e6ee5fSAndroid Build Coastguard Worker 		count += stacks[i]->count;
1688*58e6ee5fSAndroid Build Coastguard Worker 		time += stacks[i]->time;
1689*58e6ee5fSAndroid Build Coastguard Worker 		if (stacks[i]->time_max > time_max) {
1690*58e6ee5fSAndroid Build Coastguard Worker 			time_max = stacks[i]->time_max;
1691*58e6ee5fSAndroid Build Coastguard Worker 			ts_max = stacks[i]->ts_max;
1692*58e6ee5fSAndroid Build Coastguard Worker 		}
1693*58e6ee5fSAndroid Build Coastguard Worker 		if (i == start || stacks[i]->time_min < time_min) {
1694*58e6ee5fSAndroid Build Coastguard Worker 			time_min = stacks[i]->time_min;
1695*58e6ee5fSAndroid Build Coastguard Worker 			ts_min = stacks[i]->ts_min;
1696*58e6ee5fSAndroid Build Coastguard Worker 		}
1697*58e6ee5fSAndroid Build Coastguard Worker 		if (i == cnt - 1 ||
1698*58e6ee5fSAndroid Build Coastguard Worker 		    stack_overflows(stacks[i+1], longsize, level) ||
1699*58e6ee5fSAndroid Build Coastguard Worker 		    val != stack_value(stacks[i+1], longsize, level)) {
1700*58e6ee5fSAndroid Build Coastguard Worker 
1701*58e6ee5fSAndroid Build Coastguard Worker 			total_time += time;
1702*58e6ee5fSAndroid Build Coastguard Worker 			total_count += count;
1703*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].val = val;
1704*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].time_avg = time / count;
1705*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].count = count;
1706*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].time = time;
1707*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].time_min = time_min;
1708*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].ts_min = ts_min;
1709*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].time_max = time_max;
1710*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].ts_max = ts_max;
1711*58e6ee5fSAndroid Build Coastguard Worker 			chain[x].children =
1712*58e6ee5fSAndroid Build Coastguard Worker 				make_stack_chain(&stacks[start], (i - start) + 1,
1713*58e6ee5fSAndroid Build Coastguard Worker 						 longsize, level+1,
1714*58e6ee5fSAndroid Build Coastguard Worker 						 &chain[x].nr_children);
1715*58e6ee5fSAndroid Build Coastguard Worker 			x++;
1716*58e6ee5fSAndroid Build Coastguard Worker 			start = i + 1;
1717*58e6ee5fSAndroid Build Coastguard Worker 			count = 0;
1718*58e6ee5fSAndroid Build Coastguard Worker 			time = 0;
1719*58e6ee5fSAndroid Build Coastguard Worker 			time_min = 0;
1720*58e6ee5fSAndroid Build Coastguard Worker 			time_max = 0;
1721*58e6ee5fSAndroid Build Coastguard Worker 		}
1722*58e6ee5fSAndroid Build Coastguard Worker 	}
1723*58e6ee5fSAndroid Build Coastguard Worker 
1724*58e6ee5fSAndroid Build Coastguard Worker 	qsort(chain, nr_chains, sizeof(*chain), compare_chains);
1725*58e6ee5fSAndroid Build Coastguard Worker 
1726*58e6ee5fSAndroid Build Coastguard Worker 	*nr_children = nr_chains;
1727*58e6ee5fSAndroid Build Coastguard Worker 
1728*58e6ee5fSAndroid Build Coastguard Worker 	/* Should never happen */
1729*58e6ee5fSAndroid Build Coastguard Worker 	if (!total_time && !total_count)
1730*58e6ee5fSAndroid Build Coastguard Worker 		return chain;
1731*58e6ee5fSAndroid Build Coastguard Worker 
1732*58e6ee5fSAndroid Build Coastguard Worker 
1733*58e6ee5fSAndroid Build Coastguard Worker 	/* Now calculate percentage */
1734*58e6ee5fSAndroid Build Coastguard Worker 	time = 0;
1735*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_chains; i++) {
1736*58e6ee5fSAndroid Build Coastguard Worker 		if (total_time)
1737*58e6ee5fSAndroid Build Coastguard Worker 			chain[i].percent = calc_percent(chain[i].time, total_time);
1738*58e6ee5fSAndroid Build Coastguard Worker 		/* In case stacks don't have time */
1739*58e6ee5fSAndroid Build Coastguard Worker 		else if (total_count)
1740*58e6ee5fSAndroid Build Coastguard Worker 			chain[i].percent = calc_percent(chain[i].count, total_count);
1741*58e6ee5fSAndroid Build Coastguard Worker 	}
1742*58e6ee5fSAndroid Build Coastguard Worker 
1743*58e6ee5fSAndroid Build Coastguard Worker 	return chain;
1744*58e6ee5fSAndroid Build Coastguard Worker }
1745*58e6ee5fSAndroid Build Coastguard Worker 
free_chain(struct stack_chain * chain,int nr_chains)1746*58e6ee5fSAndroid Build Coastguard Worker static void free_chain(struct stack_chain *chain, int nr_chains)
1747*58e6ee5fSAndroid Build Coastguard Worker {
1748*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1749*58e6ee5fSAndroid Build Coastguard Worker 
1750*58e6ee5fSAndroid Build Coastguard Worker 	if (!chain)
1751*58e6ee5fSAndroid Build Coastguard Worker 		return;
1752*58e6ee5fSAndroid Build Coastguard Worker 
1753*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_chains; i++)
1754*58e6ee5fSAndroid Build Coastguard Worker 		free_chain(chain[i].children, chain[i].nr_children);
1755*58e6ee5fSAndroid Build Coastguard Worker 
1756*58e6ee5fSAndroid Build Coastguard Worker 	free(chain);
1757*58e6ee5fSAndroid Build Coastguard Worker }
1758*58e6ee5fSAndroid Build Coastguard Worker 
1759*58e6ee5fSAndroid Build Coastguard Worker #define INDENT	5
1760*58e6ee5fSAndroid Build Coastguard Worker 
print_indent(int level,unsigned long long mask)1761*58e6ee5fSAndroid Build Coastguard Worker static void print_indent(int level, unsigned long long mask)
1762*58e6ee5fSAndroid Build Coastguard Worker {
1763*58e6ee5fSAndroid Build Coastguard Worker 	char line;
1764*58e6ee5fSAndroid Build Coastguard Worker 	int p;
1765*58e6ee5fSAndroid Build Coastguard Worker 
1766*58e6ee5fSAndroid Build Coastguard Worker 	for (p = 0; p < level + 1; p++) {
1767*58e6ee5fSAndroid Build Coastguard Worker 		if (mask & (1ULL << p))
1768*58e6ee5fSAndroid Build Coastguard Worker 			line = '|';
1769*58e6ee5fSAndroid Build Coastguard Worker 		else
1770*58e6ee5fSAndroid Build Coastguard Worker 			line = ' ';
1771*58e6ee5fSAndroid Build Coastguard Worker 		printf("%*c ", INDENT, line);
1772*58e6ee5fSAndroid Build Coastguard Worker 	}
1773*58e6ee5fSAndroid Build Coastguard Worker }
1774*58e6ee5fSAndroid Build Coastguard Worker 
print_chain_func(struct tep_handle * pevent,struct stack_chain * chain)1775*58e6ee5fSAndroid Build Coastguard Worker static void print_chain_func(struct tep_handle *pevent, struct stack_chain *chain)
1776*58e6ee5fSAndroid Build Coastguard Worker {
1777*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long val = chain->val;
1778*58e6ee5fSAndroid Build Coastguard Worker 	const char *func;
1779*58e6ee5fSAndroid Build Coastguard Worker 
1780*58e6ee5fSAndroid Build Coastguard Worker 	func = tep_find_function(pevent, val);
1781*58e6ee5fSAndroid Build Coastguard Worker 	if (func)
1782*58e6ee5fSAndroid Build Coastguard Worker 		printf("%s (0x%llx)\n", func, val);
1783*58e6ee5fSAndroid Build Coastguard Worker 	else
1784*58e6ee5fSAndroid Build Coastguard Worker 		printf("0x%llx\n", val);
1785*58e6ee5fSAndroid Build Coastguard Worker }
1786*58e6ee5fSAndroid Build Coastguard Worker 
output_chain(struct tep_handle * pevent,struct stack_chain * chain,int level,int nr_chains,unsigned long long * mask)1787*58e6ee5fSAndroid Build Coastguard Worker static void output_chain(struct tep_handle *pevent, struct stack_chain *chain, int level,
1788*58e6ee5fSAndroid Build Coastguard Worker 			 int nr_chains, unsigned long long *mask)
1789*58e6ee5fSAndroid Build Coastguard Worker {
1790*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_chain *child;
1791*58e6ee5fSAndroid Build Coastguard Worker 	int nr_children;
1792*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1793*58e6ee5fSAndroid Build Coastguard Worker 	char line = '|';
1794*58e6ee5fSAndroid Build Coastguard Worker 
1795*58e6ee5fSAndroid Build Coastguard Worker 	if (!nr_chains)
1796*58e6ee5fSAndroid Build Coastguard Worker 		return;
1797*58e6ee5fSAndroid Build Coastguard Worker 
1798*58e6ee5fSAndroid Build Coastguard Worker 	*mask |= (1ULL << (level + 1));
1799*58e6ee5fSAndroid Build Coastguard Worker 	print_indent(level + 1, *mask);
1800*58e6ee5fSAndroid Build Coastguard Worker 	printf("\n");
1801*58e6ee5fSAndroid Build Coastguard Worker 
1802*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_chains; i++) {
1803*58e6ee5fSAndroid Build Coastguard Worker 
1804*58e6ee5fSAndroid Build Coastguard Worker 		print_indent(level, *mask);
1805*58e6ee5fSAndroid Build Coastguard Worker 
1806*58e6ee5fSAndroid Build Coastguard Worker 		printf("%*c ", INDENT, '+');
1807*58e6ee5fSAndroid Build Coastguard Worker 
1808*58e6ee5fSAndroid Build Coastguard Worker 		if (i == nr_chains - 1) {
1809*58e6ee5fSAndroid Build Coastguard Worker 			*mask &= ~(1ULL << (level + 1));
1810*58e6ee5fSAndroid Build Coastguard Worker 			line = ' ';
1811*58e6ee5fSAndroid Build Coastguard Worker 		}
1812*58e6ee5fSAndroid Build Coastguard Worker 
1813*58e6ee5fSAndroid Build Coastguard Worker 		print_chain_func(pevent, &chain[i]);
1814*58e6ee5fSAndroid Build Coastguard Worker 
1815*58e6ee5fSAndroid Build Coastguard Worker 		print_indent(level, *mask);
1816*58e6ee5fSAndroid Build Coastguard Worker 
1817*58e6ee5fSAndroid Build Coastguard Worker 		printf("%*c ", INDENT, line);
1818*58e6ee5fSAndroid Build Coastguard Worker 		printf("  %d%% (%lld)", chain[i].percent, chain[i].count);
1819*58e6ee5fSAndroid Build Coastguard Worker 		if (chain[i].time)
1820*58e6ee5fSAndroid Build Coastguard Worker 			printf(" time:%lld max:%lld(ts:%lld.%06lld) min:%lld(ts:%lld.%06lld) avg:%lld",
1821*58e6ee5fSAndroid Build Coastguard Worker 			       chain[i].time, chain[i].time_max,
1822*58e6ee5fSAndroid Build Coastguard Worker 			       nsecs_per_sec(chain[i].ts_max),
1823*58e6ee5fSAndroid Build Coastguard Worker 			       mod_to_usec(chain[i].ts_max),
1824*58e6ee5fSAndroid Build Coastguard Worker 			       chain[i].time_min,
1825*58e6ee5fSAndroid Build Coastguard Worker 			       nsecs_per_sec(chain[i].ts_min),
1826*58e6ee5fSAndroid Build Coastguard Worker 			       mod_to_usec(chain[i].ts_min),
1827*58e6ee5fSAndroid Build Coastguard Worker 			       chain[i].time_avg);
1828*58e6ee5fSAndroid Build Coastguard Worker 		printf("\n");
1829*58e6ee5fSAndroid Build Coastguard Worker 
1830*58e6ee5fSAndroid Build Coastguard Worker 		for (child = chain[i].children, nr_children = chain[i].nr_children;
1831*58e6ee5fSAndroid Build Coastguard Worker 		     child && nr_children == 1;
1832*58e6ee5fSAndroid Build Coastguard Worker 		     nr_children = child->nr_children, child = child->children) {
1833*58e6ee5fSAndroid Build Coastguard Worker 			print_indent(level, *mask);
1834*58e6ee5fSAndroid Build Coastguard Worker 			printf("%*c ", INDENT, line);
1835*58e6ee5fSAndroid Build Coastguard Worker 			printf("   ");
1836*58e6ee5fSAndroid Build Coastguard Worker 			print_chain_func(pevent, child);
1837*58e6ee5fSAndroid Build Coastguard Worker 		}
1838*58e6ee5fSAndroid Build Coastguard Worker 
1839*58e6ee5fSAndroid Build Coastguard Worker 		if (child)
1840*58e6ee5fSAndroid Build Coastguard Worker 			output_chain(pevent, child, level+1, nr_children, mask);
1841*58e6ee5fSAndroid Build Coastguard Worker 
1842*58e6ee5fSAndroid Build Coastguard Worker 		print_indent(level + 1, *mask);
1843*58e6ee5fSAndroid Build Coastguard Worker 		printf("\n");
1844*58e6ee5fSAndroid Build Coastguard Worker 	}
1845*58e6ee5fSAndroid Build Coastguard Worker 	*mask &= ~(1ULL << (level + 1));
1846*58e6ee5fSAndroid Build Coastguard Worker 	print_indent(level, *mask);
1847*58e6ee5fSAndroid Build Coastguard Worker 	printf("\n");
1848*58e6ee5fSAndroid Build Coastguard Worker }
1849*58e6ee5fSAndroid Build Coastguard Worker 
compare_stacks(const void * a,const void * b)1850*58e6ee5fSAndroid Build Coastguard Worker static int compare_stacks(const void *a, const void *b)
1851*58e6ee5fSAndroid Build Coastguard Worker {
1852*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data * const *A = a;
1853*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data * const *B = b;
1854*58e6ee5fSAndroid Build Coastguard Worker 	unsigned int sa, sb;
1855*58e6ee5fSAndroid Build Coastguard Worker 	int size;
1856*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1857*58e6ee5fSAndroid Build Coastguard Worker 
1858*58e6ee5fSAndroid Build Coastguard Worker 	/* only compare up to the smaller size of the two */
1859*58e6ee5fSAndroid Build Coastguard Worker 	if ((*A)->size > (*B)->size)
1860*58e6ee5fSAndroid Build Coastguard Worker 		size = (*B)->size;
1861*58e6ee5fSAndroid Build Coastguard Worker 	else
1862*58e6ee5fSAndroid Build Coastguard Worker 		size = (*A)->size;
1863*58e6ee5fSAndroid Build Coastguard Worker 
1864*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < size; i += sizeof(sa)) {
1865*58e6ee5fSAndroid Build Coastguard Worker 		sa = *(unsigned *)&(*A)->caller[i];
1866*58e6ee5fSAndroid Build Coastguard Worker 		sb = *(unsigned *)&(*B)->caller[i];
1867*58e6ee5fSAndroid Build Coastguard Worker 		if (sa > sb)
1868*58e6ee5fSAndroid Build Coastguard Worker 			return 1;
1869*58e6ee5fSAndroid Build Coastguard Worker 		if (sa < sb)
1870*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1871*58e6ee5fSAndroid Build Coastguard Worker 	}
1872*58e6ee5fSAndroid Build Coastguard Worker 
1873*58e6ee5fSAndroid Build Coastguard Worker 	/* They are the same up to size. Then bigger size wins */
1874*58e6ee5fSAndroid Build Coastguard Worker 	if ((*A)->size > (*B)->size)
1875*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
1876*58e6ee5fSAndroid Build Coastguard Worker 	if ((*A)->size < (*B)->size)
1877*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1878*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
1879*58e6ee5fSAndroid Build Coastguard Worker }
1880*58e6ee5fSAndroid Build Coastguard Worker 
output_stacks(struct tep_handle * pevent,struct trace_hash * stack_hash)1881*58e6ee5fSAndroid Build Coastguard Worker static void output_stacks(struct tep_handle *pevent, struct trace_hash *stack_hash)
1882*58e6ee5fSAndroid Build Coastguard Worker {
1883*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
1884*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
1885*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data **stacks;
1886*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_chain *chain;
1887*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long mask = 0;
1888*58e6ee5fSAndroid Build Coastguard Worker 	int nr_chains;
1889*58e6ee5fSAndroid Build Coastguard Worker 	int longsize = tep_get_long_size(pevent);
1890*58e6ee5fSAndroid Build Coastguard Worker 	int nr_stacks;
1891*58e6ee5fSAndroid Build Coastguard Worker 	int i;
1892*58e6ee5fSAndroid Build Coastguard Worker 
1893*58e6ee5fSAndroid Build Coastguard Worker 	nr_stacks = 0;
1894*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, stack_hash) {
1895*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
1896*58e6ee5fSAndroid Build Coastguard Worker 			nr_stacks++;
1897*58e6ee5fSAndroid Build Coastguard Worker 		}
1898*58e6ee5fSAndroid Build Coastguard Worker 	}
1899*58e6ee5fSAndroid Build Coastguard Worker 
1900*58e6ee5fSAndroid Build Coastguard Worker 	stacks = malloc(sizeof(*stacks) * nr_stacks);
1901*58e6ee5fSAndroid Build Coastguard Worker 	if (!stacks) {
1902*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate stacks");
1903*58e6ee5fSAndroid Build Coastguard Worker 		return;
1904*58e6ee5fSAndroid Build Coastguard Worker 	}
1905*58e6ee5fSAndroid Build Coastguard Worker 
1906*58e6ee5fSAndroid Build Coastguard Worker 	nr_stacks = 0;
1907*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, stack_hash) {
1908*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
1909*58e6ee5fSAndroid Build Coastguard Worker 			stacks[nr_stacks++] = stack_from_item(item);
1910*58e6ee5fSAndroid Build Coastguard Worker 		}
1911*58e6ee5fSAndroid Build Coastguard Worker 	}
1912*58e6ee5fSAndroid Build Coastguard Worker 
1913*58e6ee5fSAndroid Build Coastguard Worker 	qsort(stacks, nr_stacks, sizeof(*stacks), compare_stacks);
1914*58e6ee5fSAndroid Build Coastguard Worker 
1915*58e6ee5fSAndroid Build Coastguard Worker 	chain = make_stack_chain(stacks, nr_stacks, longsize, 0, &nr_chains);
1916*58e6ee5fSAndroid Build Coastguard Worker 
1917*58e6ee5fSAndroid Build Coastguard Worker 	output_chain(pevent, chain, 0, nr_chains, &mask);
1918*58e6ee5fSAndroid Build Coastguard Worker 
1919*58e6ee5fSAndroid Build Coastguard Worker 	if (0)
1920*58e6ee5fSAndroid Build Coastguard Worker 		for (i = 0; i < nr_stacks; i++)
1921*58e6ee5fSAndroid Build Coastguard Worker 			output_event_stack(pevent, stacks[i]);
1922*58e6ee5fSAndroid Build Coastguard Worker 
1923*58e6ee5fSAndroid Build Coastguard Worker 	free(stacks);
1924*58e6ee5fSAndroid Build Coastguard Worker 	free_chain(chain, nr_chains);
1925*58e6ee5fSAndroid Build Coastguard Worker }
1926*58e6ee5fSAndroid Build Coastguard Worker 
output_event(struct event_hash * event_hash)1927*58e6ee5fSAndroid Build Coastguard Worker static void output_event(struct event_hash *event_hash)
1928*58e6ee5fSAndroid Build Coastguard Worker {
1929*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data *event_data = event_hash->event_data;
1930*58e6ee5fSAndroid Build Coastguard Worker 	struct tep_handle *pevent = event_data->event->tep;
1931*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_seq s;
1932*58e6ee5fSAndroid Build Coastguard Worker 
1933*58e6ee5fSAndroid Build Coastguard Worker 	trace_seq_init(&s);
1934*58e6ee5fSAndroid Build Coastguard Worker 
1935*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data->print_func)
1936*58e6ee5fSAndroid Build Coastguard Worker 		event_data->print_func(&s, event_hash);
1937*58e6ee5fSAndroid Build Coastguard Worker 	else if (event_data->type == EVENT_TYPE_FUNC)
1938*58e6ee5fSAndroid Build Coastguard Worker 		func_print(&s, event_hash);
1939*58e6ee5fSAndroid Build Coastguard Worker 	else
1940*58e6ee5fSAndroid Build Coastguard Worker 		trace_seq_printf(&s, "%s:0x%llx",
1941*58e6ee5fSAndroid Build Coastguard Worker 				 event_data->event->name,
1942*58e6ee5fSAndroid Build Coastguard Worker 				 event_hash->val);
1943*58e6ee5fSAndroid Build Coastguard Worker 	trace_seq_terminate(&s);
1944*58e6ee5fSAndroid Build Coastguard Worker 
1945*58e6ee5fSAndroid Build Coastguard Worker 	printf("  Event: %s (%lld)",
1946*58e6ee5fSAndroid Build Coastguard Worker 	       s.buffer, event_hash->count);
1947*58e6ee5fSAndroid Build Coastguard Worker 
1948*58e6ee5fSAndroid Build Coastguard Worker 	trace_seq_destroy(&s);
1949*58e6ee5fSAndroid Build Coastguard Worker 
1950*58e6ee5fSAndroid Build Coastguard Worker 	if (event_hash->time_total) {
1951*58e6ee5fSAndroid Build Coastguard Worker 		event_hash->time_avg = event_hash->time_total / event_hash->count;
1952*58e6ee5fSAndroid Build Coastguard Worker 		printf(" Total: %lld Avg: %lld Max: %lld(ts:%lld.%06lld) Min:%lld(ts:%lld.%06lld)",
1953*58e6ee5fSAndroid Build Coastguard Worker 		       event_hash->time_total, event_hash->time_avg,
1954*58e6ee5fSAndroid Build Coastguard Worker 		       event_hash->time_max,
1955*58e6ee5fSAndroid Build Coastguard Worker 		       nsecs_per_sec(event_hash->ts_max),
1956*58e6ee5fSAndroid Build Coastguard Worker 		       mod_to_usec(event_hash->ts_max),
1957*58e6ee5fSAndroid Build Coastguard Worker 		       event_hash->time_min,
1958*58e6ee5fSAndroid Build Coastguard Worker 		       nsecs_per_sec(event_hash->ts_min),
1959*58e6ee5fSAndroid Build Coastguard Worker 		       mod_to_usec(event_hash->ts_min));
1960*58e6ee5fSAndroid Build Coastguard Worker 	}
1961*58e6ee5fSAndroid Build Coastguard Worker 	printf("\n");
1962*58e6ee5fSAndroid Build Coastguard Worker 
1963*58e6ee5fSAndroid Build Coastguard Worker 	output_stacks(pevent, &event_hash->stacks);
1964*58e6ee5fSAndroid Build Coastguard Worker }
1965*58e6ee5fSAndroid Build Coastguard Worker 
compare_events(const void * a,const void * b)1966*58e6ee5fSAndroid Build Coastguard Worker static int compare_events(const void *a, const void *b)
1967*58e6ee5fSAndroid Build Coastguard Worker {
1968*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash * const *A = a;
1969*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash * const *B = b;
1970*58e6ee5fSAndroid Build Coastguard Worker 	const struct event_data *event_data_a = (*A)->event_data;
1971*58e6ee5fSAndroid Build Coastguard Worker 	const struct event_data *event_data_b = (*B)->event_data;
1972*58e6ee5fSAndroid Build Coastguard Worker 
1973*58e6ee5fSAndroid Build Coastguard Worker 	/* Schedule switch goes first */
1974*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data_a->type == EVENT_TYPE_SCHED_SWITCH) {
1975*58e6ee5fSAndroid Build Coastguard Worker 		if (event_data_b->type != EVENT_TYPE_SCHED_SWITCH)
1976*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1977*58e6ee5fSAndroid Build Coastguard Worker 		/* lower the state the better */
1978*58e6ee5fSAndroid Build Coastguard Worker 		if ((*A)->val > (*B)->val)
1979*58e6ee5fSAndroid Build Coastguard Worker 			return 1;
1980*58e6ee5fSAndroid Build Coastguard Worker 		if ((*A)->val < (*B)->val)
1981*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1982*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1983*58e6ee5fSAndroid Build Coastguard Worker 	} else if (event_data_b->type == EVENT_TYPE_SCHED_SWITCH)
1984*58e6ee5fSAndroid Build Coastguard Worker 			return 1;
1985*58e6ee5fSAndroid Build Coastguard Worker 
1986*58e6ee5fSAndroid Build Coastguard Worker 	/* Wakeups are next */
1987*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data_a->type == EVENT_TYPE_WAKEUP) {
1988*58e6ee5fSAndroid Build Coastguard Worker 		if (event_data_b->type != EVENT_TYPE_WAKEUP)
1989*58e6ee5fSAndroid Build Coastguard Worker 			return -1;
1990*58e6ee5fSAndroid Build Coastguard Worker 		return 0;
1991*58e6ee5fSAndroid Build Coastguard Worker 	} else if (event_data_b->type == EVENT_TYPE_WAKEUP)
1992*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
1993*58e6ee5fSAndroid Build Coastguard Worker 
1994*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data_a->id > event_data_b->id)
1995*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
1996*58e6ee5fSAndroid Build Coastguard Worker 	if (event_data_a->id < event_data_b->id)
1997*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
1998*58e6ee5fSAndroid Build Coastguard Worker 	if ((*A)->time_total > (*B)->time_total)
1999*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2000*58e6ee5fSAndroid Build Coastguard Worker 	if ((*A)->time_total < (*B)->time_total)
2001*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
2002*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2003*58e6ee5fSAndroid Build Coastguard Worker }
2004*58e6ee5fSAndroid Build Coastguard Worker 
output_task(struct handle_data * h,struct task_data * task)2005*58e6ee5fSAndroid Build Coastguard Worker static void output_task(struct handle_data *h, struct task_data *task)
2006*58e6ee5fSAndroid Build Coastguard Worker {
2007*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2008*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2009*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash **events;
2010*58e6ee5fSAndroid Build Coastguard Worker 	const char *comm;
2011*58e6ee5fSAndroid Build Coastguard Worker 	int nr_events = 0;
2012*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2013*58e6ee5fSAndroid Build Coastguard Worker 
2014*58e6ee5fSAndroid Build Coastguard Worker 	if (task->group)
2015*58e6ee5fSAndroid Build Coastguard Worker 		return;
2016*58e6ee5fSAndroid Build Coastguard Worker 
2017*58e6ee5fSAndroid Build Coastguard Worker 	if (task->comm)
2018*58e6ee5fSAndroid Build Coastguard Worker 		comm = task->comm;
2019*58e6ee5fSAndroid Build Coastguard Worker 	else
2020*58e6ee5fSAndroid Build Coastguard Worker 		comm = tep_data_comm_from_pid(h->pevent, task->pid);
2021*58e6ee5fSAndroid Build Coastguard Worker 
2022*58e6ee5fSAndroid Build Coastguard Worker 	if (task->pid < 0)
2023*58e6ee5fSAndroid Build Coastguard Worker 		printf("%s\n", task->comm);
2024*58e6ee5fSAndroid Build Coastguard Worker 	else
2025*58e6ee5fSAndroid Build Coastguard Worker 		printf("\ntask: %s-%d\n", comm, task->pid);
2026*58e6ee5fSAndroid Build Coastguard Worker 
2027*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &task->event_hash) {
2028*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
2029*58e6ee5fSAndroid Build Coastguard Worker 			nr_events++;
2030*58e6ee5fSAndroid Build Coastguard Worker 		}
2031*58e6ee5fSAndroid Build Coastguard Worker 	}
2032*58e6ee5fSAndroid Build Coastguard Worker 
2033*58e6ee5fSAndroid Build Coastguard Worker 	events = malloc(sizeof(*events) * nr_events);
2034*58e6ee5fSAndroid Build Coastguard Worker 	if (!events) {
2035*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate events");
2036*58e6ee5fSAndroid Build Coastguard Worker 		return;
2037*58e6ee5fSAndroid Build Coastguard Worker 	}
2038*58e6ee5fSAndroid Build Coastguard Worker 
2039*58e6ee5fSAndroid Build Coastguard Worker 	i = 0;
2040*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &task->event_hash) {
2041*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
2042*58e6ee5fSAndroid Build Coastguard Worker 			events[i++] = event_from_item(item);
2043*58e6ee5fSAndroid Build Coastguard Worker 		}
2044*58e6ee5fSAndroid Build Coastguard Worker 	}
2045*58e6ee5fSAndroid Build Coastguard Worker 
2046*58e6ee5fSAndroid Build Coastguard Worker 	qsort(events, nr_events, sizeof(*events), compare_events);
2047*58e6ee5fSAndroid Build Coastguard Worker 
2048*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_events; i++)
2049*58e6ee5fSAndroid Build Coastguard Worker 		output_event(events[i]);
2050*58e6ee5fSAndroid Build Coastguard Worker 
2051*58e6ee5fSAndroid Build Coastguard Worker 	free(events);
2052*58e6ee5fSAndroid Build Coastguard Worker }
2053*58e6ee5fSAndroid Build Coastguard Worker 
output_group(struct handle_data * h,struct group_data * group)2054*58e6ee5fSAndroid Build Coastguard Worker static void output_group(struct handle_data *h, struct group_data *group)
2055*58e6ee5fSAndroid Build Coastguard Worker {
2056*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2057*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2058*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash **events;
2059*58e6ee5fSAndroid Build Coastguard Worker 	int nr_events = 0;
2060*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2061*58e6ee5fSAndroid Build Coastguard Worker 
2062*58e6ee5fSAndroid Build Coastguard Worker 	printf("\ngroup: %s\n", group->comm);
2063*58e6ee5fSAndroid Build Coastguard Worker 
2064*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &group->event_hash) {
2065*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
2066*58e6ee5fSAndroid Build Coastguard Worker 			nr_events++;
2067*58e6ee5fSAndroid Build Coastguard Worker 		}
2068*58e6ee5fSAndroid Build Coastguard Worker 	}
2069*58e6ee5fSAndroid Build Coastguard Worker 
2070*58e6ee5fSAndroid Build Coastguard Worker 	events = malloc(sizeof(*events) * nr_events);
2071*58e6ee5fSAndroid Build Coastguard Worker 	if (!events) {
2072*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate events");
2073*58e6ee5fSAndroid Build Coastguard Worker 		return;
2074*58e6ee5fSAndroid Build Coastguard Worker 	}
2075*58e6ee5fSAndroid Build Coastguard Worker 
2076*58e6ee5fSAndroid Build Coastguard Worker 	i = 0;
2077*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &group->event_hash) {
2078*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
2079*58e6ee5fSAndroid Build Coastguard Worker 			events[i++] = event_from_item(item);
2080*58e6ee5fSAndroid Build Coastguard Worker 		}
2081*58e6ee5fSAndroid Build Coastguard Worker 	}
2082*58e6ee5fSAndroid Build Coastguard Worker 
2083*58e6ee5fSAndroid Build Coastguard Worker 	qsort(events, nr_events, sizeof(*events), compare_events);
2084*58e6ee5fSAndroid Build Coastguard Worker 
2085*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_events; i++)
2086*58e6ee5fSAndroid Build Coastguard Worker 		output_event(events[i]);
2087*58e6ee5fSAndroid Build Coastguard Worker 
2088*58e6ee5fSAndroid Build Coastguard Worker 	free(events);
2089*58e6ee5fSAndroid Build Coastguard Worker }
2090*58e6ee5fSAndroid Build Coastguard Worker 
compare_tasks(const void * a,const void * b)2091*58e6ee5fSAndroid Build Coastguard Worker static int compare_tasks(const void *a, const void *b)
2092*58e6ee5fSAndroid Build Coastguard Worker {
2093*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data * const *A = a;
2094*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data * const *B = b;
2095*58e6ee5fSAndroid Build Coastguard Worker 
2096*58e6ee5fSAndroid Build Coastguard Worker 	if ((*A)->pid > (*B)->pid)
2097*58e6ee5fSAndroid Build Coastguard Worker 		return 1;
2098*58e6ee5fSAndroid Build Coastguard Worker 	else if ((*A)->pid < (*B)->pid)
2099*58e6ee5fSAndroid Build Coastguard Worker 		return -1;
2100*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2101*58e6ee5fSAndroid Build Coastguard Worker }
2102*58e6ee5fSAndroid Build Coastguard Worker 
compare_groups(const void * a,const void * b)2103*58e6ee5fSAndroid Build Coastguard Worker static int compare_groups(const void *a, const void *b)
2104*58e6ee5fSAndroid Build Coastguard Worker {
2105*58e6ee5fSAndroid Build Coastguard Worker 	const char *A = a;
2106*58e6ee5fSAndroid Build Coastguard Worker 	const char *B = b;
2107*58e6ee5fSAndroid Build Coastguard Worker 
2108*58e6ee5fSAndroid Build Coastguard Worker 	return strcmp(A, B);
2109*58e6ee5fSAndroid Build Coastguard Worker }
2110*58e6ee5fSAndroid Build Coastguard Worker 
free_event_hash(struct event_hash * event_hash)2111*58e6ee5fSAndroid Build Coastguard Worker static void free_event_hash(struct event_hash *event_hash)
2112*58e6ee5fSAndroid Build Coastguard Worker {
2113*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2114*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2115*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data *stack;
2116*58e6ee5fSAndroid Build Coastguard Worker 
2117*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &event_hash->stacks) {
2118*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2119*58e6ee5fSAndroid Build Coastguard Worker 			stack = stack_from_item(item);
2120*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(&stack->hash);
2121*58e6ee5fSAndroid Build Coastguard Worker 			free(stack);
2122*58e6ee5fSAndroid Build Coastguard Worker 		}
2123*58e6ee5fSAndroid Build Coastguard Worker 	}
2124*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_free(&event_hash->stacks);
2125*58e6ee5fSAndroid Build Coastguard Worker 	free(event_hash);
2126*58e6ee5fSAndroid Build Coastguard Worker }
2127*58e6ee5fSAndroid Build Coastguard Worker 
__free_task(struct task_data * task)2128*58e6ee5fSAndroid Build Coastguard Worker static void __free_task(struct task_data *task)
2129*58e6ee5fSAndroid Build Coastguard Worker {
2130*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2131*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2132*58e6ee5fSAndroid Build Coastguard Worker 	struct start_data *start;
2133*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
2134*58e6ee5fSAndroid Build Coastguard Worker 
2135*58e6ee5fSAndroid Build Coastguard Worker 	free(task->comm);
2136*58e6ee5fSAndroid Build Coastguard Worker 
2137*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &task->start_hash) {
2138*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2139*58e6ee5fSAndroid Build Coastguard Worker 			start = start_from_item(item);
2140*58e6ee5fSAndroid Build Coastguard Worker 			if (start->stack.record)
2141*58e6ee5fSAndroid Build Coastguard Worker 				tracecmd_free_record(start->stack.record);
2142*58e6ee5fSAndroid Build Coastguard Worker 			list_del(&start->list);
2143*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(item);
2144*58e6ee5fSAndroid Build Coastguard Worker 			free(start);
2145*58e6ee5fSAndroid Build Coastguard Worker 		}
2146*58e6ee5fSAndroid Build Coastguard Worker 	}
2147*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_free(&task->start_hash);
2148*58e6ee5fSAndroid Build Coastguard Worker 
2149*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &task->event_hash) {
2150*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2151*58e6ee5fSAndroid Build Coastguard Worker 			event_hash = event_from_item(item);
2152*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(item);
2153*58e6ee5fSAndroid Build Coastguard Worker 			free_event_hash(event_hash);
2154*58e6ee5fSAndroid Build Coastguard Worker 		}
2155*58e6ee5fSAndroid Build Coastguard Worker 	}
2156*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_free(&task->event_hash);
2157*58e6ee5fSAndroid Build Coastguard Worker 
2158*58e6ee5fSAndroid Build Coastguard Worker 	if (task->last_stack)
2159*58e6ee5fSAndroid Build Coastguard Worker 		tracecmd_free_record(task->last_stack);
2160*58e6ee5fSAndroid Build Coastguard Worker }
2161*58e6ee5fSAndroid Build Coastguard Worker 
free_task(struct task_data * task)2162*58e6ee5fSAndroid Build Coastguard Worker static void free_task(struct task_data *task)
2163*58e6ee5fSAndroid Build Coastguard Worker {
2164*58e6ee5fSAndroid Build Coastguard Worker 	__free_task(task);
2165*58e6ee5fSAndroid Build Coastguard Worker 	free(task);
2166*58e6ee5fSAndroid Build Coastguard Worker }
2167*58e6ee5fSAndroid Build Coastguard Worker 
free_group(struct group_data * group)2168*58e6ee5fSAndroid Build Coastguard Worker static void free_group(struct group_data *group)
2169*58e6ee5fSAndroid Build Coastguard Worker {
2170*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2171*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2172*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *event_hash;
2173*58e6ee5fSAndroid Build Coastguard Worker 
2174*58e6ee5fSAndroid Build Coastguard Worker 	free(group->comm);
2175*58e6ee5fSAndroid Build Coastguard Worker 
2176*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &group->event_hash) {
2177*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2178*58e6ee5fSAndroid Build Coastguard Worker 			event_hash = event_from_item(item);
2179*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(item);
2180*58e6ee5fSAndroid Build Coastguard Worker 			free_event_hash(event_hash);
2181*58e6ee5fSAndroid Build Coastguard Worker 		}
2182*58e6ee5fSAndroid Build Coastguard Worker 	}
2183*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_free(&group->event_hash);
2184*58e6ee5fSAndroid Build Coastguard Worker 	free(group);
2185*58e6ee5fSAndroid Build Coastguard Worker }
2186*58e6ee5fSAndroid Build Coastguard Worker 
show_global_task(struct handle_data * h,struct task_data * task)2187*58e6ee5fSAndroid Build Coastguard Worker static void show_global_task(struct handle_data *h,
2188*58e6ee5fSAndroid Build Coastguard Worker 			     struct task_data *task)
2189*58e6ee5fSAndroid Build Coastguard Worker {
2190*58e6ee5fSAndroid Build Coastguard Worker 	if (trace_hash_empty(&task->event_hash))
2191*58e6ee5fSAndroid Build Coastguard Worker 		return;
2192*58e6ee5fSAndroid Build Coastguard Worker 
2193*58e6ee5fSAndroid Build Coastguard Worker 	output_task(h, task);
2194*58e6ee5fSAndroid Build Coastguard Worker }
2195*58e6ee5fSAndroid Build Coastguard Worker 
output_tasks(struct handle_data * h)2196*58e6ee5fSAndroid Build Coastguard Worker static void output_tasks(struct handle_data *h)
2197*58e6ee5fSAndroid Build Coastguard Worker {
2198*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2199*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2200*58e6ee5fSAndroid Build Coastguard Worker 	struct task_data **tasks;
2201*58e6ee5fSAndroid Build Coastguard Worker 	int nr_tasks = 0;
2202*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2203*58e6ee5fSAndroid Build Coastguard Worker 
2204*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &h->task_hash) {
2205*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
2206*58e6ee5fSAndroid Build Coastguard Worker 			nr_tasks++;
2207*58e6ee5fSAndroid Build Coastguard Worker 		}
2208*58e6ee5fSAndroid Build Coastguard Worker 	}
2209*58e6ee5fSAndroid Build Coastguard Worker 
2210*58e6ee5fSAndroid Build Coastguard Worker 	tasks = malloc(sizeof(*tasks) * nr_tasks);
2211*58e6ee5fSAndroid Build Coastguard Worker 	if (!tasks) {
2212*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate tasks");
2213*58e6ee5fSAndroid Build Coastguard Worker 		return;
2214*58e6ee5fSAndroid Build Coastguard Worker 	}
2215*58e6ee5fSAndroid Build Coastguard Worker 
2216*58e6ee5fSAndroid Build Coastguard Worker 	nr_tasks = 0;
2217*58e6ee5fSAndroid Build Coastguard Worker 
2218*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &h->task_hash) {
2219*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2220*58e6ee5fSAndroid Build Coastguard Worker 			tasks[nr_tasks++] = task_from_item(item);
2221*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(item);
2222*58e6ee5fSAndroid Build Coastguard Worker 		}
2223*58e6ee5fSAndroid Build Coastguard Worker 	}
2224*58e6ee5fSAndroid Build Coastguard Worker 
2225*58e6ee5fSAndroid Build Coastguard Worker 	qsort(tasks, nr_tasks, sizeof(*tasks), compare_tasks);
2226*58e6ee5fSAndroid Build Coastguard Worker 
2227*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_tasks; i++) {
2228*58e6ee5fSAndroid Build Coastguard Worker 		output_task(h, tasks[i]);
2229*58e6ee5fSAndroid Build Coastguard Worker 		free_task(tasks[i]);
2230*58e6ee5fSAndroid Build Coastguard Worker 	}
2231*58e6ee5fSAndroid Build Coastguard Worker 
2232*58e6ee5fSAndroid Build Coastguard Worker 	free(tasks);
2233*58e6ee5fSAndroid Build Coastguard Worker }
2234*58e6ee5fSAndroid Build Coastguard Worker 
output_groups(struct handle_data * h)2235*58e6ee5fSAndroid Build Coastguard Worker static void output_groups(struct handle_data *h)
2236*58e6ee5fSAndroid Build Coastguard Worker {
2237*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2238*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2239*58e6ee5fSAndroid Build Coastguard Worker 	struct group_data **groups;
2240*58e6ee5fSAndroid Build Coastguard Worker 	int nr_groups = 0;
2241*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2242*58e6ee5fSAndroid Build Coastguard Worker 
2243*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &h->group_hash) {
2244*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket) {
2245*58e6ee5fSAndroid Build Coastguard Worker 			nr_groups++;
2246*58e6ee5fSAndroid Build Coastguard Worker 		}
2247*58e6ee5fSAndroid Build Coastguard Worker 	}
2248*58e6ee5fSAndroid Build Coastguard Worker 
2249*58e6ee5fSAndroid Build Coastguard Worker 	if (nr_groups == 0)
2250*58e6ee5fSAndroid Build Coastguard Worker 		return;
2251*58e6ee5fSAndroid Build Coastguard Worker 
2252*58e6ee5fSAndroid Build Coastguard Worker 	groups = malloc(sizeof(*groups) * nr_groups);
2253*58e6ee5fSAndroid Build Coastguard Worker 	if (!groups) {
2254*58e6ee5fSAndroid Build Coastguard Worker 		warning("Could not allocate groups");
2255*58e6ee5fSAndroid Build Coastguard Worker 		return;
2256*58e6ee5fSAndroid Build Coastguard Worker 	}
2257*58e6ee5fSAndroid Build Coastguard Worker 
2258*58e6ee5fSAndroid Build Coastguard Worker 	nr_groups = 0;
2259*58e6ee5fSAndroid Build Coastguard Worker 
2260*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &h->group_hash) {
2261*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2262*58e6ee5fSAndroid Build Coastguard Worker 			groups[nr_groups++] = group_from_item(item);
2263*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(item);
2264*58e6ee5fSAndroid Build Coastguard Worker 		}
2265*58e6ee5fSAndroid Build Coastguard Worker 	}
2266*58e6ee5fSAndroid Build Coastguard Worker 
2267*58e6ee5fSAndroid Build Coastguard Worker 	qsort(groups, nr_groups, sizeof(*groups), compare_groups);
2268*58e6ee5fSAndroid Build Coastguard Worker 
2269*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < nr_groups; i++) {
2270*58e6ee5fSAndroid Build Coastguard Worker 		output_group(h, groups[i]);
2271*58e6ee5fSAndroid Build Coastguard Worker 		free_group(groups[i]);
2272*58e6ee5fSAndroid Build Coastguard Worker 	}
2273*58e6ee5fSAndroid Build Coastguard Worker 
2274*58e6ee5fSAndroid Build Coastguard Worker 	free(groups);
2275*58e6ee5fSAndroid Build Coastguard Worker }
2276*58e6ee5fSAndroid Build Coastguard Worker 
output_handle(struct handle_data * h)2277*58e6ee5fSAndroid Build Coastguard Worker static void output_handle(struct handle_data *h)
2278*58e6ee5fSAndroid Build Coastguard Worker {
2279*58e6ee5fSAndroid Build Coastguard Worker 	int i;
2280*58e6ee5fSAndroid Build Coastguard Worker 
2281*58e6ee5fSAndroid Build Coastguard Worker 	show_global_task(h, h->global_task);
2282*58e6ee5fSAndroid Build Coastguard Worker 	for (i = 0; i < h->cpus; i++)
2283*58e6ee5fSAndroid Build Coastguard Worker 		show_global_task(h, &h->global_percpu_tasks[i]);
2284*58e6ee5fSAndroid Build Coastguard Worker 
2285*58e6ee5fSAndroid Build Coastguard Worker 	output_groups(h);
2286*58e6ee5fSAndroid Build Coastguard Worker 	output_tasks(h);
2287*58e6ee5fSAndroid Build Coastguard Worker }
2288*58e6ee5fSAndroid Build Coastguard Worker 
merge_event_stack(struct event_hash * event,struct stack_data * stack)2289*58e6ee5fSAndroid Build Coastguard Worker static void merge_event_stack(struct event_hash *event,
2290*58e6ee5fSAndroid Build Coastguard Worker 			      struct stack_data *stack)
2291*58e6ee5fSAndroid Build Coastguard Worker {
2292*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data *exist;
2293*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2294*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_match match;
2295*58e6ee5fSAndroid Build Coastguard Worker 
2296*58e6ee5fSAndroid Build Coastguard Worker 	match.caller = stack->caller;
2297*58e6ee5fSAndroid Build Coastguard Worker 	match.size = stack->size;
2298*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&event->stacks, stack->hash.key, match_stack,
2299*58e6ee5fSAndroid Build Coastguard Worker 			       &match);
2300*58e6ee5fSAndroid Build Coastguard Worker 	if (!item) {
2301*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_add(&event->stacks, &stack->hash);
2302*58e6ee5fSAndroid Build Coastguard Worker 		return;
2303*58e6ee5fSAndroid Build Coastguard Worker 	}
2304*58e6ee5fSAndroid Build Coastguard Worker 	exist = stack_from_item(item);
2305*58e6ee5fSAndroid Build Coastguard Worker 	exist->count += stack->count;
2306*58e6ee5fSAndroid Build Coastguard Worker 	exist->time += stack->time;
2307*58e6ee5fSAndroid Build Coastguard Worker 
2308*58e6ee5fSAndroid Build Coastguard Worker 	if (exist->time_max < stack->time_max) {
2309*58e6ee5fSAndroid Build Coastguard Worker 		exist->time_max = stack->time_max;
2310*58e6ee5fSAndroid Build Coastguard Worker 		exist->ts_max = stack->ts_max;
2311*58e6ee5fSAndroid Build Coastguard Worker 	}
2312*58e6ee5fSAndroid Build Coastguard Worker 	if (exist->time_min > stack->time_min) {
2313*58e6ee5fSAndroid Build Coastguard Worker 		exist->time_min = stack->time_min;
2314*58e6ee5fSAndroid Build Coastguard Worker 		exist->ts_min = stack->ts_min;
2315*58e6ee5fSAndroid Build Coastguard Worker 	}
2316*58e6ee5fSAndroid Build Coastguard Worker 	free(stack);
2317*58e6ee5fSAndroid Build Coastguard Worker }
2318*58e6ee5fSAndroid Build Coastguard Worker 
merge_stacks(struct event_hash * exist,struct event_hash * event)2319*58e6ee5fSAndroid Build Coastguard Worker static void merge_stacks(struct event_hash *exist, struct event_hash *event)
2320*58e6ee5fSAndroid Build Coastguard Worker {
2321*58e6ee5fSAndroid Build Coastguard Worker 	struct stack_data *stack;
2322*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2323*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2324*58e6ee5fSAndroid Build Coastguard Worker 
2325*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &event->stacks) {
2326*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2327*58e6ee5fSAndroid Build Coastguard Worker 			stack = stack_from_item(item);
2328*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(&stack->hash);
2329*58e6ee5fSAndroid Build Coastguard Worker 			merge_event_stack(exist, stack);
2330*58e6ee5fSAndroid Build Coastguard Worker 		}
2331*58e6ee5fSAndroid Build Coastguard Worker 	}
2332*58e6ee5fSAndroid Build Coastguard Worker }
2333*58e6ee5fSAndroid Build Coastguard Worker 
merge_event_into_group(struct group_data * group,struct event_hash * event)2334*58e6ee5fSAndroid Build Coastguard Worker static void merge_event_into_group(struct group_data *group,
2335*58e6ee5fSAndroid Build Coastguard Worker 				   struct event_hash *event)
2336*58e6ee5fSAndroid Build Coastguard Worker {
2337*58e6ee5fSAndroid Build Coastguard Worker 	struct event_hash *exist;
2338*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2339*58e6ee5fSAndroid Build Coastguard Worker 	struct event_data_match edata;
2340*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key;
2341*58e6ee5fSAndroid Build Coastguard Worker 
2342*58e6ee5fSAndroid Build Coastguard Worker 	if (event->event_data->type == EVENT_TYPE_WAKEUP) {
2343*58e6ee5fSAndroid Build Coastguard Worker 		edata.event_data = event->event_data;
2344*58e6ee5fSAndroid Build Coastguard Worker 		event->search_val = 0;
2345*58e6ee5fSAndroid Build Coastguard Worker 		event->val = 0;
2346*58e6ee5fSAndroid Build Coastguard Worker 		key = trace_hash((unsigned long)event->event_data);
2347*58e6ee5fSAndroid Build Coastguard Worker 	} else if (event->event_data->type == EVENT_TYPE_SCHED_SWITCH) {
2348*58e6ee5fSAndroid Build Coastguard Worker 		edata.event_data = event->event_data;
2349*58e6ee5fSAndroid Build Coastguard Worker 		event->search_val = event->val;
2350*58e6ee5fSAndroid Build Coastguard Worker 		key = (unsigned long)event->event_data +
2351*58e6ee5fSAndroid Build Coastguard Worker 			((unsigned long)event->val * 2);
2352*58e6ee5fSAndroid Build Coastguard Worker 		key = trace_hash(key);
2353*58e6ee5fSAndroid Build Coastguard Worker 	} else {
2354*58e6ee5fSAndroid Build Coastguard Worker 		key = event->hash.key;
2355*58e6ee5fSAndroid Build Coastguard Worker 	}
2356*58e6ee5fSAndroid Build Coastguard Worker 
2357*58e6ee5fSAndroid Build Coastguard Worker 	edata.event_data = event->event_data;
2358*58e6ee5fSAndroid Build Coastguard Worker 	edata.search_val = event->search_val;
2359*58e6ee5fSAndroid Build Coastguard Worker 	edata.val = event->val;
2360*58e6ee5fSAndroid Build Coastguard Worker 
2361*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&group->event_hash, key, match_event, &edata);
2362*58e6ee5fSAndroid Build Coastguard Worker 	if (!item) {
2363*58e6ee5fSAndroid Build Coastguard Worker 		event->hash.key = key;
2364*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_add(&group->event_hash, &event->hash);
2365*58e6ee5fSAndroid Build Coastguard Worker 		return;
2366*58e6ee5fSAndroid Build Coastguard Worker 	}
2367*58e6ee5fSAndroid Build Coastguard Worker 
2368*58e6ee5fSAndroid Build Coastguard Worker 	exist = event_from_item(item);
2369*58e6ee5fSAndroid Build Coastguard Worker 	exist->count += event->count;
2370*58e6ee5fSAndroid Build Coastguard Worker 	exist->time_total += event->time_total;
2371*58e6ee5fSAndroid Build Coastguard Worker 
2372*58e6ee5fSAndroid Build Coastguard Worker 	if (exist->time_max < event->time_max) {
2373*58e6ee5fSAndroid Build Coastguard Worker 		exist->time_max = event->time_max;
2374*58e6ee5fSAndroid Build Coastguard Worker 		exist->ts_max = event->ts_max;
2375*58e6ee5fSAndroid Build Coastguard Worker 	}
2376*58e6ee5fSAndroid Build Coastguard Worker 	if (exist->time_min > event->time_min) {
2377*58e6ee5fSAndroid Build Coastguard Worker 		exist->time_min = event->time_min;
2378*58e6ee5fSAndroid Build Coastguard Worker 		exist->ts_min = event->ts_min;
2379*58e6ee5fSAndroid Build Coastguard Worker 	}
2380*58e6ee5fSAndroid Build Coastguard Worker 
2381*58e6ee5fSAndroid Build Coastguard Worker 	merge_stacks(exist, event);
2382*58e6ee5fSAndroid Build Coastguard Worker 	free_event_hash(event);
2383*58e6ee5fSAndroid Build Coastguard Worker }
2384*58e6ee5fSAndroid Build Coastguard Worker 
add_group(struct handle_data * h,struct task_data * task)2385*58e6ee5fSAndroid Build Coastguard Worker static void add_group(struct handle_data *h, struct task_data *task)
2386*58e6ee5fSAndroid Build Coastguard Worker {
2387*58e6ee5fSAndroid Build Coastguard Worker 	unsigned long long key;
2388*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2389*58e6ee5fSAndroid Build Coastguard Worker 	struct group_data *grp;
2390*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2391*58e6ee5fSAndroid Build Coastguard Worker 	void *data = task->comm;
2392*58e6ee5fSAndroid Build Coastguard Worker 
2393*58e6ee5fSAndroid Build Coastguard Worker 	if (!task->comm)
2394*58e6ee5fSAndroid Build Coastguard Worker 		return;
2395*58e6ee5fSAndroid Build Coastguard Worker 
2396*58e6ee5fSAndroid Build Coastguard Worker 	key = trace_hash_str(task->comm);
2397*58e6ee5fSAndroid Build Coastguard Worker 
2398*58e6ee5fSAndroid Build Coastguard Worker 	item = trace_hash_find(&h->group_hash, key, match_group, data);
2399*58e6ee5fSAndroid Build Coastguard Worker 	if (item) {
2400*58e6ee5fSAndroid Build Coastguard Worker 		grp = group_from_item(item);
2401*58e6ee5fSAndroid Build Coastguard Worker 	} else {
2402*58e6ee5fSAndroid Build Coastguard Worker 		grp = malloc(sizeof(*grp));
2403*58e6ee5fSAndroid Build Coastguard Worker 		if (!grp) {
2404*58e6ee5fSAndroid Build Coastguard Worker 			warning("Could not allocate group");
2405*58e6ee5fSAndroid Build Coastguard Worker 			return;
2406*58e6ee5fSAndroid Build Coastguard Worker 		}
2407*58e6ee5fSAndroid Build Coastguard Worker 		memset(grp, 0, sizeof(*grp));
2408*58e6ee5fSAndroid Build Coastguard Worker 
2409*58e6ee5fSAndroid Build Coastguard Worker 		grp->comm = strdup(task->comm);
2410*58e6ee5fSAndroid Build Coastguard Worker 		if (!grp->comm)
2411*58e6ee5fSAndroid Build Coastguard Worker 			die("strdup");
2412*58e6ee5fSAndroid Build Coastguard Worker 		grp->hash.key = key;
2413*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_add(&h->group_hash, &grp->hash);
2414*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_init(&grp->event_hash, 32);
2415*58e6ee5fSAndroid Build Coastguard Worker 	}
2416*58e6ee5fSAndroid Build Coastguard Worker 	task->group = grp;
2417*58e6ee5fSAndroid Build Coastguard Worker 
2418*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &task->event_hash) {
2419*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_while_item(item, bucket) {
2420*58e6ee5fSAndroid Build Coastguard Worker 			struct event_hash *event_hash;
2421*58e6ee5fSAndroid Build Coastguard Worker 
2422*58e6ee5fSAndroid Build Coastguard Worker 			event_hash = event_from_item(item);
2423*58e6ee5fSAndroid Build Coastguard Worker 			trace_hash_del(&event_hash->hash);
2424*58e6ee5fSAndroid Build Coastguard Worker 			merge_event_into_group(grp, event_hash);
2425*58e6ee5fSAndroid Build Coastguard Worker 		}
2426*58e6ee5fSAndroid Build Coastguard Worker 	}
2427*58e6ee5fSAndroid Build Coastguard Worker }
2428*58e6ee5fSAndroid Build Coastguard Worker 
merge_tasks(struct handle_data * h)2429*58e6ee5fSAndroid Build Coastguard Worker static void merge_tasks(struct handle_data *h)
2430*58e6ee5fSAndroid Build Coastguard Worker {
2431*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item **bucket;
2432*58e6ee5fSAndroid Build Coastguard Worker 	struct trace_hash_item *item;
2433*58e6ee5fSAndroid Build Coastguard Worker 
2434*58e6ee5fSAndroid Build Coastguard Worker 	if (!merge_like_comms)
2435*58e6ee5fSAndroid Build Coastguard Worker 		return;
2436*58e6ee5fSAndroid Build Coastguard Worker 
2437*58e6ee5fSAndroid Build Coastguard Worker 	trace_hash_for_each_bucket(bucket, &h->task_hash) {
2438*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_for_each_item(item, bucket)
2439*58e6ee5fSAndroid Build Coastguard Worker 			add_group(h, task_from_item(item));
2440*58e6ee5fSAndroid Build Coastguard Worker 	}
2441*58e6ee5fSAndroid Build Coastguard Worker }
2442*58e6ee5fSAndroid Build Coastguard Worker 
do_trace_profile(void)2443*58e6ee5fSAndroid Build Coastguard Worker int do_trace_profile(void)
2444*58e6ee5fSAndroid Build Coastguard Worker {
2445*58e6ee5fSAndroid Build Coastguard Worker 	struct handle_data *h;
2446*58e6ee5fSAndroid Build Coastguard Worker 
2447*58e6ee5fSAndroid Build Coastguard Worker 	for (h = handles; h; h = h->next) {
2448*58e6ee5fSAndroid Build Coastguard Worker 		if (merge_like_comms)
2449*58e6ee5fSAndroid Build Coastguard Worker 			merge_tasks(h);
2450*58e6ee5fSAndroid Build Coastguard Worker 		output_handle(h);
2451*58e6ee5fSAndroid Build Coastguard Worker 		trace_hash_free(&h->task_hash);
2452*58e6ee5fSAndroid Build Coastguard Worker 	}
2453*58e6ee5fSAndroid Build Coastguard Worker 
2454*58e6ee5fSAndroid Build Coastguard Worker 	return 0;
2455*58e6ee5fSAndroid Build Coastguard Worker }
2456