blob: 56a84f2cc46d520f2ae68954c8b1d69bef697cc7 [file] [log] [blame]
Arjan van de Venf48d55c2009-09-12 12:52:11 +02001/*
2 * svghelper.c - helper functions for outputting svg
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
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -020015#include <inttypes.h>
Arjan van de Venf48d55c2009-09-12 12:52:11 +020016#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include <string.h>
Stanislav Fomichevc5079992013-12-02 18:37:36 +040020#include <linux/bitops.h>
Arjan van de Venf48d55c2009-09-12 12:52:11 +020021
Stanislav Fomichevc5079992013-12-02 18:37:36 +040022#include "perf.h"
Arjan van de Venf48d55c2009-09-12 12:52:11 +020023#include "svghelper.h"
Stanislav Fomichevc5079992013-12-02 18:37:36 +040024#include "cpumap.h"
Arjan van de Venf48d55c2009-09-12 12:52:11 +020025
26static u64 first_time, last_time;
27static u64 turbo_frequency, max_freq;
28
29
30#define SLOT_MULT 30.0
31#define SLOT_HEIGHT 25.0
Arjan van de Ven5094b652009-09-20 18:14:16 +020032
33int svg_page_width = 1000;
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +040034u64 svg_highlight;
35const char *svg_highlight_name;
Arjan van de Venf48d55c2009-09-12 12:52:11 +020036
Arjan van de Ven39a90a82009-09-24 15:40:13 +020037#define MIN_TEXT_SIZE 0.01
Arjan van de Ven964a0b32009-09-19 13:35:07 +020038
Arjan van de Venf48d55c2009-09-12 12:52:11 +020039static u64 total_height;
40static FILE *svgfile;
41
42static double cpu2slot(int cpu)
43{
44 return 2 * cpu + 1;
45}
46
Stanislav Fomichevc5079992013-12-02 18:37:36 +040047static int *topology_map;
48
Arjan van de Venf48d55c2009-09-12 12:52:11 +020049static double cpu2y(int cpu)
50{
Stanislav Fomichevc5079992013-12-02 18:37:36 +040051 if (topology_map)
52 return cpu2slot(topology_map[cpu]) * SLOT_MULT;
53 else
54 return cpu2slot(cpu) * SLOT_MULT;
Arjan van de Venf48d55c2009-09-12 12:52:11 +020055}
56
Thomas Renninger00e99a42011-01-21 15:30:09 +010057static double time2pixels(u64 __time)
Arjan van de Venf48d55c2009-09-12 12:52:11 +020058{
59 double X;
60
Thomas Renninger00e99a42011-01-21 15:30:09 +010061 X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time);
Arjan van de Venf48d55c2009-09-12 12:52:11 +020062 return X;
63}
64
Arjan van de Ven611a5462009-09-20 18:14:38 +020065/*
66 * Round text sizes so that the svg viewer only needs a discrete
67 * number of renderings of the font
68 */
69static double round_text_size(double size)
70{
71 int loop = 100;
72 double target = 10.0;
73
74 if (size >= 10.0)
75 return size;
76 while (loop--) {
77 if (size >= target)
78 return target;
79 target = target / 2.0;
80 }
81 return size;
82}
83
Arjan van de Ven5094b652009-09-20 18:14:16 +020084void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
Arjan van de Venf48d55c2009-09-12 12:52:11 +020085{
Arjan van de Ven5094b652009-09-20 18:14:16 +020086 int new_width;
Arjan van de Venf48d55c2009-09-12 12:52:11 +020087
88 svgfile = fopen(filename, "w");
89 if (!svgfile) {
90 fprintf(stderr, "Cannot open %s for output\n", filename);
91 return;
92 }
Arjan van de Ven5094b652009-09-20 18:14:16 +020093 first_time = start;
94 first_time = first_time / 100000000 * 100000000;
95 last_time = end;
96
97 /*
98 * if the recording is short, we default to a width of 1000, but
99 * for longer recordings we want at least 200 units of width per second
100 */
101 new_width = (last_time - first_time) / 5000000;
102
103 if (new_width > svg_page_width)
104 svg_page_width = new_width;
105
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200106 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
107 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400108 fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200109 fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200110
111 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
112
113 fprintf(svgfile, " rect { stroke-width: 1; }\n");
114 fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n");
115 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
116 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400117 fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200118 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
Arjan van de Ven2e600d02009-10-20 06:47:31 +0900119 fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200120 fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200121 fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
122 fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
123 fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n");
124 fprintf(svgfile, " rect.c2 { fill:rgb(255,172,172); fill-opacity:0.5; stroke-width:0; } \n");
125 fprintf(svgfile, " rect.c3 { fill:rgb(255,130,130); fill-opacity:0.5; stroke-width:0; } \n");
126 fprintf(svgfile, " rect.c4 { fill:rgb(255, 88, 88); fill-opacity:0.5; stroke-width:0; } \n");
127 fprintf(svgfile, " rect.c5 { fill:rgb(255, 44, 44); fill-opacity:0.5; stroke-width:0; } \n");
128 fprintf(svgfile, " rect.c6 { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; } \n");
129 fprintf(svgfile, " line.pstate { stroke:rgb(255,255, 0); stroke-opacity:0.8; stroke-width:2; } \n");
130
131 fprintf(svgfile, " ]]>\n </style>\n</defs>\n");
132}
133
134void svg_box(int Yslot, u64 start, u64 end, const char *type)
135{
136 if (!svgfile)
137 return;
138
139 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
140 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
141}
142
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400143static char *time_to_string(u64 duration);
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400144void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400145{
146 if (!svgfile)
147 return;
148
149 fprintf(svgfile, "<g>\n");
150 fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu,
151 time_to_string(end - start));
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400152 if (backtrace)
153 fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace);
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400154 svg_box(Yslot, start, end, "blocked");
155 fprintf(svgfile, "</g>\n");
156}
157
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400158void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200159{
160 double text_size;
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400161 const char *type;
162
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200163 if (!svgfile)
164 return;
165
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400166 if (svg_highlight && end - start > svg_highlight)
167 type = "sample_hi";
168 else
169 type = "sample";
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400170 fprintf(svgfile, "<g>\n");
171
172 fprintf(svgfile, "<title>#%d running %s</title>\n",
173 cpu, time_to_string(end - start));
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400174 if (backtrace)
175 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400176 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n",
177 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT,
178 type);
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200179
180 text_size = (time2pixels(end)-time2pixels(start));
181 if (cpu > 9)
182 text_size = text_size/2;
183 if (text_size > 1.25)
184 text_size = 1.25;
Arjan van de Ven611a5462009-09-20 18:14:38 +0200185 text_size = round_text_size(text_size);
186
Arjan van de Ven964a0b32009-09-19 13:35:07 +0200187 if (text_size > MIN_TEXT_SIZE)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200188 fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200189 time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1);
190
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400191 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200192}
193
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200194static char *time_to_string(u64 duration)
195{
196 static char text[80];
197
198 text[0] = 0;
199
200 if (duration < 1000) /* less than 1 usec */
201 return text;
202
203 if (duration < 1000 * 1000) { /* less than 1 msec */
204 sprintf(text, "%4.1f us", duration / 1000.0);
205 return text;
206 }
207 sprintf(text, "%4.1f ms", duration / 1000.0 / 1000);
208
209 return text;
210}
211
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400212void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200213{
214 char *text;
215 const char *style;
216 double font_size;
217
218 if (!svgfile)
219 return;
220
221 style = "waiting";
222
223 if (end-start > 10 * 1000000) /* 10 msec */
224 style = "WAITING";
225
226 text = time_to_string(end-start);
227
Arjan van de Ven611a5462009-09-20 18:14:38 +0200228 font_size = 1.0 * (time2pixels(end)-time2pixels(start));
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200229
Arjan van de Ven611a5462009-09-20 18:14:38 +0200230 if (font_size > 3)
231 font_size = 3;
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200232
Arjan van de Ven611a5462009-09-20 18:14:38 +0200233 font_size = round_text_size(font_size);
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200234
Arjan van de Ven611a5462009-09-20 18:14:38 +0200235 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400236 fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start));
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400237 if (backtrace)
238 fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace);
Arjan van de Ven611a5462009-09-20 18:14:38 +0200239 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
240 time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200241 if (font_size > MIN_TEXT_SIZE)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200242 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n",
243 font_size, text);
244 fprintf(svgfile, "</g>\n");
Arjan van de Vena92fe7b2009-09-20 18:13:53 +0200245}
246
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200247static char *cpu_model(void)
248{
249 static char cpu_m[255];
250 char buf[256];
251 FILE *file;
252
253 cpu_m[0] = 0;
254 /* CPU type */
255 file = fopen("/proc/cpuinfo", "r");
256 if (file) {
257 while (fgets(buf, 255, file)) {
258 if (strstr(buf, "model name")) {
259 strncpy(cpu_m, &buf[13], 255);
260 break;
261 }
262 }
263 fclose(file);
264 }
Arjan van de Ven39a90a82009-09-24 15:40:13 +0200265
266 /* CPU type */
267 file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
268 if (file) {
269 while (fgets(buf, 255, file)) {
270 unsigned int freq;
271 freq = strtoull(buf, NULL, 10);
272 if (freq > max_freq)
273 max_freq = freq;
274 }
275 fclose(file);
276 }
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200277 return cpu_m;
278}
279
280void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
281{
282 char cpu_string[80];
283 if (!svgfile)
284 return;
285
286 max_freq = __max_freq;
287 turbo_frequency = __turbo_freq;
288
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400289 fprintf(svgfile, "<g>\n");
290
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200291 fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"cpu\"/>\n",
292 time2pixels(first_time),
293 time2pixels(last_time)-time2pixels(first_time),
294 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
295
Stanislav Fomichevc5079992013-12-02 18:37:36 +0400296 sprintf(cpu_string, "CPU %i", (int)cpu);
Arjan van de Ven611a5462009-09-20 18:14:38 +0200297 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200298 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
299
Arjan van de Ven964a0b32009-09-19 13:35:07 +0200300 fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200301 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400302
303 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200304}
305
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400306void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace)
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200307{
308 double width;
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400309 const char *type;
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200310
311 if (!svgfile)
312 return;
313
Stanislav Fomicheve57a2df2013-12-17 19:53:49 +0400314 if (svg_highlight && end - start >= svg_highlight)
315 type = "sample_hi";
316 else if (svg_highlight_name && strstr(name, svg_highlight_name))
317 type = "sample_hi";
318 else
319 type = "sample";
Arjan van de Ven611a5462009-09-20 18:14:38 +0200320
321 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
Stanislav Fomichevde996222013-12-02 18:37:34 +0400322 fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start));
Stanislav Fomichev8b6dcca2013-12-02 18:37:33 +0400323 if (backtrace)
324 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
Arjan van de Ven611a5462009-09-20 18:14:38 +0200325 fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
326 time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200327 width = time2pixels(end)-time2pixels(start);
328 if (width > 6)
329 width = 6;
330
Arjan van de Ven611a5462009-09-20 18:14:38 +0200331 width = round_text_size(width);
332
Arjan van de Ven964a0b32009-09-19 13:35:07 +0200333 if (width > MIN_TEXT_SIZE)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200334 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n",
335 width, name);
336
337 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200338}
339
340void svg_cstate(int cpu, u64 start, u64 end, int type)
341{
342 double width;
343 char style[128];
344
345 if (!svgfile)
346 return;
347
348
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400349 fprintf(svgfile, "<g>\n");
350
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200351 if (type > 6)
352 type = 6;
353 sprintf(style, "c%i", type);
354
355 fprintf(svgfile, "<rect class=\"%s\" x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\"/>\n",
356 style,
357 time2pixels(start), time2pixels(end)-time2pixels(start),
358 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
359
Arjan van de Ven611a5462009-09-20 18:14:38 +0200360 width = (time2pixels(end)-time2pixels(start))/2.0;
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200361 if (width > 6)
362 width = 6;
363
Arjan van de Ven611a5462009-09-20 18:14:38 +0200364 width = round_text_size(width);
365
Arjan van de Ven964a0b32009-09-19 13:35:07 +0200366 if (width > MIN_TEXT_SIZE)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200367 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n",
368 time2pixels(start), cpu2y(cpu)+width, width, type);
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400369
370 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200371}
372
373static char *HzToHuman(unsigned long hz)
374{
375 static char buffer[1024];
376 unsigned long long Hz;
377
378 memset(buffer, 0, 1024);
379
380 Hz = hz;
381
382 /* default: just put the Number in */
383 sprintf(buffer, "%9lli", Hz);
384
385 if (Hz > 1000)
386 sprintf(buffer, " %6lli Mhz", (Hz+500)/1000);
387
388 if (Hz > 1500000)
389 sprintf(buffer, " %6.2f Ghz", (Hz+5000.0)/1000000);
390
391 if (Hz == turbo_frequency)
392 sprintf(buffer, "Turbo");
393
394 return buffer;
395}
396
397void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
398{
399 double height = 0;
400
401 if (!svgfile)
402 return;
403
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400404 fprintf(svgfile, "<g>\n");
405
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200406 if (max_freq)
407 height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
408 height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
409 fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n",
410 time2pixels(start), time2pixels(end), height, height);
Arjan van de Ven611a5462009-09-20 18:14:38 +0200411 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200412 time2pixels(start), height+0.9, HzToHuman(freq));
413
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400414 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200415}
416
417
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400418void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace)
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200419{
420 double height;
421
422 if (!svgfile)
423 return;
424
425
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400426 fprintf(svgfile, "<g>\n");
427
428 fprintf(svgfile, "<title>%s wakes up %s</title>\n",
429 desc1 ? desc1 : "?",
430 desc2 ? desc2 : "?");
431
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400432 if (backtrace)
433 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
434
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200435 if (row1 < row2) {
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200436 if (row1) {
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200437 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
438 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200439 if (desc2)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200440 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200441 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
442 }
443 if (row2) {
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200444 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
445 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200446 if (desc1)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200447 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200448 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
449 }
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200450 } else {
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200451 if (row2) {
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200452 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
453 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200454 if (desc1)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200455 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200456 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
457 }
458 if (row1) {
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200459 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
460 time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200461 if (desc2)
Arjan van de Ven611a5462009-09-20 18:14:38 +0200462 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
Arjan van de Ven4f1202c2009-09-20 18:13:28 +0200463 time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
464 }
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200465 }
466 height = row1 * SLOT_MULT;
467 if (row2 > row1)
468 height += SLOT_HEIGHT;
469 if (row1)
470 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
471 time2pixels(start), height);
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400472
473 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200474}
475
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400476void svg_wakeline(u64 start, int row1, int row2, const char *backtrace)
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200477{
478 double height;
479
480 if (!svgfile)
481 return;
482
483
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400484 fprintf(svgfile, "<g>\n");
485
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400486 if (backtrace)
487 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
488
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200489 if (row1 < row2)
490 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
491 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT);
492 else
493 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
494 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT);
495
496 height = row1 * SLOT_MULT;
497 if (row2 > row1)
498 height += SLOT_HEIGHT;
499 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
500 time2pixels(start), height);
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400501
502 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200503}
504
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400505void svg_interrupt(u64 start, int row, const char *backtrace)
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200506{
507 if (!svgfile)
508 return;
509
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400510 fprintf(svgfile, "<g>\n");
511
512 fprintf(svgfile, "<title>Wakeup from interrupt</title>\n");
513
Stanislav Fomichev6f8d67f2013-11-01 20:25:51 +0400514 if (backtrace)
515 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
516
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200517 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
518 time2pixels(start), row * SLOT_MULT);
519 fprintf(svgfile, "<circle cx=\"%4.8f\" cy=\"%4.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
520 time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400521
522 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200523}
524
525void svg_text(int Yslot, u64 start, const char *text)
526{
527 if (!svgfile)
528 return;
529
Arjan van de Ven611a5462009-09-20 18:14:38 +0200530 fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200531 time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
532}
533
534static void svg_legenda_box(int X, const char *text, const char *style)
535{
536 double boxsize;
537 boxsize = SLOT_HEIGHT / 2;
538
539 fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
540 X, boxsize, boxsize, style);
Arjan van de Ven611a5462009-09-20 18:14:38 +0200541 fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200542 X + boxsize + 5, boxsize, 0.8 * boxsize, text);
543}
544
545void svg_legenda(void)
546{
547 if (!svgfile)
548 return;
549
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400550 fprintf(svgfile, "<g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200551 svg_legenda_box(0, "Running", "sample");
Thomas Renningere8530722011-02-27 22:36:45 +0100552 svg_legenda_box(100, "Idle","c1");
553 svg_legenda_box(200, "Deeper Idle", "c3");
554 svg_legenda_box(350, "Deepest Idle", "c6");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200555 svg_legenda_box(550, "Sleeping", "process2");
556 svg_legenda_box(650, "Waiting for cpu", "waiting");
557 svg_legenda_box(800, "Blocked on IO", "blocked");
Stanislav Fomichevcbb2e812013-11-01 20:25:49 +0400558 fprintf(svgfile, "</g>\n");
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200559}
560
Arjan van de Ven5094b652009-09-20 18:14:16 +0200561void svg_time_grid(void)
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200562{
563 u64 i;
564
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200565 if (!svgfile)
566 return;
567
568 i = first_time;
569 while (i < last_time) {
570 int color = 220;
571 double thickness = 0.075;
572 if ((i % 100000000) == 0) {
573 thickness = 0.5;
574 color = 192;
575 }
576 if ((i % 1000000000) == 0) {
577 thickness = 2.0;
578 color = 128;
579 }
580
Arnaldo Carvalho de Melo9486aa32011-01-22 20:37:02 -0200581 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%" PRIu64 "\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%1.3f\"/>\n",
Arjan van de Venf48d55c2009-09-12 12:52:11 +0200582 time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness);
583
584 i += 10000000;
585 }
586}
587
588void svg_close(void)
589{
590 if (svgfile) {
591 fprintf(svgfile, "</svg>\n");
592 fclose(svgfile);
593 svgfile = NULL;
594 }
595}
Stanislav Fomichevc5079992013-12-02 18:37:36 +0400596
597#define cpumask_bits(maskp) ((maskp)->bits)
598typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
599
600struct topology {
601 cpumask_t *sib_core;
602 int sib_core_nr;
603 cpumask_t *sib_thr;
604 int sib_thr_nr;
605};
606
607static void scan_thread_topology(int *map, struct topology *t, int cpu, int *pos)
608{
609 int i;
610 int thr;
611
612 for (i = 0; i < t->sib_thr_nr; i++) {
613 if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i])))
614 continue;
615
616 for_each_set_bit(thr,
617 cpumask_bits(&t->sib_thr[i]),
618 MAX_NR_CPUS)
619 if (map[thr] == -1)
620 map[thr] = (*pos)++;
621 }
622}
623
624static void scan_core_topology(int *map, struct topology *t)
625{
626 int pos = 0;
627 int i;
628 int cpu;
629
630 for (i = 0; i < t->sib_core_nr; i++)
631 for_each_set_bit(cpu,
632 cpumask_bits(&t->sib_core[i]),
633 MAX_NR_CPUS)
634 scan_thread_topology(map, t, cpu, &pos);
635}
636
637static int str_to_bitmap(char *s, cpumask_t *b)
638{
639 int i;
640 int ret = 0;
641 struct cpu_map *m;
642 int c;
643
644 m = cpu_map__new(s);
645 if (!m)
646 return -1;
647
648 for (i = 0; i < m->nr; i++) {
649 c = m->map[i];
650 if (c >= MAX_NR_CPUS) {
651 ret = -1;
652 break;
653 }
654
655 set_bit(c, cpumask_bits(b));
656 }
657
658 cpu_map__delete(m);
659
660 return ret;
661}
662
663int svg_build_topology_map(char *sib_core, int sib_core_nr,
664 char *sib_thr, int sib_thr_nr)
665{
666 int i;
667 struct topology t;
668
669 t.sib_core_nr = sib_core_nr;
670 t.sib_thr_nr = sib_thr_nr;
671 t.sib_core = calloc(sib_core_nr, sizeof(cpumask_t));
672 t.sib_thr = calloc(sib_thr_nr, sizeof(cpumask_t));
673
674 if (!t.sib_core || !t.sib_thr) {
675 fprintf(stderr, "topology: no memory\n");
676 goto exit;
677 }
678
679 for (i = 0; i < sib_core_nr; i++) {
680 if (str_to_bitmap(sib_core, &t.sib_core[i])) {
681 fprintf(stderr, "topology: can't parse siblings map\n");
682 goto exit;
683 }
684
685 sib_core += strlen(sib_core) + 1;
686 }
687
688 for (i = 0; i < sib_thr_nr; i++) {
689 if (str_to_bitmap(sib_thr, &t.sib_thr[i])) {
690 fprintf(stderr, "topology: can't parse siblings map\n");
691 goto exit;
692 }
693
694 sib_thr += strlen(sib_thr) + 1;
695 }
696
697 topology_map = malloc(sizeof(int) * MAX_NR_CPUS);
698 if (!topology_map) {
699 fprintf(stderr, "topology: no memory\n");
700 goto exit;
701 }
702
703 for (i = 0; i < MAX_NR_CPUS; i++)
704 topology_map[i] = -1;
705
706 scan_core_topology(topology_map, &t);
707
708 return 0;
709
710exit:
711 free(t.sib_core);
712 free(t.sib_thr);
713
714 return -1;
715}