aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/svghelper.c
diff options
context:
space:
mode:
authorStanislav Fomichev <stfomichev@yandex-team.ru>2013-12-02 09:37:36 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-12-16 14:34:53 -0500
commitc507999790438cde78b5618fa64daefd697035af (patch)
tree0ee428460b358e6cc362450622d9b8941db1feca /tools/perf/util/svghelper.c
parent58b9a18ecd251cbd6e666ad792023ab77c7d100e (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.c132
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
23static u64 first_time, last_time; 26static u64 first_time, last_time;
24static u64 turbo_frequency, max_freq; 27static 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
45static int *topology_map;
46
42static double cpu2y(int cpu) 47static 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
47static double time2pixels(u64 __time) 55static 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)
581typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
582
583struct topology {
584 cpumask_t *sib_core;
585 int sib_core_nr;
586 cpumask_t *sib_thr;
587 int sib_thr_nr;
588};
589
590static 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
607static 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
620static 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
646int 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
693exit:
694 free(t.sib_core);
695 free(t.sib_thr);
696
697 return -1;
698}