perf timechart: Add backtrace support
[firefly-linux-kernel-4.4.55.git] / tools / perf / builtin-timechart.c
1 /*
2  * builtin-timechart.c - make an svg timechart of system activity
3  *
4  * (C) Copyright 2009 Intel Corporation
5  *
6  * Authors:
7  *     Arjan van de Ven <arjan@linux.intel.com>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; version 2
12  * of the License.
13  */
14
15 #include <traceevent/event-parse.h>
16
17 #include "builtin.h"
18
19 #include "util/util.h"
20
21 #include "util/color.h"
22 #include <linux/list.h>
23 #include "util/cache.h"
24 #include "util/evlist.h"
25 #include "util/evsel.h"
26 #include <linux/rbtree.h>
27 #include "util/symbol.h"
28 #include "util/callchain.h"
29 #include "util/strlist.h"
30
31 #include "perf.h"
32 #include "util/header.h"
33 #include "util/parse-options.h"
34 #include "util/parse-events.h"
35 #include "util/event.h"
36 #include "util/session.h"
37 #include "util/svghelper.h"
38 #include "util/tool.h"
39 #include "util/data.h"
40
41 #define SUPPORT_OLD_POWER_EVENTS 1
42 #define PWR_EVENT_EXIT -1
43
44 static int proc_num = 15;
45
46 static unsigned int     numcpus;
47 static u64              min_freq;       /* Lowest CPU frequency seen */
48 static u64              max_freq;       /* Highest CPU frequency seen */
49 static u64              turbo_frequency;
50
51 static u64              first_time, last_time;
52
53 static bool             power_only;
54 static bool             tasks_only;
55 static bool             with_backtrace;
56
57
58 struct per_pid;
59 struct per_pidcomm;
60
61 struct cpu_sample;
62 struct power_event;
63 struct wake_event;
64
65 struct sample_wrapper;
66
67 /*
68  * Datastructure layout:
69  * We keep an list of "pid"s, matching the kernels notion of a task struct.
70  * Each "pid" entry, has a list of "comm"s.
71  *      this is because we want to track different programs different, while
72  *      exec will reuse the original pid (by design).
73  * Each comm has a list of samples that will be used to draw
74  * final graph.
75  */
76
77 struct per_pid {
78         struct per_pid *next;
79
80         int             pid;
81         int             ppid;
82
83         u64             start_time;
84         u64             end_time;
85         u64             total_time;
86         int             display;
87
88         struct per_pidcomm *all;
89         struct per_pidcomm *current;
90 };
91
92
93 struct per_pidcomm {
94         struct per_pidcomm *next;
95
96         u64             start_time;
97         u64             end_time;
98         u64             total_time;
99
100         int             Y;
101         int             display;
102
103         long            state;
104         u64             state_since;
105
106         char            *comm;
107
108         struct cpu_sample *samples;
109 };
110
111 struct sample_wrapper {
112         struct sample_wrapper *next;
113
114         u64             timestamp;
115         unsigned char   data[0];
116 };
117
118 #define TYPE_NONE       0
119 #define TYPE_RUNNING    1
120 #define TYPE_WAITING    2
121 #define TYPE_BLOCKED    3
122
123 struct cpu_sample {
124         struct cpu_sample *next;
125
126         u64 start_time;
127         u64 end_time;
128         int type;
129         int cpu;
130         const char *backtrace;
131 };
132
133 static struct per_pid *all_data;
134
135 #define CSTATE 1
136 #define PSTATE 2
137
138 struct power_event {
139         struct power_event *next;
140         int type;
141         int state;
142         u64 start_time;
143         u64 end_time;
144         int cpu;
145 };
146
147 struct wake_event {
148         struct wake_event *next;
149         int waker;
150         int wakee;
151         u64 time;
152         const char *backtrace;
153 };
154
155 static struct power_event    *power_events;
156 static struct wake_event     *wake_events;
157
158 struct process_filter;
159 struct process_filter {
160         char                    *name;
161         int                     pid;
162         struct process_filter   *next;
163 };
164
165 static struct process_filter *process_filter;
166
167
168 static struct per_pid *find_create_pid(int pid)
169 {
170         struct per_pid *cursor = all_data;
171
172         while (cursor) {
173                 if (cursor->pid == pid)
174                         return cursor;
175                 cursor = cursor->next;
176         }
177         cursor = zalloc(sizeof(*cursor));
178         assert(cursor != NULL);
179         cursor->pid = pid;
180         cursor->next = all_data;
181         all_data = cursor;
182         return cursor;
183 }
184
185 static void pid_set_comm(int pid, char *comm)
186 {
187         struct per_pid *p;
188         struct per_pidcomm *c;
189         p = find_create_pid(pid);
190         c = p->all;
191         while (c) {
192                 if (c->comm && strcmp(c->comm, comm) == 0) {
193                         p->current = c;
194                         return;
195                 }
196                 if (!c->comm) {
197                         c->comm = strdup(comm);
198                         p->current = c;
199                         return;
200                 }
201                 c = c->next;
202         }
203         c = zalloc(sizeof(*c));
204         assert(c != NULL);
205         c->comm = strdup(comm);
206         p->current = c;
207         c->next = p->all;
208         p->all = c;
209 }
210
211 static void pid_fork(int pid, int ppid, u64 timestamp)
212 {
213         struct per_pid *p, *pp;
214         p = find_create_pid(pid);
215         pp = find_create_pid(ppid);
216         p->ppid = ppid;
217         if (pp->current && pp->current->comm && !p->current)
218                 pid_set_comm(pid, pp->current->comm);
219
220         p->start_time = timestamp;
221         if (p->current) {
222                 p->current->start_time = timestamp;
223                 p->current->state_since = timestamp;
224         }
225 }
226
227 static void pid_exit(int pid, u64 timestamp)
228 {
229         struct per_pid *p;
230         p = find_create_pid(pid);
231         p->end_time = timestamp;
232         if (p->current)
233                 p->current->end_time = timestamp;
234 }
235
236 static void
237 pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end,
238                const char *backtrace)
239 {
240         struct per_pid *p;
241         struct per_pidcomm *c;
242         struct cpu_sample *sample;
243
244         p = find_create_pid(pid);
245         c = p->current;
246         if (!c) {
247                 c = zalloc(sizeof(*c));
248                 assert(c != NULL);
249                 p->current = c;
250                 c->next = p->all;
251                 p->all = c;
252         }
253
254         sample = zalloc(sizeof(*sample));
255         assert(sample != NULL);
256         sample->start_time = start;
257         sample->end_time = end;
258         sample->type = type;
259         sample->next = c->samples;
260         sample->cpu = cpu;
261         sample->backtrace = backtrace;
262         c->samples = sample;
263
264         if (sample->type == TYPE_RUNNING && end > start && start > 0) {
265                 c->total_time += (end-start);
266                 p->total_time += (end-start);
267         }
268
269         if (c->start_time == 0 || c->start_time > start)
270                 c->start_time = start;
271         if (p->start_time == 0 || p->start_time > start)
272                 p->start_time = start;
273 }
274
275 #define MAX_CPUS 4096
276
277 static u64 cpus_cstate_start_times[MAX_CPUS];
278 static int cpus_cstate_state[MAX_CPUS];
279 static u64 cpus_pstate_start_times[MAX_CPUS];
280 static u64 cpus_pstate_state[MAX_CPUS];
281
282 static int process_comm_event(struct perf_tool *tool __maybe_unused,
283                               union perf_event *event,
284                               struct perf_sample *sample __maybe_unused,
285                               struct machine *machine __maybe_unused)
286 {
287         pid_set_comm(event->comm.tid, event->comm.comm);
288         return 0;
289 }
290
291 static int process_fork_event(struct perf_tool *tool __maybe_unused,
292                               union perf_event *event,
293                               struct perf_sample *sample __maybe_unused,
294                               struct machine *machine __maybe_unused)
295 {
296         pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
297         return 0;
298 }
299
300 static int process_exit_event(struct perf_tool *tool __maybe_unused,
301                               union perf_event *event,
302                               struct perf_sample *sample __maybe_unused,
303                               struct machine *machine __maybe_unused)
304 {
305         pid_exit(event->fork.pid, event->fork.time);
306         return 0;
307 }
308
309 struct trace_entry {
310         unsigned short          type;
311         unsigned char           flags;
312         unsigned char           preempt_count;
313         int                     pid;
314         int                     lock_depth;
315 };
316
317 #ifdef SUPPORT_OLD_POWER_EVENTS
318 static int use_old_power_events;
319 struct power_entry_old {
320         struct trace_entry te;
321         u64     type;
322         u64     value;
323         u64     cpu_id;
324 };
325 #endif
326
327 struct power_processor_entry {
328         struct trace_entry te;
329         u32     state;
330         u32     cpu_id;
331 };
332
333 #define TASK_COMM_LEN 16
334 struct wakeup_entry {
335         struct trace_entry te;
336         char comm[TASK_COMM_LEN];
337         int   pid;
338         int   prio;
339         int   success;
340 };
341
342 struct sched_switch {
343         struct trace_entry te;
344         char prev_comm[TASK_COMM_LEN];
345         int  prev_pid;
346         int  prev_prio;
347         long prev_state; /* Arjan weeps. */
348         char next_comm[TASK_COMM_LEN];
349         int  next_pid;
350         int  next_prio;
351 };
352
353 static void c_state_start(int cpu, u64 timestamp, int state)
354 {
355         cpus_cstate_start_times[cpu] = timestamp;
356         cpus_cstate_state[cpu] = state;
357 }
358
359 static void c_state_end(int cpu, u64 timestamp)
360 {
361         struct power_event *pwr = zalloc(sizeof(*pwr));
362
363         if (!pwr)
364                 return;
365
366         pwr->state = cpus_cstate_state[cpu];
367         pwr->start_time = cpus_cstate_start_times[cpu];
368         pwr->end_time = timestamp;
369         pwr->cpu = cpu;
370         pwr->type = CSTATE;
371         pwr->next = power_events;
372
373         power_events = pwr;
374 }
375
376 static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
377 {
378         struct power_event *pwr;
379
380         if (new_freq > 8000000) /* detect invalid data */
381                 return;
382
383         pwr = zalloc(sizeof(*pwr));
384         if (!pwr)
385                 return;
386
387         pwr->state = cpus_pstate_state[cpu];
388         pwr->start_time = cpus_pstate_start_times[cpu];
389         pwr->end_time = timestamp;
390         pwr->cpu = cpu;
391         pwr->type = PSTATE;
392         pwr->next = power_events;
393
394         if (!pwr->start_time)
395                 pwr->start_time = first_time;
396
397         power_events = pwr;
398
399         cpus_pstate_state[cpu] = new_freq;
400         cpus_pstate_start_times[cpu] = timestamp;
401
402         if ((u64)new_freq > max_freq)
403                 max_freq = new_freq;
404
405         if (new_freq < min_freq || min_freq == 0)
406                 min_freq = new_freq;
407
408         if (new_freq == max_freq - 1000)
409                         turbo_frequency = max_freq;
410 }
411
412 static void
413 sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te,
414              const char *backtrace)
415 {
416         struct per_pid *p;
417         struct wakeup_entry *wake = (void *)te;
418         struct wake_event *we = zalloc(sizeof(*we));
419
420         if (!we)
421                 return;
422
423         we->time = timestamp;
424         we->waker = pid;
425         we->backtrace = backtrace;
426
427         if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ))
428                 we->waker = -1;
429
430         we->wakee = wake->pid;
431         we->next = wake_events;
432         wake_events = we;
433         p = find_create_pid(we->wakee);
434
435         if (p && p->current && p->current->state == TYPE_NONE) {
436                 p->current->state_since = timestamp;
437                 p->current->state = TYPE_WAITING;
438         }
439         if (p && p->current && p->current->state == TYPE_BLOCKED) {
440                 pid_put_sample(p->pid, p->current->state, cpu,
441                                p->current->state_since, timestamp, NULL);
442                 p->current->state_since = timestamp;
443                 p->current->state = TYPE_WAITING;
444         }
445 }
446
447 static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te,
448                          const char *backtrace)
449 {
450         struct per_pid *p = NULL, *prev_p;
451         struct sched_switch *sw = (void *)te;
452
453
454         prev_p = find_create_pid(sw->prev_pid);
455
456         p = find_create_pid(sw->next_pid);
457
458         if (prev_p->current && prev_p->current->state != TYPE_NONE)
459                 pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu,
460                                prev_p->current->state_since, timestamp,
461                                backtrace);
462         if (p && p->current) {
463                 if (p->current->state != TYPE_NONE)
464                         pid_put_sample(sw->next_pid, p->current->state, cpu,
465                                        p->current->state_since, timestamp,
466                                        backtrace);
467
468                 p->current->state_since = timestamp;
469                 p->current->state = TYPE_RUNNING;
470         }
471
472         if (prev_p->current) {
473                 prev_p->current->state = TYPE_NONE;
474                 prev_p->current->state_since = timestamp;
475                 if (sw->prev_state & 2)
476                         prev_p->current->state = TYPE_BLOCKED;
477                 if (sw->prev_state == 0)
478                         prev_p->current->state = TYPE_WAITING;
479         }
480 }
481
482 static const char *cat_backtrace(union perf_event *event,
483                                  struct perf_sample *sample,
484                                  struct machine *machine)
485 {
486         struct addr_location al;
487         unsigned int i;
488         char *p = NULL;
489         size_t p_len;
490         u8 cpumode = PERF_RECORD_MISC_USER;
491         struct addr_location tal;
492         struct ip_callchain *chain = sample->callchain;
493         FILE *f = open_memstream(&p, &p_len);
494
495         if (!f) {
496                 perror("open_memstream error");
497                 return NULL;
498         }
499
500         if (!chain)
501                 goto exit;
502
503         if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
504                 fprintf(stderr, "problem processing %d event, skipping it.\n",
505                         event->header.type);
506                 goto exit;
507         }
508
509         for (i = 0; i < chain->nr; i++) {
510                 u64 ip;
511
512                 if (callchain_param.order == ORDER_CALLEE)
513                         ip = chain->ips[i];
514                 else
515                         ip = chain->ips[chain->nr - i - 1];
516
517                 if (ip >= PERF_CONTEXT_MAX) {
518                         switch (ip) {
519                         case PERF_CONTEXT_HV:
520                                 cpumode = PERF_RECORD_MISC_HYPERVISOR;
521                                 break;
522                         case PERF_CONTEXT_KERNEL:
523                                 cpumode = PERF_RECORD_MISC_KERNEL;
524                                 break;
525                         case PERF_CONTEXT_USER:
526                                 cpumode = PERF_RECORD_MISC_USER;
527                                 break;
528                         default:
529                                 pr_debug("invalid callchain context: "
530                                          "%"PRId64"\n", (s64) ip);
531
532                                 /*
533                                  * It seems the callchain is corrupted.
534                                  * Discard all.
535                                  */
536                                 free(p);
537                                 p = NULL;
538                                 goto exit;
539                         }
540                         continue;
541                 }
542
543                 tal.filtered = false;
544                 thread__find_addr_location(al.thread, machine, cpumode,
545                                            MAP__FUNCTION, ip, &tal);
546
547                 if (tal.sym)
548                         fprintf(f, "..... %016" PRIx64 " %s\n", ip,
549                                 tal.sym->name);
550                 else
551                         fprintf(f, "..... %016" PRIx64 "\n", ip);
552         }
553
554 exit:
555         fclose(f);
556
557         return p;
558 }
559
560 typedef int (*tracepoint_handler)(struct perf_evsel *evsel,
561                                   struct perf_sample *sample,
562                                   const char *backtrace);
563
564 static int process_sample_event(struct perf_tool *tool __maybe_unused,
565                                 union perf_event *event __maybe_unused,
566                                 struct perf_sample *sample,
567                                 struct perf_evsel *evsel,
568                                 struct machine *machine __maybe_unused)
569 {
570         if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
571                 if (!first_time || first_time > sample->time)
572                         first_time = sample->time;
573                 if (last_time < sample->time)
574                         last_time = sample->time;
575         }
576
577         if (sample->cpu > numcpus)
578                 numcpus = sample->cpu;
579
580         if (evsel->handler != NULL) {
581                 tracepoint_handler f = evsel->handler;
582                 return f(evsel, sample, cat_backtrace(event, sample, machine));
583         }
584
585         return 0;
586 }
587
588 static int
589 process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused,
590                         struct perf_sample *sample,
591                         const char *backtrace __maybe_unused)
592 {
593         struct power_processor_entry *ppe = sample->raw_data;
594
595         if (ppe->state == (u32) PWR_EVENT_EXIT)
596                 c_state_end(ppe->cpu_id, sample->time);
597         else
598                 c_state_start(ppe->cpu_id, sample->time, ppe->state);
599         return 0;
600 }
601
602 static int
603 process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused,
604                              struct perf_sample *sample,
605                              const char *backtrace __maybe_unused)
606 {
607         struct power_processor_entry *ppe = sample->raw_data;
608
609         p_state_change(ppe->cpu_id, sample->time, ppe->state);
610         return 0;
611 }
612
613 static int
614 process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused,
615                             struct perf_sample *sample,
616                             const char *backtrace)
617 {
618         struct trace_entry *te = sample->raw_data;
619
620         sched_wakeup(sample->cpu, sample->time, sample->pid, te, backtrace);
621         return 0;
622 }
623
624 static int
625 process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused,
626                             struct perf_sample *sample,
627                             const char *backtrace)
628 {
629         struct trace_entry *te = sample->raw_data;
630
631         sched_switch(sample->cpu, sample->time, te, backtrace);
632         return 0;
633 }
634
635 #ifdef SUPPORT_OLD_POWER_EVENTS
636 static int
637 process_sample_power_start(struct perf_evsel *evsel __maybe_unused,
638                            struct perf_sample *sample,
639                            const char *backtrace __maybe_unused)
640 {
641         struct power_entry_old *peo = sample->raw_data;
642
643         c_state_start(peo->cpu_id, sample->time, peo->value);
644         return 0;
645 }
646
647 static int
648 process_sample_power_end(struct perf_evsel *evsel __maybe_unused,
649                          struct perf_sample *sample,
650                          const char *backtrace __maybe_unused)
651 {
652         c_state_end(sample->cpu, sample->time);
653         return 0;
654 }
655
656 static int
657 process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused,
658                                struct perf_sample *sample,
659                                const char *backtrace __maybe_unused)
660 {
661         struct power_entry_old *peo = sample->raw_data;
662
663         p_state_change(peo->cpu_id, sample->time, peo->value);
664         return 0;
665 }
666 #endif /* SUPPORT_OLD_POWER_EVENTS */
667
668 /*
669  * After the last sample we need to wrap up the current C/P state
670  * and close out each CPU for these.
671  */
672 static void end_sample_processing(void)
673 {
674         u64 cpu;
675         struct power_event *pwr;
676
677         for (cpu = 0; cpu <= numcpus; cpu++) {
678                 /* C state */
679 #if 0
680                 pwr = zalloc(sizeof(*pwr));
681                 if (!pwr)
682                         return;
683
684                 pwr->state = cpus_cstate_state[cpu];
685                 pwr->start_time = cpus_cstate_start_times[cpu];
686                 pwr->end_time = last_time;
687                 pwr->cpu = cpu;
688                 pwr->type = CSTATE;
689                 pwr->next = power_events;
690
691                 power_events = pwr;
692 #endif
693                 /* P state */
694
695                 pwr = zalloc(sizeof(*pwr));
696                 if (!pwr)
697                         return;
698
699                 pwr->state = cpus_pstate_state[cpu];
700                 pwr->start_time = cpus_pstate_start_times[cpu];
701                 pwr->end_time = last_time;
702                 pwr->cpu = cpu;
703                 pwr->type = PSTATE;
704                 pwr->next = power_events;
705
706                 if (!pwr->start_time)
707                         pwr->start_time = first_time;
708                 if (!pwr->state)
709                         pwr->state = min_freq;
710                 power_events = pwr;
711         }
712 }
713
714 /*
715  * Sort the pid datastructure
716  */
717 static void sort_pids(void)
718 {
719         struct per_pid *new_list, *p, *cursor, *prev;
720         /* sort by ppid first, then by pid, lowest to highest */
721
722         new_list = NULL;
723
724         while (all_data) {
725                 p = all_data;
726                 all_data = p->next;
727                 p->next = NULL;
728
729                 if (new_list == NULL) {
730                         new_list = p;
731                         p->next = NULL;
732                         continue;
733                 }
734                 prev = NULL;
735                 cursor = new_list;
736                 while (cursor) {
737                         if (cursor->ppid > p->ppid ||
738                                 (cursor->ppid == p->ppid && cursor->pid > p->pid)) {
739                                 /* must insert before */
740                                 if (prev) {
741                                         p->next = prev->next;
742                                         prev->next = p;
743                                         cursor = NULL;
744                                         continue;
745                                 } else {
746                                         p->next = new_list;
747                                         new_list = p;
748                                         cursor = NULL;
749                                         continue;
750                                 }
751                         }
752
753                         prev = cursor;
754                         cursor = cursor->next;
755                         if (!cursor)
756                                 prev->next = p;
757                 }
758         }
759         all_data = new_list;
760 }
761
762
763 static void draw_c_p_states(void)
764 {
765         struct power_event *pwr;
766         pwr = power_events;
767
768         /*
769          * two pass drawing so that the P state bars are on top of the C state blocks
770          */
771         while (pwr) {
772                 if (pwr->type == CSTATE)
773                         svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
774                 pwr = pwr->next;
775         }
776
777         pwr = power_events;
778         while (pwr) {
779                 if (pwr->type == PSTATE) {
780                         if (!pwr->state)
781                                 pwr->state = min_freq;
782                         svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
783                 }
784                 pwr = pwr->next;
785         }
786 }
787
788 static void draw_wakeups(void)
789 {
790         struct wake_event *we;
791         struct per_pid *p;
792         struct per_pidcomm *c;
793
794         we = wake_events;
795         while (we) {
796                 int from = 0, to = 0;
797                 char *task_from = NULL, *task_to = NULL;
798
799                 /* locate the column of the waker and wakee */
800                 p = all_data;
801                 while (p) {
802                         if (p->pid == we->waker || p->pid == we->wakee) {
803                                 c = p->all;
804                                 while (c) {
805                                         if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
806                                                 if (p->pid == we->waker && !from) {
807                                                         from = c->Y;
808                                                         task_from = strdup(c->comm);
809                                                 }
810                                                 if (p->pid == we->wakee && !to) {
811                                                         to = c->Y;
812                                                         task_to = strdup(c->comm);
813                                                 }
814                                         }
815                                         c = c->next;
816                                 }
817                                 c = p->all;
818                                 while (c) {
819                                         if (p->pid == we->waker && !from) {
820                                                 from = c->Y;
821                                                 task_from = strdup(c->comm);
822                                         }
823                                         if (p->pid == we->wakee && !to) {
824                                                 to = c->Y;
825                                                 task_to = strdup(c->comm);
826                                         }
827                                         c = c->next;
828                                 }
829                         }
830                         p = p->next;
831                 }
832
833                 if (!task_from) {
834                         task_from = malloc(40);
835                         sprintf(task_from, "[%i]", we->waker);
836                 }
837                 if (!task_to) {
838                         task_to = malloc(40);
839                         sprintf(task_to, "[%i]", we->wakee);
840                 }
841
842                 if (we->waker == -1)
843                         svg_interrupt(we->time, to, we->backtrace);
844                 else if (from && to && abs(from - to) == 1)
845                         svg_wakeline(we->time, from, to, we->backtrace);
846                 else
847                         svg_partial_wakeline(we->time, from, task_from, to,
848                                              task_to, we->backtrace);
849                 we = we->next;
850
851                 free(task_from);
852                 free(task_to);
853         }
854 }
855
856 static void draw_cpu_usage(void)
857 {
858         struct per_pid *p;
859         struct per_pidcomm *c;
860         struct cpu_sample *sample;
861         p = all_data;
862         while (p) {
863                 c = p->all;
864                 while (c) {
865                         sample = c->samples;
866                         while (sample) {
867                                 if (sample->type == TYPE_RUNNING)
868                                         svg_process(sample->cpu, sample->start_time, sample->end_time, "sample", c->comm);
869
870                                 sample = sample->next;
871                         }
872                         c = c->next;
873                 }
874                 p = p->next;
875         }
876 }
877
878 static void draw_process_bars(void)
879 {
880         struct per_pid *p;
881         struct per_pidcomm *c;
882         struct cpu_sample *sample;
883         int Y = 0;
884
885         Y = 2 * numcpus + 2;
886
887         p = all_data;
888         while (p) {
889                 c = p->all;
890                 while (c) {
891                         if (!c->display) {
892                                 c->Y = 0;
893                                 c = c->next;
894                                 continue;
895                         }
896
897                         svg_box(Y, c->start_time, c->end_time, "process");
898                         sample = c->samples;
899                         while (sample) {
900                                 if (sample->type == TYPE_RUNNING)
901                                         svg_running(Y, sample->cpu,
902                                                     sample->start_time,
903                                                     sample->end_time,
904                                                     sample->backtrace);
905                                 if (sample->type == TYPE_BLOCKED)
906                                         svg_blocked(Y, sample->cpu,
907                                                     sample->start_time,
908                                                     sample->end_time,
909                                                     sample->backtrace);
910                                 if (sample->type == TYPE_WAITING)
911                                         svg_waiting(Y, sample->cpu,
912                                                     sample->start_time,
913                                                     sample->end_time,
914                                                     sample->backtrace);
915                                 sample = sample->next;
916                         }
917
918                         if (c->comm) {
919                                 char comm[256];
920                                 if (c->total_time > 5000000000) /* 5 seconds */
921                                         sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / 1000000000.0);
922                                 else
923                                         sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / 1000000.0);
924
925                                 svg_text(Y, c->start_time, comm);
926                         }
927                         c->Y = Y;
928                         Y++;
929                         c = c->next;
930                 }
931                 p = p->next;
932         }
933 }
934
935 static void add_process_filter(const char *string)
936 {
937         int pid = strtoull(string, NULL, 10);
938         struct process_filter *filt = malloc(sizeof(*filt));
939
940         if (!filt)
941                 return;
942
943         filt->name = strdup(string);
944         filt->pid  = pid;
945         filt->next = process_filter;
946
947         process_filter = filt;
948 }
949
950 static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
951 {
952         struct process_filter *filt;
953         if (!process_filter)
954                 return 1;
955
956         filt = process_filter;
957         while (filt) {
958                 if (filt->pid && p->pid == filt->pid)
959                         return 1;
960                 if (strcmp(filt->name, c->comm) == 0)
961                         return 1;
962                 filt = filt->next;
963         }
964         return 0;
965 }
966
967 static int determine_display_tasks_filtered(void)
968 {
969         struct per_pid *p;
970         struct per_pidcomm *c;
971         int count = 0;
972
973         p = all_data;
974         while (p) {
975                 p->display = 0;
976                 if (p->start_time == 1)
977                         p->start_time = first_time;
978
979                 /* no exit marker, task kept running to the end */
980                 if (p->end_time == 0)
981                         p->end_time = last_time;
982
983                 c = p->all;
984
985                 while (c) {
986                         c->display = 0;
987
988                         if (c->start_time == 1)
989                                 c->start_time = first_time;
990
991                         if (passes_filter(p, c)) {
992                                 c->display = 1;
993                                 p->display = 1;
994                                 count++;
995                         }
996
997                         if (c->end_time == 0)
998                                 c->end_time = last_time;
999
1000                         c = c->next;
1001                 }
1002                 p = p->next;
1003         }
1004         return count;
1005 }
1006
1007 static int determine_display_tasks(u64 threshold)
1008 {
1009         struct per_pid *p;
1010         struct per_pidcomm *c;
1011         int count = 0;
1012
1013         if (process_filter)
1014                 return determine_display_tasks_filtered();
1015
1016         p = all_data;
1017         while (p) {
1018                 p->display = 0;
1019                 if (p->start_time == 1)
1020                         p->start_time = first_time;
1021
1022                 /* no exit marker, task kept running to the end */
1023                 if (p->end_time == 0)
1024                         p->end_time = last_time;
1025                 if (p->total_time >= threshold)
1026                         p->display = 1;
1027
1028                 c = p->all;
1029
1030                 while (c) {
1031                         c->display = 0;
1032
1033                         if (c->start_time == 1)
1034                                 c->start_time = first_time;
1035
1036                         if (c->total_time >= threshold) {
1037                                 c->display = 1;
1038                                 count++;
1039                         }
1040
1041                         if (c->end_time == 0)
1042                                 c->end_time = last_time;
1043
1044                         c = c->next;
1045                 }
1046                 p = p->next;
1047         }
1048         return count;
1049 }
1050
1051
1052
1053 #define TIME_THRESH 10000000
1054
1055 static void write_svg_file(const char *filename)
1056 {
1057         u64 i;
1058         int count;
1059         int thresh = TIME_THRESH;
1060
1061         numcpus++;
1062
1063         if (power_only)
1064                 proc_num = 0;
1065
1066         /* We'd like to show at least proc_num tasks;
1067          * be less picky if we have fewer */
1068         do {
1069                 count = determine_display_tasks(thresh);
1070                 thresh /= 10;
1071         } while (!process_filter && thresh && count < proc_num);
1072
1073         open_svg(filename, numcpus, count, first_time, last_time);
1074
1075         svg_time_grid();
1076         svg_legenda();
1077
1078         for (i = 0; i < numcpus; i++)
1079                 svg_cpu_box(i, max_freq, turbo_frequency);
1080
1081         draw_cpu_usage();
1082         if (proc_num)
1083                 draw_process_bars();
1084         if (!tasks_only)
1085                 draw_c_p_states();
1086         if (proc_num)
1087                 draw_wakeups();
1088
1089         svg_close();
1090 }
1091
1092 static int __cmd_timechart(const char *output_name)
1093 {
1094         struct perf_tool perf_timechart = {
1095                 .comm            = process_comm_event,
1096                 .fork            = process_fork_event,
1097                 .exit            = process_exit_event,
1098                 .sample          = process_sample_event,
1099                 .ordered_samples = true,
1100         };
1101         const struct perf_evsel_str_handler power_tracepoints[] = {
1102                 { "power:cpu_idle",             process_sample_cpu_idle },
1103                 { "power:cpu_frequency",        process_sample_cpu_frequency },
1104                 { "sched:sched_wakeup",         process_sample_sched_wakeup },
1105                 { "sched:sched_switch",         process_sample_sched_switch },
1106 #ifdef SUPPORT_OLD_POWER_EVENTS
1107                 { "power:power_start",          process_sample_power_start },
1108                 { "power:power_end",            process_sample_power_end },
1109                 { "power:power_frequency",      process_sample_power_frequency },
1110 #endif
1111         };
1112         struct perf_data_file file = {
1113                 .path = input_name,
1114                 .mode = PERF_DATA_MODE_READ,
1115         };
1116
1117         struct perf_session *session = perf_session__new(&file, false,
1118                                                          &perf_timechart);
1119         int ret = -EINVAL;
1120
1121         if (session == NULL)
1122                 return -ENOMEM;
1123
1124         if (!perf_session__has_traces(session, "timechart record"))
1125                 goto out_delete;
1126
1127         if (perf_session__set_tracepoints_handlers(session,
1128                                                    power_tracepoints)) {
1129                 pr_err("Initializing session tracepoint handlers failed\n");
1130                 goto out_delete;
1131         }
1132
1133         ret = perf_session__process_events(session, &perf_timechart);
1134         if (ret)
1135                 goto out_delete;
1136
1137         end_sample_processing();
1138
1139         sort_pids();
1140
1141         write_svg_file(output_name);
1142
1143         pr_info("Written %2.1f seconds of trace to %s.\n",
1144                 (last_time - first_time) / 1000000000.0, output_name);
1145 out_delete:
1146         perf_session__delete(session);
1147         return ret;
1148 }
1149
1150 static int __cmd_record(int argc, const char **argv)
1151 {
1152         unsigned int rec_argc, i, j;
1153         const char **rec_argv;
1154         const char **p;
1155         unsigned int record_elems;
1156
1157         const char * const common_args[] = {
1158                 "record", "-a", "-R", "-c", "1",
1159         };
1160         unsigned int common_args_nr = ARRAY_SIZE(common_args);
1161
1162         const char * const backtrace_args[] = {
1163                 "-g",
1164         };
1165         unsigned int backtrace_args_no = ARRAY_SIZE(backtrace_args);
1166
1167         const char * const power_args[] = {
1168                 "-e", "power:cpu_frequency",
1169                 "-e", "power:cpu_idle",
1170         };
1171         unsigned int power_args_nr = ARRAY_SIZE(power_args);
1172
1173         const char * const old_power_args[] = {
1174 #ifdef SUPPORT_OLD_POWER_EVENTS
1175                 "-e", "power:power_start",
1176                 "-e", "power:power_end",
1177                 "-e", "power:power_frequency",
1178 #endif
1179         };
1180         unsigned int old_power_args_nr = ARRAY_SIZE(old_power_args);
1181
1182         const char * const tasks_args[] = {
1183                 "-e", "sched:sched_wakeup",
1184                 "-e", "sched:sched_switch",
1185         };
1186         unsigned int tasks_args_nr = ARRAY_SIZE(tasks_args);
1187
1188 #ifdef SUPPORT_OLD_POWER_EVENTS
1189         if (!is_valid_tracepoint("power:cpu_idle") &&
1190             is_valid_tracepoint("power:power_start")) {
1191                 use_old_power_events = 1;
1192                 power_args_nr = 0;
1193         } else {
1194                 old_power_args_nr = 0;
1195         }
1196 #endif
1197
1198         if (power_only)
1199                 tasks_args_nr = 0;
1200
1201         if (tasks_only) {
1202                 power_args_nr = 0;
1203                 old_power_args_nr = 0;
1204         }
1205
1206         if (!with_backtrace)
1207                 backtrace_args_no = 0;
1208
1209         record_elems = common_args_nr + tasks_args_nr +
1210                 power_args_nr + old_power_args_nr + backtrace_args_no;
1211
1212         rec_argc = record_elems + argc;
1213         rec_argv = calloc(rec_argc + 1, sizeof(char *));
1214
1215         if (rec_argv == NULL)
1216                 return -ENOMEM;
1217
1218         p = rec_argv;
1219         for (i = 0; i < common_args_nr; i++)
1220                 *p++ = strdup(common_args[i]);
1221
1222         for (i = 0; i < backtrace_args_no; i++)
1223                 *p++ = strdup(backtrace_args[i]);
1224
1225         for (i = 0; i < tasks_args_nr; i++)
1226                 *p++ = strdup(tasks_args[i]);
1227
1228         for (i = 0; i < power_args_nr; i++)
1229                 *p++ = strdup(power_args[i]);
1230
1231         for (i = 0; i < old_power_args_nr; i++)
1232                 *p++ = strdup(old_power_args[i]);
1233
1234         for (j = 1; j < (unsigned int)argc; j++)
1235                 *p++ = argv[j];
1236
1237         return cmd_record(rec_argc, rec_argv, NULL);
1238 }
1239
1240 static int
1241 parse_process(const struct option *opt __maybe_unused, const char *arg,
1242               int __maybe_unused unset)
1243 {
1244         if (arg)
1245                 add_process_filter(arg);
1246         return 0;
1247 }
1248
1249 int cmd_timechart(int argc, const char **argv,
1250                   const char *prefix __maybe_unused)
1251 {
1252         const char *output_name = "output.svg";
1253         const struct option timechart_options[] = {
1254         OPT_STRING('i', "input", &input_name, "file", "input file name"),
1255         OPT_STRING('o', "output", &output_name, "file", "output file name"),
1256         OPT_INTEGER('w', "width", &svg_page_width, "page width"),
1257         OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
1258         OPT_BOOLEAN('T', "tasks-only", &tasks_only,
1259                     "output processes data only"),
1260         OPT_CALLBACK('p', "process", NULL, "process",
1261                       "process selector. Pass a pid or process name.",
1262                        parse_process),
1263         OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1264                     "Look for files with symbols relative to this directory"),
1265         OPT_INTEGER('n', "proc-num", &proc_num,
1266                     "min. number of tasks to print"),
1267         OPT_END()
1268         };
1269         const char * const timechart_usage[] = {
1270                 "perf timechart [<options>] {record}",
1271                 NULL
1272         };
1273
1274         const struct option record_options[] = {
1275         OPT_BOOLEAN('P', "power-only", &power_only, "output power data only"),
1276         OPT_BOOLEAN('T', "tasks-only", &tasks_only,
1277                     "output processes data only"),
1278         OPT_BOOLEAN('g', "callchain", &with_backtrace, "record callchain"),
1279         OPT_END()
1280         };
1281         const char * const record_usage[] = {
1282                 "perf timechart record [<options>]",
1283                 NULL
1284         };
1285         argc = parse_options(argc, argv, timechart_options, timechart_usage,
1286                         PARSE_OPT_STOP_AT_NON_OPTION);
1287
1288         if (power_only && tasks_only) {
1289                 pr_err("-P and -T options cannot be used at the same time.\n");
1290                 return -1;
1291         }
1292
1293         symbol__init();
1294
1295         if (argc && !strncmp(argv[0], "rec", 3)) {
1296                 argc = parse_options(argc, argv, record_options, record_usage,
1297                                      PARSE_OPT_STOP_AT_NON_OPTION);
1298
1299                 if (power_only && tasks_only) {
1300                         pr_err("-P and -T options cannot be used at the same time.\n");
1301                         return -1;
1302                 }
1303
1304                 return __cmd_record(argc, argv);
1305         } else if (argc)
1306                 usage_with_options(timechart_usage, timechart_options);
1307
1308         setup_pager();
1309
1310         return __cmd_timechart(output_name);
1311 }