diff options
author | Stanislav Fomichev <stfomichev@yandex-team.ru> | 2013-12-02 09:37:36 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-12-16 14:34:53 -0500 |
commit | c507999790438cde78b5618fa64daefd697035af (patch) | |
tree | 0ee428460b358e6cc362450622d9b8941db1feca /tools/perf/util/svghelper.c | |
parent | 58b9a18ecd251cbd6e666ad792023ab77c7d100e (diff) |
perf timechart: Add support for topology
Add -t switch to sort CPUs topologically.
Signed-off-by: Stanislav Fomichev <stfomichev@yandex-team.ru>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Ramkumar Ramachandra <artagnon@gmail.com>
Link: http://lkml.kernel.org/r/1385995056-20158-5-git-send-email-stfomichev@yandex-team.ru
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/svghelper.c')
-rw-r--r-- | tools/perf/util/svghelper.c | 132 |
1 files changed, 130 insertions, 2 deletions
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 927851d05d03..9468136735ca 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c | |||
@@ -17,8 +17,11 @@ | |||
17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
18 | #include <unistd.h> | 18 | #include <unistd.h> |
19 | #include <string.h> | 19 | #include <string.h> |
20 | #include <linux/bitops.h> | ||
20 | 21 | ||
22 | #include "perf.h" | ||
21 | #include "svghelper.h" | 23 | #include "svghelper.h" |
24 | #include "cpumap.h" | ||
22 | 25 | ||
23 | static u64 first_time, last_time; | 26 | static u64 first_time, last_time; |
24 | static u64 turbo_frequency, max_freq; | 27 | static u64 turbo_frequency, max_freq; |
@@ -39,9 +42,14 @@ static double cpu2slot(int cpu) | |||
39 | return 2 * cpu + 1; | 42 | return 2 * cpu + 1; |
40 | } | 43 | } |
41 | 44 | ||
45 | static int *topology_map; | ||
46 | |||
42 | static double cpu2y(int cpu) | 47 | static double cpu2y(int cpu) |
43 | { | 48 | { |
44 | return cpu2slot(cpu) * SLOT_MULT; | 49 | if (topology_map) |
50 | return cpu2slot(topology_map[cpu]) * SLOT_MULT; | ||
51 | else | ||
52 | return cpu2slot(cpu) * SLOT_MULT; | ||
45 | } | 53 | } |
46 | 54 | ||
47 | static double time2pixels(u64 __time) | 55 | static double time2pixels(u64 __time) |
@@ -275,7 +283,7 @@ void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) | |||
275 | time2pixels(last_time)-time2pixels(first_time), | 283 | time2pixels(last_time)-time2pixels(first_time), |
276 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); | 284 | cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); |
277 | 285 | ||
278 | sprintf(cpu_string, "CPU %i", (int)cpu+1); | 286 | sprintf(cpu_string, "CPU %i", (int)cpu); |
279 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", | 287 | fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", |
280 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); | 288 | 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); |
281 | 289 | ||
@@ -568,3 +576,123 @@ void svg_close(void) | |||
568 | svgfile = NULL; | 576 | svgfile = NULL; |
569 | } | 577 | } |
570 | } | 578 | } |
579 | |||
580 | #define cpumask_bits(maskp) ((maskp)->bits) | ||
581 | typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t; | ||
582 | |||
583 | struct topology { | ||
584 | cpumask_t *sib_core; | ||
585 | int sib_core_nr; | ||
586 | cpumask_t *sib_thr; | ||
587 | int sib_thr_nr; | ||
588 | }; | ||
589 | |||
590 | static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos) | ||
591 | { | ||
592 | int i; | ||
593 | int thr; | ||
594 | |||
595 | for (i = 0; i < t->sib_thr_nr; i++) { | ||
596 | if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i]))) | ||
597 | continue; | ||
598 | |||
599 | for_each_set_bit(thr, | ||
600 | cpumask_bits(&t->sib_thr[i]), | ||
601 | MAX_NR_CPUS) | ||
602 | if (map[thr] == -1) | ||
603 | map[thr] = (*pos)++; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | static void scan_core_topology(int *map, struct topology *t) | ||
608 | { | ||
609 | int pos = 0; | ||
610 | int i; | ||
611 | int cpu; | ||
612 | |||
613 | for (i = 0; i < t->sib_core_nr; i++) | ||
614 | for_each_set_bit(cpu, | ||
615 | cpumask_bits(&t->sib_core[i]), | ||
616 | MAX_NR_CPUS) | ||
617 | scan_thread_topology(map, t, cpu, &pos); | ||
618 | } | ||
619 | |||
620 | static int str_to_bitmap(char *s, cpumask_t *b) | ||
621 | { | ||
622 | int i; | ||
623 | int ret = 0; | ||
624 | struct cpu_map *m; | ||
625 | int c; | ||
626 | |||
627 | m = cpu_map__new(s); | ||
628 | if (!m) | ||
629 | return -1; | ||
630 | |||
631 | for (i = 0; i < m->nr; i++) { | ||
632 | c = m->map[i]; | ||
633 | if (c >= MAX_NR_CPUS) { | ||
634 | ret = -1; | ||
635 | break; | ||
636 | } | ||
637 | |||
638 | set_bit(c, cpumask_bits(b)); | ||
639 | } | ||
640 | |||
641 | cpu_map__delete(m); | ||
642 | |||
643 | return ret; | ||
644 | } | ||
645 | |||
646 | int svg_build_topology_map(char *sib_core, int sib_core_nr, | ||
647 | char *sib_thr, int sib_thr_nr) | ||
648 | { | ||
649 | int i; | ||
650 | struct topology t; | ||
651 | |||
652 | t.sib_core_nr = sib_core_nr; | ||
653 | t.sib_thr_nr = sib_thr_nr; | ||
654 | t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t)); | ||
655 | t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t)); | ||
656 | |||
657 | if (!t.sib_core || !t.sib_thr) { | ||
658 | fprintf(stderr, "topology: no memory\n"); | ||
659 | goto exit; | ||
660 | } | ||
661 | |||
662 | for (i = 0; i < sib_core_nr; i++) { | ||
663 | if (str_to_bitmap(sib_core, &t.sib_core[i])) { | ||
664 | fprintf(stderr, "topology: can't parse siblings map\n"); | ||
665 | goto exit; | ||
666 | } | ||
667 | |||
668 | sib_core += strlen(sib_core) + 1; | ||
669 | } | ||
670 | |||
671 | for (i = 0; i < sib_thr_nr; i++) { | ||
672 | if (str_to_bitmap(sib_thr, &t.sib_thr[i])) { | ||
673 | fprintf(stderr, "topology: can't parse siblings map\n"); | ||
674 | goto exit; | ||
675 | } | ||
676 | |||
677 | sib_thr += strlen(sib_thr) + 1; | ||
678 | } | ||
679 | |||
680 | topology_map = malloc(sizeof(int) * MAX_NR_CPUS); | ||
681 | if (!topology_map) { | ||
682 | fprintf(stderr, "topology: no memory\n"); | ||
683 | goto exit; | ||
684 | } | ||
685 | |||
686 | for (i = 0; i < MAX_NR_CPUS; i++) | ||
687 | topology_map[i] = -1; | ||
688 | |||
689 | scan_core_topology(topology_map, &t); | ||
690 | |||
691 | return 0; | ||
692 | |||
693 | exit: | ||
694 | free(t.sib_core); | ||
695 | free(t.sib_thr); | ||
696 | |||
697 | return -1; | ||
698 | } | ||