Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.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 "builtin.h"
16
17 #include "util/util.h"
18
19 #include "util/color.h"
20 #include <linux/list.h>
21 #include "util/cache.h"
22 #include "util/evsel.h"
23 #include <linux/rbtree.h>
24 #include "util/symbol.h"
25 #include "util/callchain.h"
26 #include "util/strlist.h"
27
28 #include "perf.h"
29 #include "util/header.h"
30 #include "util/parse-options.h"
31 #include "util/parse-events.h"
32 #include "util/event.h"
33 #include "util/session.h"
34 #include "util/svghelper.h"
35 #include "util/tool.h"
36
37 #define SUPPORT_OLD_POWER_EVENTS 1
38 #define PWR_EVENT_EXIT -1
39
40
41 static const char       *input_name;
42 static const char       *output_name = "output.svg";
43
44 static unsigned int     numcpus;
45 static u64              min_freq;       /* Lowest CPU frequency seen */
46 static u64              max_freq;       /* Highest CPU frequency seen */
47 static u64              turbo_frequency;
48
49 static u64              first_time, last_time;
50
51 static bool             power_only;
52
53
54 struct per_pid;
55 struct per_pidcomm;
56
57 struct cpu_sample;
58 struct power_event;
59 struct wake_event;
60
61 struct sample_wrapper;
62
63 /*
64  * Datastructure layout:
65  * We keep an list of "pid"s, matching the kernels notion of a task struct.
66  * Each "pid" entry, has a list of "comm"s.
67  *      this is because we want to track different programs different, while
68  *      exec will reuse the original pid (by design).
69  * Each comm has a list of samples that will be used to draw
70  * final graph.
71  */
72
73 struct per_pid {
74         struct per_pid *next;
75
76         int             pid;
77         int             ppid;
78
79         u64             start_time;
80         u64             end_time;
81         u64             total_time;
82         int             display;
83
84         struct per_pidcomm *all;
85         struct per_pidcomm *current;
86 };
87
88
89 struct per_pidcomm {
90         struct per_pidcomm *next;
91
92         u64             start_time;
93         u64             end_time;
94         u64             total_time;
95
96         int             Y;
97         int             display;
98
99         long            state;
100         u64             state_since;
101
102         char            *comm;
103
104         struct cpu_sample *samples;
105 };
106
107 struct sample_wrapper {
108         struct sample_wrapper *next;
109
110         u64             timestamp;
111         unsigned char   data[0];
112 };
113
114 #define TYPE_NONE       0
115 #define TYPE_RUNNING    1
116 #define TYPE_WAITING    2
117 #define TYPE_BLOCKED    3
118
119 struct cpu_sample {
120         struct cpu_sample *next;
121
122         u64 start_time;
123         u64 end_time;
124         int type;
125         int cpu;
126 };
127
128 static struct per_pid *all_data;
129
130 #define CSTATE 1
131 #define PSTATE 2
132
133 struct power_event {
134         struct power_event *next;
135         int type;
136         int state;
137         u64 start_time;
138         u64 end_time;
139         int cpu;
140 };
141
142 struct wake_event {
143         struct wake_event *next;
144         int waker;
145         int wakee;
146         u64 time;
147 };
148
149 static struct power_event    *power_events;
150 static struct wake_event     *wake_events;
151
152 struct process_filter;
153 struct process_filter {
154         char                    *name;
155         int                     pid;
156         struct process_filter   *next;
157 };
158
159 static struct process_filter *process_filter;
160
161
162 static struct per_pid *find_create_pid(int pid)
163 {
164         struct per_pid *cursor = all_data;
165
166         while (cursor) {
167                 if (cursor->pid == pid)
168                         return cursor;
169                 cursor = cursor->next;
170         }
171         cursor = malloc(sizeof(struct per_pid));
172         assert(cursor != NULL);
173         memset(cursor, 0, sizeof(struct per_pid));
174         cursor->pid = pid;
175         cursor->next = all_data;
176         all_data = cursor;
177         return cursor;
178 }
179
180 static void pid_set_comm(int pid, char *comm)
181 {
182         struct per_pid *p;
183         struct per_pidcomm *c;
184         p = find_create_pid(pid);
185         c = p->all;
186         while (c) {
187                 if (c->comm && strcmp(c->comm, comm) == 0) {
188                         p->current = c;
189                         return;
190                 }
191                 if (!c->comm) {
192                         c->comm = strdup(comm);
193                         p->current = c;
194                         return;
195                 }
196                 c = c->next;
197         }
198         c = malloc(sizeof(struct per_pidcomm));
199         assert(c != NULL);
200         memset(c, 0, sizeof(struct per_pidcomm));
201         c->comm = strdup(comm);
202         p->current = c;
203         c->next = p->all;
204         p->all = c;
205 }
206
207 static void pid_fork(int pid, int ppid, u64 timestamp)
208 {
209         struct per_pid *p, *pp;
210         p = find_create_pid(pid);
211         pp = find_create_pid(ppid);
212         p->ppid = ppid;
213         if (pp->current && pp->current->comm && !p->current)
214                 pid_set_comm(pid, pp->current->comm);
215
216         p->start_time = timestamp;
217         if (p->current) {
218                 p->current->start_time = timestamp;
219                 p->current->state_since = timestamp;
220         }
221 }
222
223 static void pid_exit(int pid, u64 timestamp)
224 {
225         struct per_pid *p;
226         p = find_create_pid(pid);
227         p->end_time = timestamp;
228         if (p->current)
229                 p->current->end_time = timestamp;
230 }
231
232 static void
233 pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end)
234 {
235         struct per_pid *p;
236         struct per_pidcomm *c;
237         struct cpu_sample *sample;
238
239         p = find_create_pid(pid);
240         c = p->current;
241         if (!c) {
242                 c = malloc(sizeof(struct per_pidcomm));
243                 assert(c != NULL);
244                 memset(c, 0, sizeof(struct per_pidcomm));
245                 p->current = c;
246                 c->next = p->all;
247                 p->all = c;
248         }
249
250         sample = malloc(sizeof(struct cpu_sample));
251         assert(sample != NULL);
252         memset(sample, 0, sizeof(struct cpu_sample));
253         sample->start_time = start;
254         sample->end_time = end;
255         sample->type = type;
256         sample->next = c->samples;
257         sample->cpu = cpu;
258         c->samples = sample;
259
260         if (sample->type == TYPE_RUNNING && end > start && start > 0) {
261                 c->total_time += (end-start);
262                 p->total_time += (end-start);
263         }
264
265         if (c->start_time == 0 || c->start_time > start)
266                 c->start_time = start;
267         if (p->start_time == 0 || p->start_time > start)
268                 p->start_time = start;
269 }
270
271 #define MAX_CPUS 4096
272
273 static u64 cpus_cstate_start_times[MAX_CPUS];
274 static int cpus_cstate_state[MAX_CPUS];
275 static u64 cpus_pstate_start_times[MAX_CPUS];
276 static u64 cpus_pstate_state[MAX_CPUS];
277
278 static int process_comm_event(struct perf_tool *tool __used,
279                               union perf_event *event,
280                               struct perf_sample *sample __used,
281                               struct machine *machine __used)
282 {
283         pid_set_comm(event->comm.tid, event->comm.comm);
284         return 0;
285 }
286
287 static int process_fork_event(struct perf_tool *tool __used,
288                               union perf_event *event,
289                               struct perf_sample *sample __used,
290                               struct machine *machine __used)
291 {
292         pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
293         return 0;
294 }
295
296 static int process_exit_event(struct perf_tool *tool __used,
297                               union perf_event *event,
298                               struct perf_sample *sample __used,
299                               struct machine *machine __used)
300 {
301         pid_exit(event->fork.pid, event->fork.time);
302         return 0;
303 }
304
305 struct trace_entry {
306         unsigned short          type;
307         unsigned char           flags;
308         unsigned char           preempt_count;
309         int                     pid;
310         int                     lock_depth;
311 };
312
313 #ifdef SUPPORT_OLD_POWER_EVENTS
314 static int use_old_power_events;
315 struct power_entry_old {
316         struct trace_entry te;
317         u64     type;
318         u64     value;
319         u64     cpu_id;
320 };
321 #endif
322
323 struct power_processor_entry {
324         struct trace_entry te;
325         u32     state;
326         u32     cpu_id;
327 };
328
329 #define TASK_COMM_LEN 16
330 struct wakeup_entry {
331         struct trace_entry te;
332         char comm[TASK_COMM_LEN];
333         int   pid;
334         int   prio;
335         int   success;
336 };
337
338 /*
339  * trace_flag_type is an enumeration that holds different
340  * states when a trace occurs. These are:
341  *  IRQS_OFF            - interrupts were disabled
342  *  IRQS_NOSUPPORT      - arch does not support irqs_disabled_flags
343  *  NEED_RESCED         - reschedule is requested
344  *  HARDIRQ             - inside an interrupt handler
345  *  SOFTIRQ             - inside a softirq handler
346  */
347 enum trace_flag_type {
348         TRACE_FLAG_IRQS_OFF             = 0x01,
349         TRACE_FLAG_IRQS_NOSUPPORT       = 0x02,
350         TRACE_FLAG_NEED_RESCHED         = 0x04,
351         TRACE_FLAG_HARDIRQ              = 0x08,
352         TRACE_FLAG_SOFTIRQ              = 0x10,
353 };
354
355
356
357 struct sched_switch {
358         struct trace_entry te;
359         char prev_comm[TASK_COMM_LEN];
360         int  prev_pid;
361         int  prev_prio;
362         long prev_state; /* Arjan weeps. */
363         char next_comm[TASK_COMM_LEN];
364         int  next_pid;
365         int  next_prio;
366 };
367
368 static void c_state_start(int cpu, u64 timestamp, int state)
369 {
370         cpus_cstate_start_times[cpu] = timestamp;
371         cpus_cstate_state[cpu] = state;
372 }
373
374 static void c_state_end(int cpu, u64 timestamp)
375 {
376         struct power_event *pwr;
377         pwr = malloc(sizeof(struct power_event));
378         if (!pwr)
379                 return;
380         memset(pwr, 0, sizeof(struct power_event));
381
382         pwr->state = cpus_cstate_state[cpu];
383         pwr->start_time = cpus_cstate_start_times[cpu];
384         pwr->end_time = timestamp;
385         pwr->cpu = cpu;
386         pwr->type = CSTATE;
387         pwr->next = power_events;
388
389         power_events = pwr;
390 }
391
392 static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
393 {
394         struct power_event *pwr;
395         pwr = malloc(sizeof(struct power_event));
396
397         if (new_freq > 8000000) /* detect invalid data */
398                 return;
399
400         if (!pwr)
401                 return;
402         memset(pwr, 0, sizeof(struct power_event));
403
404         pwr->state = cpus_pstate_state[cpu];
405         pwr->start_time = cpus_pstate_start_times[cpu];
406         pwr->end_time = timestamp;
407         pwr->cpu = cpu;
408         pwr->type = PSTATE;
409         pwr->next = power_events;
410
411         if (!pwr->start_time)
412                 pwr->start_time = first_time;
413
414         power_events = pwr;
415
416         cpus_pstate_state[cpu] = new_freq;
417         cpus_pstate_start_times[cpu] = timestamp;
418
419         if ((u64)new_freq > max_freq)
420                 max_freq = new_freq;
421
422         if (new_freq < min_freq || min_freq == 0)
423                 min_freq = new_freq;
424
425         if (new_freq == max_freq - 1000)
426                         turbo_frequency = max_freq;
427 }
428
429 static void
430 sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te)
431 {
432         struct wake_event *we;
433         struct per_pid *p;
434         struct wakeup_entry *wake = (void *)te;
435
436         we = malloc(sizeof(struct wake_event));
437         if (!we)
438                 return;
439
440         memset(we, 0, sizeof(struct wake_event));
441         we->time = timestamp;
442         we->waker = pid;
443
444         if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ))
445                 we->waker = -1;
446
447         we->wakee = wake->pid;
448         we->next = wake_events;
449         wake_events = we;
450         p = find_create_pid(we->wakee);
451
452         if (p && p->current && p->current->state == TYPE_NONE) {
453                 p->current->state_since = timestamp;
454                 p->current->state = TYPE_WAITING;
455         }
456         if (p && p->current && p->current->state == TYPE_BLOCKED) {
457                 pid_put_sample(p->pid, p->current->state, cpu, p->current->state_since, timestamp);
458                 p->current->state_since = timestamp;
459                 p->current->state = TYPE_WAITING;
460         }
461 }
462
463 static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
464 {
465         struct per_pid *p = NULL, *prev_p;
466         struct sched_switch *sw = (void *)te;
467
468
469         prev_p = find_create_pid(sw->prev_pid);
470
471         p = find_create_pid(sw->next_pid);
472
473         if (prev_p->current && prev_p->current->state != TYPE_NONE)
474                 pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, prev_p->current->state_since, timestamp);
475         if (p && p->current) {
476                 if (p->current->state != TYPE_NONE)
477                         pid_put_sample(sw->next_pid, p->current->state, cpu, p->current->state_since, timestamp);
478
479                 p->current->state_since = timestamp;
480                 p->current->state = TYPE_RUNNING;
481         }
482
483         if (prev_p->current) {
484                 prev_p->current->state = TYPE_NONE;
485                 prev_p->current->state_since = timestamp;
486                 if (sw->prev_state & 2)
487                         prev_p->current->state = TYPE_BLOCKED;
488                 if (sw->prev_state == 0)
489                         prev_p->current->state = TYPE_WAITING;
490         }
491 }
492
493
494 static int process_sample_event(struct perf_tool *tool __used,
495                                 union perf_event *event __used,
496                                 struct perf_sample *sample,
497                                 struct perf_evsel *evsel,
498                                 struct machine *machine __used)
499 {
500         struct trace_entry *te;
501
502         if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
503                 if (!first_time || first_time > sample->time)
504                         first_time = sample->time;
505                 if (last_time < sample->time)
506                         last_time = sample->time;
507         }
508
509         te = (void *)sample->raw_data;
510         if ((evsel->attr.sample_type & PERF_SAMPLE_RAW) && sample->raw_size > 0) {
511                 char *event_str;
512 #ifdef SUPPORT_OLD_POWER_EVENTS
513                 struct power_entry_old *peo;
514                 peo = (void *)te;
515 #endif
516                 /*
517                  * FIXME: use evsel, its already mapped from id to perf_evsel,
518                  * remove perf_header__find_event infrastructure bits.
519                  * Mapping all these "power:cpu_idle" strings to the tracepoint
520                  * ID and then just comparing against evsel->attr.config.
521                  *
522                  * e.g.:
523                  *
524                  * if (evsel->attr.config == power_cpu_idle_id)
525                  */
526                 event_str = perf_header__find_event(te->type);
527
528                 if (!event_str)
529                         return 0;
530
531                 if (sample->cpu > numcpus)
532                         numcpus = sample->cpu;
533
534                 if (strcmp(event_str, "power:cpu_idle") == 0) {
535                         struct power_processor_entry *ppe = (void *)te;
536                         if (ppe->state == (u32)PWR_EVENT_EXIT)
537                                 c_state_end(ppe->cpu_id, sample->time);
538                         else
539                                 c_state_start(ppe->cpu_id, sample->time,
540                                               ppe->state);
541                 }
542                 else if (strcmp(event_str, "power:cpu_frequency") == 0) {
543                         struct power_processor_entry *ppe = (void *)te;
544                         p_state_change(ppe->cpu_id, sample->time, ppe->state);
545                 }
546
547                 else if (strcmp(event_str, "sched:sched_wakeup") == 0)
548                         sched_wakeup(sample->cpu, sample->time, sample->pid, te);
549
550                 else if (strcmp(event_str, "sched:sched_switch") == 0)
551                         sched_switch(sample->cpu, sample->time, te);
552
553 #ifdef SUPPORT_OLD_POWER_EVENTS
554                 if (use_old_power_events) {
555                         if (strcmp(event_str, "power:power_start") == 0)
556                                 c_state_start(peo->cpu_id, sample->time,
557                                               peo->value);
558
559                         else if (strcmp(event_str, "power:power_end") == 0)
560                                 c_state_end(sample->cpu, sample->time);
561
562                         else if (strcmp(event_str,
563                                         "power:power_frequency") == 0)
564                                 p_state_change(peo->cpu_id, sample->time,
565                                                peo->value);
566                 }
567 #endif
568         }
569         return 0;
570 }
571
572 /*
573  * After the last sample we need to wrap up the current C/P state
574  * and close out each CPU for these.
575  */
576 static void end_sample_processing(void)
577 {
578         u64 cpu;
579         struct power_event *pwr;
580
581         for (cpu = 0; cpu <= numcpus; cpu++) {
582                 pwr = malloc(sizeof(struct power_event));
583                 if (!pwr)
584                         return;
585                 memset(pwr, 0, sizeof(struct power_event));
586
587                 /* C state */
588 #if 0
589                 pwr->state = cpus_cstate_state[cpu];
590                 pwr->start_time = cpus_cstate_start_times[cpu];
591                 pwr->end_time = last_time;
592                 pwr->cpu = cpu;
593                 pwr->type = CSTATE;
594                 pwr->next = power_events;
595
596                 power_events = pwr;
597 #endif
598                 /* P state */
599
600                 pwr = malloc(sizeof(struct power_event));
601                 if (!pwr)
602                         return;
603                 memset(pwr, 0, sizeof(struct power_event));
604
605                 pwr->state = cpus_pstate_state[cpu];
606                 pwr->start_time = cpus_pstate_start_times[cpu];
607                 pwr->end_time = last_time;
608                 pwr->cpu = cpu;
609                 pwr->type = PSTATE;
610                 pwr->next = power_events;
611
612                 if (!pwr->start_time)
613                         pwr->start_time = first_time;
614                 if (!pwr->state)
615                         pwr->state = min_freq;
616                 power_events = pwr;
617         }
618 }
619
620 /*
621  * Sort the pid datastructure
622  */
623 static void sort_pids(void)
624 {
625         struct per_pid *new_list, *p, *cursor, *prev;
626         /* sort by ppid first, then by pid, lowest to highest */
627
628         new_list = NULL;
629
630         while (all_data) {
631                 p = all_data;
632                 all_data = p->next;
633                 p->next = NULL;
634
635                 if (new_list == NULL) {
636                         new_list = p;
637                         p->next = NULL;
638                         continue;
639                 }
640                 prev = NULL;
641                 cursor = new_list;
642                 while (cursor) {
643                         if (cursor->ppid > p->ppid ||
644                                 (cursor->ppid == p->ppid && cursor->pid > p->pid)) {
645                                 /* must insert before */
646                                 if (prev) {
647                                         p->next = prev->next;
648                                         prev->next = p;
649                                         cursor = NULL;
650                                         continue;
651                                 } else {
652                                         p->next = new_list;
653                                         new_list = p;
654                                         cursor = NULL;
655                                         continue;
656                                 }
657                         }
658
659                         prev = cursor;
660                         cursor = cursor->next;
661                         if (!cursor)
662                                 prev->next = p;
663                 }
664         }
665         all_data = new_list;
666 }
667
668
669 static void draw_c_p_states(void)
670 {
671         struct power_event *pwr;
672         pwr = power_events;
673
674         /*
675          * two pass drawing so that the P state bars are on top of the C state blocks
676          */
677         while (pwr) {
678                 if (pwr->type == CSTATE) {
679                         /* If the first event is an _end event, start timestamp is zero
680                            -> ignore these */
681                         if (pwr->start_time == 0 || pwr->end_time == 0) {
682                                 pwr = pwr->next;
683                                 continue;
684                         }
685                         svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
686                 }
687                 pwr = pwr->next;
688         }
689
690         pwr = power_events;
691         while (pwr) {
692                 if (pwr->type == PSTATE) {
693                         if (!pwr->state)
694                                 pwr->state = min_freq;
695                         svg_pstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
696                 }
697                 pwr = pwr->next;
698         }
699 }
700
701 static void draw_wakeups(void)
702 {
703         struct wake_event *we;
704         struct per_pid *p;
705         struct per_pidcomm *c;
706
707         we = wake_events;
708         while (we) {
709                 int from = 0, to = 0;
710                 char *task_from = NULL, *task_to = NULL;
711
712                 /* locate the column of the waker and wakee */
713                 p = all_data;
714                 while (p) {
715                         if (p->pid == we->waker || p->pid == we->wakee) {
716                                 c = p->all;
717                                 while (c) {
718                                         if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
719                                                 if (p->pid == we->waker && !from) {
720                                                         from = c->Y;
721                                                         task_from = strdup(c->comm);
722                                                 }
723                                                 if (p->pid == we->wakee && !to) {
724                                                         to = c->Y;
725                                                         task_to = strdup(c->comm);
726                                                 }
727                                         }
728                                         c = c->next;
729                                 }
730                                 c = p->all;
731                                 while (c) {
732                                         if (p->pid == we->waker && !from) {
733                                                 from = c->Y;
734                                                 task_from = strdup(c->comm);
735                                         }
736                                         if (p->pid == we->wakee && !to) {
737                                                 to = c->Y;
738                                                 task_to = strdup(c->comm);
739                                         }
740                                         c = c->next;
741                                 }
742                         }
743                         p = p->next;
744                 }
745
746                 if (!task_from) {
747                         task_from = malloc(40);
748                         sprintf(task_from, "[%i]", we->waker);
749                 }
750                 if (!task_to) {
751                         task_to = malloc(40);
752                         sprintf(task_to, "[%i]", we->wakee);
753                 }
754
755                 if (we->waker == -1)
756                         svg_interrupt(we->time, to);
757                 else if (from && to && abs(from - to) == 1)
758                         svg_wakeline(we->time, from, to);
759                 else
760                         svg_partial_wakeline(we->time, from, task_from, to, task_to);
761                 we = we->next;
762
763                 free(task_from);
764                 free(task_to);
765         }
766 }
767
768 static void draw_cpu_usage(void)
769 {
770         struct per_pid *p;
771         struct per_pidcomm *c;
772         struct cpu_sample *sample;
773         p = all_data;
774         while (p) {
775                 c = p->all;
776                 while (c) {
777                         sample = c->samples;
778                         while (sample) {
779                                 if (sample->type == TYPE_RUNNING)
780                                         svg_process(sample->cpu, sample->start_time, sample->end_time, "sample", c->comm);
781
782                                 sample = sample->next;
783                         }
784                         c = c->next;
785                 }
786                 p = p->next;
787         }
788 }
789
790 static void draw_process_bars(void)
791 {
792         struct per_pid *p;
793         struct per_pidcomm *c;
794         struct cpu_sample *sample;
795         int Y = 0;
796
797         Y = 2 * numcpus + 2;
798
799         p = all_data;
800         while (p) {
801                 c = p->all;
802                 while (c) {
803                         if (!c->display) {
804                                 c->Y = 0;
805                                 c = c->next;
806                                 continue;
807                         }
808
809                         svg_box(Y, c->start_time, c->end_time, "process");
810                         sample = c->samples;
811                         while (sample) {
812                                 if (sample->type == TYPE_RUNNING)
813                                         svg_sample(Y, sample->cpu, sample->start_time, sample->end_time);
814                                 if (sample->type == TYPE_BLOCKED)
815                                         svg_box(Y, sample->start_time, sample->end_time, "blocked");
816                                 if (sample->type == TYPE_WAITING)
817                                         svg_waiting(Y, sample->start_time, sample->end_time);
818                                 sample = sample->next;
819                         }
820
821                         if (c->comm) {
822                                 char comm[256];
823                                 if (c->total_time > 5000000000) /* 5 seconds */
824                                         sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / 1000000000.0);
825                                 else
826                                         sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / 1000000.0);
827
828                                 svg_text(Y, c->start_time, comm);
829                         }
830                         c->Y = Y;
831                         Y++;
832                         c = c->next;
833                 }
834                 p = p->next;
835         }
836 }
837
838 static void add_process_filter(const char *string)
839 {
840         struct process_filter *filt;
841         int pid;
842
843         pid = strtoull(string, NULL, 10);
844         filt = malloc(sizeof(struct process_filter));
845         if (!filt)
846                 return;
847
848         filt->name = strdup(string);
849         filt->pid  = pid;
850         filt->next = process_filter;
851
852         process_filter = filt;
853 }
854
855 static int passes_filter(struct per_pid *p, struct per_pidcomm *c)
856 {
857         struct process_filter *filt;
858         if (!process_filter)
859                 return 1;
860
861         filt = process_filter;
862         while (filt) {
863                 if (filt->pid && p->pid == filt->pid)
864                         return 1;
865                 if (strcmp(filt->name, c->comm) == 0)
866                         return 1;
867                 filt = filt->next;
868         }
869         return 0;
870 }
871
872 static int determine_display_tasks_filtered(void)
873 {
874         struct per_pid *p;
875         struct per_pidcomm *c;
876         int count = 0;
877
878         p = all_data;
879         while (p) {
880                 p->display = 0;
881                 if (p->start_time == 1)
882                         p->start_time = first_time;
883
884                 /* no exit marker, task kept running to the end */
885                 if (p->end_time == 0)
886                         p->end_time = last_time;
887
888                 c = p->all;
889
890                 while (c) {
891                         c->display = 0;
892
893                         if (c->start_time == 1)
894                                 c->start_time = first_time;
895
896                         if (passes_filter(p, c)) {
897                                 c->display = 1;
898                                 p->display = 1;
899                                 count++;
900                         }
901
902                         if (c->end_time == 0)
903                                 c->end_time = last_time;
904
905                         c = c->next;
906                 }
907                 p = p->next;
908         }
909         return count;
910 }
911
912 static int determine_display_tasks(u64 threshold)
913 {
914         struct per_pid *p;
915         struct per_pidcomm *c;
916         int count = 0;
917
918         if (process_filter)
919                 return determine_display_tasks_filtered();
920
921         p = all_data;
922         while (p) {
923                 p->display = 0;
924                 if (p->start_time == 1)
925                         p->start_time = first_time;
926
927                 /* no exit marker, task kept running to the end */
928                 if (p->end_time == 0)
929                         p->end_time = last_time;
930                 if (p->total_time >= threshold && !power_only)
931                         p->display = 1;
932
933                 c = p->all;
934
935                 while (c) {
936                         c->display = 0;
937
938                         if (c->start_time == 1)
939                                 c->start_time = first_time;
940
941                         if (c->total_time >= threshold && !power_only) {
942                                 c->display = 1;
943                                 count++;
944                         }
945
946                         if (c->end_time == 0)
947                                 c->end_time = last_time;
948
949                         c = c->next;
950                 }
951                 p = p->next;
952         }
953         return count;
954 }
955
956
957
958 #define TIME_THRESH 10000000
959
960 static void write_svg_file(const char *filename)
961 {
962         u64 i;
963         int count;
964
965         numcpus++;
966
967
968         count = determine_display_tasks(TIME_THRESH);
969
970         /* We'd like to show at least 15 tasks; be less picky if we have fewer */
971         if (count < 15)
972                 count = determine_display_tasks(TIME_THRESH / 10);
973
974         open_svg(filename, numcpus, count, first_time, last_time);
975
976         svg_time_grid();
977         svg_legenda();
978
979         for (i = 0; i < numcpus; i++)
980                 svg_cpu_box(i, max_freq, turbo_frequency);
981
982         draw_cpu_usage();
983         draw_process_bars();
984         draw_c_p_states();
985         draw_wakeups();
986
987         svg_close();
988 }
989
990 static struct perf_tool perf_timechart = {
991         .comm                   = process_comm_event,
992         .fork                   = process_fork_event,
993         .exit                   = process_exit_event,
994         .sample                 = process_sample_event,
995         .ordered_samples        = true,
996 };
997
998 static int __cmd_timechart(void)
999 {
1000         struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1001                                                          0, false, &perf_timechart);
1002         int ret = -EINVAL;
1003
1004         if (session == NULL)
1005                 return -ENOMEM;
1006
1007         if (!perf_session__has_traces(session, "timechart record"))
1008                 goto out_delete;
1009
1010         ret = perf_session__process_events(session, &perf_timechart);
1011         if (ret)
1012                 goto out_delete;
1013
1014         end_sample_processing();
1015
1016         sort_pids();
1017
1018         write_svg_file(output_name);
1019
1020         pr_info("Written %2.1f seconds of trace to %s.\n",
1021                 (last_time - first_time) / 1000000000.0, output_name);
1022 out_delete:
1023         perf_session__delete(session);
1024         return ret;
1025 }
1026
1027 static const char * const timechart_usage[] = {
1028         "perf timechart [<options>] {record}",
1029         NULL
1030 };
1031
1032 #ifdef SUPPORT_OLD_POWER_EVENTS
1033 static const char * const record_old_args[] = {
1034         "record",
1035         "-a",
1036         "-R",
1037         "-f",
1038         "-c", "1",
1039         "-e", "power:power_start",
1040         "-e", "power:power_end",
1041         "-e", "power:power_frequency",
1042         "-e", "sched:sched_wakeup",
1043         "-e", "sched:sched_switch",
1044 };
1045 #endif
1046
1047 static const char * const record_new_args[] = {
1048         "record",
1049         "-a",
1050         "-R",
1051         "-f",
1052         "-c", "1",
1053         "-e", "power:cpu_frequency",
1054         "-e", "power:cpu_idle",
1055         "-e", "sched:sched_wakeup",
1056         "-e", "sched:sched_switch",
1057 };
1058
1059 static int __cmd_record(int argc, const char **argv)
1060 {
1061         unsigned int rec_argc, i, j;
1062         const char **rec_argv;
1063         const char * const *record_args = record_new_args;
1064         unsigned int record_elems = ARRAY_SIZE(record_new_args);
1065
1066 #ifdef SUPPORT_OLD_POWER_EVENTS
1067         if (!is_valid_tracepoint("power:cpu_idle") &&
1068             is_valid_tracepoint("power:power_start")) {
1069                 use_old_power_events = 1;
1070                 record_args = record_old_args;
1071                 record_elems = ARRAY_SIZE(record_old_args);
1072         }
1073 #endif
1074
1075         rec_argc = record_elems + argc - 1;
1076         rec_argv = calloc(rec_argc + 1, sizeof(char *));
1077
1078         if (rec_argv == NULL)
1079                 return -ENOMEM;
1080
1081         for (i = 0; i < record_elems; i++)
1082                 rec_argv[i] = strdup(record_args[i]);
1083
1084         for (j = 1; j < (unsigned int)argc; j++, i++)
1085                 rec_argv[i] = argv[j];
1086
1087         return cmd_record(i, rec_argv, NULL);
1088 }
1089
1090 static int
1091 parse_process(const struct option *opt __used, const char *arg, int __used unset)
1092 {
1093         if (arg)
1094                 add_process_filter(arg);
1095         return 0;
1096 }
1097
1098 static const struct option options[] = {
1099         OPT_STRING('i', "input", &input_name, "file",
1100                     "input file name"),
1101         OPT_STRING('o', "output", &output_name, "file",
1102                     "output file name"),
1103         OPT_INTEGER('w', "width", &svg_page_width,
1104                     "page width"),
1105         OPT_BOOLEAN('P', "power-only", &power_only,
1106                     "output power data only"),
1107         OPT_CALLBACK('p', "process", NULL, "process",
1108                       "process selector. Pass a pid or process name.",
1109                        parse_process),
1110         OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1111                     "Look for files with symbols relative to this directory"),
1112         OPT_END()
1113 };
1114
1115
1116 int cmd_timechart(int argc, const char **argv, const char *prefix __used)
1117 {
1118         argc = parse_options(argc, argv, options, timechart_usage,
1119                         PARSE_OPT_STOP_AT_NON_OPTION);
1120
1121         symbol__init();
1122
1123         if (argc && !strncmp(argv[0], "rec", 3))
1124                 return __cmd_record(argc, argv);
1125         else if (argc)
1126                 usage_with_options(timechart_usage, options);
1127
1128         setup_pager();
1129
1130         return __cmd_timechart();
1131 }