^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * svghelper.c - helper functions for outputting svg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) Copyright 2009 Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Arjan van de Ven <arjan@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/time64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <internal/cpumap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <perf/cpumap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "env.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "svghelper.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static u64 first_time, last_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static u64 turbo_frequency, max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SLOT_MULT 30.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SLOT_HEIGHT 25.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define SLOT_HALF (SLOT_HEIGHT / 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int svg_page_width = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u64 svg_highlight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) const char *svg_highlight_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define MIN_TEXT_SIZE 0.01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static u64 total_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static FILE *svgfile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static double cpu2slot(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 2 * cpu + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static int *topology_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static double cpu2y(int cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (topology_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return cpu2slot(topology_map[cpu]) * SLOT_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return cpu2slot(cpu) * SLOT_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static double time2pixels(u64 __time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) double X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * Round text sizes so that the svg viewer only needs a discrete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * number of renderings of the font
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static double round_text_size(double size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) int loop = 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) double target = 10.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (size >= 10.0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) while (loop--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (size >= target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) target = target / 2.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int new_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) svgfile = fopen(filename, "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (!svgfile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) fprintf(stderr, "Cannot open %s for output\n", filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) first_time = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) first_time = first_time / 100000000 * 100000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) last_time = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * if the recording is short, we default to a width of 1000, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * for longer recordings we want at least 200 units of width per second
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) new_width = (last_time - first_time) / 5000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (new_width > svg_page_width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) svg_page_width = new_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) fprintf(svgfile, " rect { stroke-width: 1; }\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) fprintf(svgfile, " rect.process3 { fill:rgb(180,180,180); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) fprintf(svgfile, " rect.error { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) fprintf(svgfile, " rect.net { fill:rgb( 0,128, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) fprintf(svgfile, " rect.disk { fill:rgb( 0, 0,255); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) fprintf(svgfile, " rect.sync { fill:rgb(128,128, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) fprintf(svgfile, " rect.poll { fill:rgb( 0,128,128); fill-opacity:0.2; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fprintf(svgfile, " rect.c2 { fill:rgb(255,172,172); fill-opacity:0.5; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) fprintf(svgfile, " rect.c3 { fill:rgb(255,130,130); fill-opacity:0.5; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) fprintf(svgfile, " rect.c4 { fill:rgb(255, 88, 88); fill-opacity:0.5; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) fprintf(svgfile, " rect.c5 { fill:rgb(255, 44, 44); fill-opacity:0.5; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) fprintf(svgfile, " rect.c6 { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) fprintf(svgfile, " line.pstate { stroke:rgb(255,255, 0); stroke-opacity:0.8; stroke-width:2; } \n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) fprintf(svgfile, " ]]>\n </style>\n</defs>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static double normalize_height(double height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (height < 0.25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return 0.25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) else if (height < 0.50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0.50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) else if (height < 0.75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0.75;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return 0.100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) void svg_ubox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) double w = time2pixels(end) - time2pixels(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) height = normalize_height(height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) fprintf(svgfile, "<title>fd=%d error=%d merges=%d</title>\n", fd, err, merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) time2pixels(start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) Yslot * SLOT_MULT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) SLOT_HALF * height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) void svg_lbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) double w = time2pixels(end) - time2pixels(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) height = normalize_height(height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) fprintf(svgfile, "<title>fd=%d error=%d merges=%d</title>\n", fd, err, merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) time2pixels(start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) Yslot * SLOT_MULT + SLOT_HEIGHT - SLOT_HALF * height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) SLOT_HALF * height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) void svg_fbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) double w = time2pixels(end) - time2pixels(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) height = normalize_height(height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) fprintf(svgfile, "<title>fd=%d error=%d merges=%d</title>\n", fd, err, merges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) time2pixels(start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) Yslot * SLOT_MULT + SLOT_HEIGHT - SLOT_HEIGHT * height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) SLOT_HEIGHT * height,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) void svg_box(int Yslot, u64 start, u64 end, const char *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) static char *time_to_string(u64 duration);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) time_to_string(end - start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) svg_box(Yslot, start, end, "blocked");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) double text_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (svg_highlight && end - start > svg_highlight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) type = "sample_hi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) type = "sample";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) fprintf(svgfile, "<title>#%d running %s</title>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) cpu, time_to_string(end - start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) text_size = (time2pixels(end)-time2pixels(start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (cpu > 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) text_size = text_size/2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (text_size > 1.25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) text_size = 1.25;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) text_size = round_text_size(text_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (text_size > MIN_TEXT_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\" font-size=\"%.8fpt\">%i</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static char *time_to_string(u64 duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static char text[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) text[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (duration < NSEC_PER_USEC) /* less than 1 usec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (duration < NSEC_PER_MSEC) { /* less than 1 msec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) sprintf(text, "%.1f us", duration / (double)NSEC_PER_USEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) sprintf(text, "%.1f ms", duration / (double)NSEC_PER_MSEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) char *text;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) const char *style;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) double font_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) style = "waiting";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (end-start > 10 * NSEC_PER_MSEC) /* 10 msec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) style = "WAITING";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) text = time_to_string(end-start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) font_size = 1.0 * (time2pixels(end)-time2pixels(start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (font_size > 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) font_size = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) font_size = round_text_size(font_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) fprintf(svgfile, "<rect x=\"0\" width=\"%.8f\" y=\"0\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (font_size > MIN_TEXT_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%.8fpt\"> %s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) font_size, text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static char *cpu_model(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static char cpu_m[255];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) char buf[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) FILE *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) cpu_m[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* CPU type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) file = fopen("/proc/cpuinfo", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) while (fgets(buf, 255, file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (strstr(buf, "model name")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) strlcpy(cpu_m, &buf[13], 255);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) fclose(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* CPU type */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (file) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) while (fgets(buf, 255, file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) unsigned int freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) freq = strtoull(buf, NULL, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (freq > max_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) max_freq = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) fclose(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return cpu_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) void svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) char cpu_string[80];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) max_freq = __max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) turbo_frequency = __turbo_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"cpu\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) time2pixels(first_time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) time2pixels(last_time)-time2pixels(first_time),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) sprintf(cpu_string, "CPU %i", (int)cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\">%s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) fprintf(svgfile, "<text transform=\"translate(%.8f,%.8f)\" font-size=\"1.25pt\">%s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) double width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) const char *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (svg_highlight && end - start >= svg_highlight)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) type = "sample_hi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) else if (svg_highlight_name && strstr(name, svg_highlight_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) type = "sample_hi";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) type = "sample";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\">\n", time2pixels(start), cpu2y(cpu));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) fprintf(svgfile, "<rect x=\"0\" width=\"%.8f\" y=\"0\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) width = time2pixels(end)-time2pixels(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (width > 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) width = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) width = round_text_size(width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (width > MIN_TEXT_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%.8fpt\">%s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) width, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) void svg_cstate(int cpu, u64 start, u64 end, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) double width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) char style[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (type > 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) type = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) sprintf(style, "c%i", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) fprintf(svgfile, "<rect class=\"%s\" x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) style,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) time2pixels(start), time2pixels(end)-time2pixels(start),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) width = (time2pixels(end)-time2pixels(start))/2.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (width > 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) width = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) width = round_text_size(width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) if (width > MIN_TEXT_SIZE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\" font-size=\"%.8fpt\">C%i</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) time2pixels(start), cpu2y(cpu)+width, width, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static char *HzToHuman(unsigned long hz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) static char buffer[1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) unsigned long long Hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) memset(buffer, 0, 1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) Hz = hz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) /* default: just put the Number in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) sprintf(buffer, "%9lli", Hz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (Hz > 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) sprintf(buffer, " %6lli Mhz", (Hz+500)/1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (Hz > 1500000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) sprintf(buffer, " %6.2f Ghz", (Hz+5000.0)/1000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (Hz == turbo_frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) sprintf(buffer, "Turbo");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) void svg_pstate(int cpu, u64 start, u64 end, u64 freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) double height = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (max_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) fprintf(svgfile, "<line x1=\"%.8f\" x2=\"%.8f\" y1=\"%.1f\" y2=\"%.1f\" class=\"pstate\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) time2pixels(start), time2pixels(end), height, height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\" font-size=\"0.25pt\">%s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) time2pixels(start), height+0.9, HzToHuman(freq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) double height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) fprintf(svgfile, "<title>%s wakes up %s</title>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) desc1 ? desc1 : "?",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) desc2 ? desc2 : "?");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) if (row1 < row2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (row1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (desc2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s ></text></g>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) if (row2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (desc1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s ></text></g>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (row2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (desc1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s <</text></g>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (row1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (desc2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s <</text></g>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) height = row1 * SLOT_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (row2 > row1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) height += SLOT_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (row1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) time2pixels(start), height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) void svg_wakeline(u64 start, int row1, int row2, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) double height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (row1 < row2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) height = row1 * SLOT_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (row2 > row1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) height += SLOT_HEIGHT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) time2pixels(start), height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) void svg_interrupt(u64 start, int row, const char *backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) fprintf(svgfile, "<title>Wakeup from interrupt</title>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (backtrace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) fprintf(svgfile, "<desc>%s</desc>\n", backtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) time2pixels(start), row * SLOT_MULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) void svg_text(int Yslot, u64 start, const char *text)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\">%s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) static void svg_legenda_box(int X, const char *text, const char *style)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) double boxsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) boxsize = SLOT_HEIGHT / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) fprintf(svgfile, "<rect x=\"%i\" width=\"%.8f\" y=\"0\" height=\"%.1f\" class=\"%s\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) X, boxsize, boxsize, style);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) fprintf(svgfile, "<text transform=\"translate(%.8f, %.8f)\" font-size=\"%.8fpt\">%s</text>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) X + boxsize + 5, boxsize, 0.8 * boxsize, text);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) void svg_io_legenda(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) svg_legenda_box(0, "Disk", "disk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) svg_legenda_box(100, "Network", "net");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) svg_legenda_box(200, "Sync", "sync");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) svg_legenda_box(300, "Poll", "poll");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) svg_legenda_box(400, "Error", "error");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) void svg_legenda(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) fprintf(svgfile, "<g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) svg_legenda_box(0, "Running", "sample");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) svg_legenda_box(100, "Idle","c1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) svg_legenda_box(200, "Deeper Idle", "c3");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) svg_legenda_box(350, "Deepest Idle", "c6");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) svg_legenda_box(550, "Sleeping", "process2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) svg_legenda_box(650, "Waiting for cpu", "waiting");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) svg_legenda_box(800, "Blocked on IO", "blocked");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) fprintf(svgfile, "</g>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) void svg_time_grid(double min_thickness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) u64 i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (!svgfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) i = first_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) while (i < last_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) int color = 220;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) double thickness = 0.075;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if ((i % 100000000) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) thickness = 0.5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) color = 192;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if ((i % 1000000000) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) thickness = 2.0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) color = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (thickness >= min_thickness)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%" PRIu64 "\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%.3f\"/>\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) time2pixels(i), SLOT_MULT/2, time2pixels(i),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) total_height, color, color, color, thickness);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) i += 10000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) void svg_close(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) if (svgfile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) fprintf(svgfile, "</svg>\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) fclose(svgfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) svgfile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) #define cpumask_bits(maskp) ((maskp)->bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) typedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct topology {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) cpumask_t *sib_core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int sib_core_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) cpumask_t *sib_thr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) int sib_thr_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) static void scan_thread_topology(int *map, struct topology *t, int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int *pos, int nr_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int thr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) for (i = 0; i < t->sib_thr_nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i])))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) for_each_set_bit(thr, cpumask_bits(&t->sib_thr[i]), nr_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (map[thr] == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) map[thr] = (*pos)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static void scan_core_topology(int *map, struct topology *t, int nr_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) int pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) for (i = 0; i < t->sib_core_nr; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) for_each_set_bit(cpu, cpumask_bits(&t->sib_core[i]), nr_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) scan_thread_topology(map, t, cpu, &pos, nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) static int str_to_bitmap(char *s, cpumask_t *b, int nr_cpus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct perf_cpu_map *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) m = perf_cpu_map__new(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) for (i = 0; i < m->nr; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) c = m->map[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (c >= nr_cpus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) set_bit(c, cpumask_bits(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) perf_cpu_map__put(m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int svg_build_topology_map(struct perf_env *env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) int i, nr_cpus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) struct topology t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) char *sib_core, *sib_thr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) nr_cpus = min(env->nr_cpus_online, MAX_NR_CPUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) t.sib_core_nr = env->nr_sibling_cores;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) t.sib_thr_nr = env->nr_sibling_threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) t.sib_core = calloc(env->nr_sibling_cores, sizeof(cpumask_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) t.sib_thr = calloc(env->nr_sibling_threads, sizeof(cpumask_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) sib_core = env->sibling_cores;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) sib_thr = env->sibling_threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (!t.sib_core || !t.sib_thr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) fprintf(stderr, "topology: no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) for (i = 0; i < env->nr_sibling_cores; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (str_to_bitmap(sib_core, &t.sib_core[i], nr_cpus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) fprintf(stderr, "topology: can't parse siblings map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) sib_core += strlen(sib_core) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) for (i = 0; i < env->nr_sibling_threads; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (str_to_bitmap(sib_thr, &t.sib_thr[i], nr_cpus)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) fprintf(stderr, "topology: can't parse siblings map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) sib_thr += strlen(sib_thr) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) topology_map = malloc(sizeof(int) * nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (!topology_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) fprintf(stderr, "topology: no memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) for (i = 0; i < nr_cpus; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) topology_map[i] = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) scan_core_topology(topology_map, &t, nr_cpus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) zfree(&t.sib_core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) zfree(&t.sib_thr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }