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