]> Git Repo - linux.git/blob - tools/perf/util/svghelper.c
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / tools / perf / util / svghelper.c
1 /*
2  * svghelper.c - helper functions for outputting svg
3  *
4  * (C) Copyright 2009 Intel Corporation
5  *
6  * Authors:
7  *     Arjan van de Ven <[email protected]>
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 <inttypes.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <linux/bitops.h>
21
22 #include "perf.h"
23 #include "svghelper.h"
24 #include "cpumap.h"
25
26 static u64 first_time, last_time;
27 static u64 turbo_frequency, max_freq;
28
29
30 #define SLOT_MULT 30.0
31 #define SLOT_HEIGHT 25.0
32
33 int svg_page_width = 1000;
34 u64 svg_highlight;
35 const char *svg_highlight_name;
36
37 #define MIN_TEXT_SIZE 0.01
38
39 static u64 total_height;
40 static FILE *svgfile;
41
42 static double cpu2slot(int cpu)
43 {
44         return 2 * cpu + 1;
45 }
46
47 static int *topology_map;
48
49 static double cpu2y(int cpu)
50 {
51         if (topology_map)
52                 return cpu2slot(topology_map[cpu]) * SLOT_MULT;
53         else
54                 return cpu2slot(cpu) * SLOT_MULT;
55 }
56
57 static double time2pixels(u64 __time)
58 {
59         double X;
60
61         X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time);
62         return X;
63 }
64
65 /*
66  * Round text sizes so that the svg viewer only needs a discrete
67  * number of renderings of the font
68  */
69 static 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
84 void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
85 {
86         int new_width;
87
88         svgfile = fopen(filename, "w");
89         if (!svgfile) {
90                 fprintf(stderr, "Cannot open %s for output\n", filename);
91                 return;
92         }
93         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
106         total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
107         fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
108         fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
109         fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
110
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");
117         fprintf(svgfile, "      rect.sample_hi{ fill:rgb(255,128,  0); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
118         fprintf(svgfile, "      rect.blocked  { fill:rgb(255,  0,  0); fill-opacity:0.5; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
119         fprintf(svgfile, "      rect.waiting  { fill:rgb(224,214,  0); fill-opacity:0.8; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
120         fprintf(svgfile, "      rect.WAITING  { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0;   stroke:rgb(  0,  0,  0); } \n");
121         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
134 void 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
143 static char *time_to_string(u64 duration);
144 void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
145 {
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));
152         if (backtrace)
153                 fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace);
154         svg_box(Yslot, start, end, "blocked");
155         fprintf(svgfile, "</g>\n");
156 }
157
158 void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
159 {
160         double text_size;
161         const char *type;
162
163         if (!svgfile)
164                 return;
165
166         if (svg_highlight && end - start > svg_highlight)
167                 type = "sample_hi";
168         else
169                 type = "sample";
170         fprintf(svgfile, "<g>\n");
171
172         fprintf(svgfile, "<title>#%d running %s</title>\n",
173                 cpu, time_to_string(end - start));
174         if (backtrace)
175                 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
176         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);
179
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;
185         text_size = round_text_size(text_size);
186
187         if (text_size > MIN_TEXT_SIZE)
188                 fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n",
189                         time2pixels(start), Yslot *  SLOT_MULT + SLOT_HEIGHT - 1, text_size,  cpu + 1);
190
191         fprintf(svgfile, "</g>\n");
192 }
193
194 static 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
212 void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
213 {
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
228         font_size = 1.0 * (time2pixels(end)-time2pixels(start));
229
230         if (font_size > 3)
231                 font_size = 3;
232
233         font_size = round_text_size(font_size);
234
235         fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
236         fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start));
237         if (backtrace)
238                 fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace);
239         fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n",
240                 time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
241         if (font_size > MIN_TEXT_SIZE)
242                 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n",
243                         font_size, text);
244         fprintf(svgfile, "</g>\n");
245 }
246
247 static 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         }
265
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         }
277         return cpu_m;
278 }
279
280 void 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
289         fprintf(svgfile, "<g>\n");
290
291         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
296         sprintf(cpu_string, "CPU %i", (int)cpu);
297         fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
298                 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
299
300         fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n",
301                 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
302
303         fprintf(svgfile, "</g>\n");
304 }
305
306 void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace)
307 {
308         double width;
309         const char *type;
310
311         if (!svgfile)
312                 return;
313
314         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";
320
321         fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu));
322         fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start));
323         if (backtrace)
324                 fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
325         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);
327         width = time2pixels(end)-time2pixels(start);
328         if (width > 6)
329                 width = 6;
330
331         width = round_text_size(width);
332
333         if (width > MIN_TEXT_SIZE)
334                 fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n",
335                         width, name);
336
337         fprintf(svgfile, "</g>\n");
338 }
339
340 void 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
349         fprintf(svgfile, "<g>\n");
350
351         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
360         width = (time2pixels(end)-time2pixels(start))/2.0;
361         if (width > 6)
362                 width = 6;
363
364         width = round_text_size(width);
365
366         if (width > MIN_TEXT_SIZE)
367                 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);
369
370         fprintf(svgfile, "</g>\n");
371 }
372
373 static 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
397 void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
398 {
399         double height = 0;
400
401         if (!svgfile)
402                 return;
403
404         fprintf(svgfile, "<g>\n");
405
406         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);
411         fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n",
412                 time2pixels(start), height+0.9, HzToHuman(freq));
413
414         fprintf(svgfile, "</g>\n");
415 }
416
417
418 void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace)
419 {
420         double height;
421
422         if (!svgfile)
423                 return;
424
425
426         fprintf(svgfile, "<g>\n");
427
428         fprintf(svgfile, "<title>%s wakes up %s</title>\n",
429                 desc1 ? desc1 : "?",
430                 desc2 ? desc2 : "?");
431
432         if (backtrace)
433                 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
434
435         if (row1 < row2) {
436                 if (row1) {
437                         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);
439                         if (desc2)
440                                 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
441                                         time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
442                 }
443                 if (row2) {
444                         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);
446                         if (desc1)
447                                 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n",
448                                         time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
449                 }
450         } else {
451                 if (row2) {
452                         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);
454                         if (desc1)
455                                 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
456                                         time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
457                 }
458                 if (row1) {
459                         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);
461                         if (desc2)
462                                 fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n",
463                                         time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
464                 }
465         }
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);
472
473         fprintf(svgfile, "</g>\n");
474 }
475
476 void svg_wakeline(u64 start, int row1, int row2, const char *backtrace)
477 {
478         double height;
479
480         if (!svgfile)
481                 return;
482
483
484         fprintf(svgfile, "<g>\n");
485
486         if (backtrace)
487                 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
488
489         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);
501
502         fprintf(svgfile, "</g>\n");
503 }
504
505 void svg_interrupt(u64 start, int row, const char *backtrace)
506 {
507         if (!svgfile)
508                 return;
509
510         fprintf(svgfile, "<g>\n");
511
512         fprintf(svgfile, "<title>Wakeup from interrupt</title>\n");
513
514         if (backtrace)
515                 fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
516
517         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);
521
522         fprintf(svgfile, "</g>\n");
523 }
524
525 void svg_text(int Yslot, u64 start, const char *text)
526 {
527         if (!svgfile)
528                 return;
529
530         fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n",
531                 time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
532 }
533
534 static 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);
541         fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n",
542                 X + boxsize + 5, boxsize, 0.8 * boxsize, text);
543 }
544
545 void svg_legenda(void)
546 {
547         if (!svgfile)
548                 return;
549
550         fprintf(svgfile, "<g>\n");
551         svg_legenda_box(0,      "Running", "sample");
552         svg_legenda_box(100,    "Idle","c1");
553         svg_legenda_box(200,    "Deeper Idle", "c3");
554         svg_legenda_box(350,    "Deepest Idle", "c6");
555         svg_legenda_box(550,    "Sleeping", "process2");
556         svg_legenda_box(650,    "Waiting for cpu", "waiting");
557         svg_legenda_box(800,    "Blocked on IO", "blocked");
558         fprintf(svgfile, "</g>\n");
559 }
560
561 void svg_time_grid(void)
562 {
563         u64 i;
564
565         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
581                 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",
582                         time2pixels(i), SLOT_MULT/2, time2pixels(i), total_height, color, color, color, thickness);
583
584                 i += 10000000;
585         }
586 }
587
588 void svg_close(void)
589 {
590         if (svgfile) {
591                 fprintf(svgfile, "</svg>\n");
592                 fclose(svgfile);
593                 svgfile = NULL;
594         }
595 }
596
597 #define cpumask_bits(maskp) ((maskp)->bits)
598 typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
599
600 struct topology {
601         cpumask_t *sib_core;
602         int sib_core_nr;
603         cpumask_t *sib_thr;
604         int sib_thr_nr;
605 };
606
607 static 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
624 static 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
637 static 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
663 int 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
710 exit:
711         free(t.sib_core);
712         free(t.sib_thr);
713
714         return -1;
715 }
This page took 0.071904 seconds and 4 git commands to generate.