162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * svghelper.c - helper functions for outputting svg 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (C) Copyright 2009 Intel Corporation 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: 862306a36Sopenharmony_ci * Arjan van de Ven <arjan@linux.intel.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <inttypes.h> 1262306a36Sopenharmony_ci#include <stdio.h> 1362306a36Sopenharmony_ci#include <stdlib.h> 1462306a36Sopenharmony_ci#include <unistd.h> 1562306a36Sopenharmony_ci#include <string.h> 1662306a36Sopenharmony_ci#include <linux/bitmap.h> 1762306a36Sopenharmony_ci#include <linux/string.h> 1862306a36Sopenharmony_ci#include <linux/time64.h> 1962306a36Sopenharmony_ci#include <linux/zalloc.h> 2062306a36Sopenharmony_ci#include <internal/cpumap.h> 2162306a36Sopenharmony_ci#include <perf/cpumap.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "env.h" 2462306a36Sopenharmony_ci#include "svghelper.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic u64 first_time, last_time; 2762306a36Sopenharmony_cistatic u64 turbo_frequency, max_freq; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define SLOT_MULT 30.0 3162306a36Sopenharmony_ci#define SLOT_HEIGHT 25.0 3262306a36Sopenharmony_ci#define SLOT_HALF (SLOT_HEIGHT / 2) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciint svg_page_width = 1000; 3562306a36Sopenharmony_ciu64 svg_highlight; 3662306a36Sopenharmony_ciconst char *svg_highlight_name; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define MIN_TEXT_SIZE 0.01 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic u64 total_height; 4162306a36Sopenharmony_cistatic FILE *svgfile; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic double cpu2slot(int cpu) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci return 2 * cpu + 1; 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic int *topology_map; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic double cpu2y(int cpu) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci if (topology_map) 5362306a36Sopenharmony_ci return cpu2slot(topology_map[cpu]) * SLOT_MULT; 5462306a36Sopenharmony_ci else 5562306a36Sopenharmony_ci return cpu2slot(cpu) * SLOT_MULT; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic double time2pixels(u64 __time) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci double X; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time); 6362306a36Sopenharmony_ci return X; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* 6762306a36Sopenharmony_ci * Round text sizes so that the svg viewer only needs a discrete 6862306a36Sopenharmony_ci * number of renderings of the font 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistatic double round_text_size(double size) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci int loop = 100; 7362306a36Sopenharmony_ci double target = 10.0; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci if (size >= 10.0) 7662306a36Sopenharmony_ci return size; 7762306a36Sopenharmony_ci while (loop--) { 7862306a36Sopenharmony_ci if (size >= target) 7962306a36Sopenharmony_ci return target; 8062306a36Sopenharmony_ci target = target / 2.0; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci return size; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_civoid open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci int new_width; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci svgfile = fopen(filename, "w"); 9062306a36Sopenharmony_ci if (!svgfile) { 9162306a36Sopenharmony_ci fprintf(stderr, "Cannot open %s for output\n", filename); 9262306a36Sopenharmony_ci return; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci first_time = start; 9562306a36Sopenharmony_ci first_time = first_time / 100000000 * 100000000; 9662306a36Sopenharmony_ci last_time = end; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci /* 9962306a36Sopenharmony_ci * if the recording is short, we default to a width of 1000, but 10062306a36Sopenharmony_ci * for longer recordings we want at least 200 units of width per second 10162306a36Sopenharmony_ci */ 10262306a36Sopenharmony_ci new_width = (last_time - first_time) / 5000000; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci if (new_width > svg_page_width) 10562306a36Sopenharmony_ci svg_page_width = new_width; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; 10862306a36Sopenharmony_ci fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); 10962306a36Sopenharmony_ci fprintf(svgfile, "<!DOCTYPE svg SYSTEM \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"); 11062306a36Sopenharmony_ci fprintf(svgfile, "<svg width=\"%i\" height=\"%" PRIu64 "\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci fprintf(svgfile, " rect { stroke-width: 1; }\n"); 11562306a36Sopenharmony_ci fprintf(svgfile, " rect.process { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:1; stroke:rgb( 0, 0, 0); } \n"); 11662306a36Sopenharmony_ci fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 11762306a36Sopenharmony_ci fprintf(svgfile, " rect.process3 { fill:rgb(180,180,180); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 11862306a36Sopenharmony_ci fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 11962306a36Sopenharmony_ci fprintf(svgfile, " rect.sample_hi{ fill:rgb(255,128, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12062306a36Sopenharmony_ci fprintf(svgfile, " rect.error { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12162306a36Sopenharmony_ci fprintf(svgfile, " rect.net { fill:rgb( 0,128, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12262306a36Sopenharmony_ci fprintf(svgfile, " rect.disk { fill:rgb( 0, 0,255); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12362306a36Sopenharmony_ci fprintf(svgfile, " rect.sync { fill:rgb(128,128, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12462306a36Sopenharmony_ci fprintf(svgfile, " rect.poll { fill:rgb( 0,128,128); fill-opacity:0.2; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12562306a36Sopenharmony_ci fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12662306a36Sopenharmony_ci fprintf(svgfile, " rect.waiting { fill:rgb(224,214, 0); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12762306a36Sopenharmony_ci fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 12862306a36Sopenharmony_ci fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n"); 12962306a36Sopenharmony_ci fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n"); 13062306a36Sopenharmony_ci fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n"); 13162306a36Sopenharmony_ci fprintf(svgfile, " rect.c2 { fill:rgb(255,172,172); fill-opacity:0.5; stroke-width:0; } \n"); 13262306a36Sopenharmony_ci fprintf(svgfile, " rect.c3 { fill:rgb(255,130,130); fill-opacity:0.5; stroke-width:0; } \n"); 13362306a36Sopenharmony_ci fprintf(svgfile, " rect.c4 { fill:rgb(255, 88, 88); fill-opacity:0.5; stroke-width:0; } \n"); 13462306a36Sopenharmony_ci fprintf(svgfile, " rect.c5 { fill:rgb(255, 44, 44); fill-opacity:0.5; stroke-width:0; } \n"); 13562306a36Sopenharmony_ci fprintf(svgfile, " rect.c6 { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; } \n"); 13662306a36Sopenharmony_ci fprintf(svgfile, " line.pstate { stroke:rgb(255,255, 0); stroke-opacity:0.8; stroke-width:2; } \n"); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci fprintf(svgfile, " ]]>\n </style>\n</defs>\n"); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic double normalize_height(double height) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci if (height < 0.25) 14462306a36Sopenharmony_ci return 0.25; 14562306a36Sopenharmony_ci else if (height < 0.50) 14662306a36Sopenharmony_ci return 0.50; 14762306a36Sopenharmony_ci else if (height < 0.75) 14862306a36Sopenharmony_ci return 0.75; 14962306a36Sopenharmony_ci else 15062306a36Sopenharmony_ci return 0.100; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_civoid svg_ubox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci double w = time2pixels(end) - time2pixels(start); 15662306a36Sopenharmony_ci height = normalize_height(height); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (!svgfile) 15962306a36Sopenharmony_ci return; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 16262306a36Sopenharmony_ci fprintf(svgfile, "<title>fd=%d error=%d merges=%d</title>\n", fd, err, merges); 16362306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n", 16462306a36Sopenharmony_ci time2pixels(start), 16562306a36Sopenharmony_ci w, 16662306a36Sopenharmony_ci Yslot * SLOT_MULT, 16762306a36Sopenharmony_ci SLOT_HALF * height, 16862306a36Sopenharmony_ci type); 16962306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_civoid svg_lbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci double w = time2pixels(end) - time2pixels(start); 17562306a36Sopenharmony_ci height = normalize_height(height); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (!svgfile) 17862306a36Sopenharmony_ci return; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 18162306a36Sopenharmony_ci fprintf(svgfile, "<title>fd=%d error=%d merges=%d</title>\n", fd, err, merges); 18262306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n", 18362306a36Sopenharmony_ci time2pixels(start), 18462306a36Sopenharmony_ci w, 18562306a36Sopenharmony_ci Yslot * SLOT_MULT + SLOT_HEIGHT - SLOT_HALF * height, 18662306a36Sopenharmony_ci SLOT_HALF * height, 18762306a36Sopenharmony_ci type); 18862306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_civoid svg_fbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci double w = time2pixels(end) - time2pixels(start); 19462306a36Sopenharmony_ci height = normalize_height(height); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (!svgfile) 19762306a36Sopenharmony_ci return; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 20062306a36Sopenharmony_ci fprintf(svgfile, "<title>fd=%d error=%d merges=%d</title>\n", fd, err, merges); 20162306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n", 20262306a36Sopenharmony_ci time2pixels(start), 20362306a36Sopenharmony_ci w, 20462306a36Sopenharmony_ci Yslot * SLOT_MULT + SLOT_HEIGHT - SLOT_HEIGHT * height, 20562306a36Sopenharmony_ci SLOT_HEIGHT * height, 20662306a36Sopenharmony_ci type); 20762306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_civoid svg_box(int Yslot, u64 start, u64 end, const char *type) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci if (!svgfile) 21362306a36Sopenharmony_ci return; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n", 21662306a36Sopenharmony_ci time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic char *time_to_string(u64 duration); 22062306a36Sopenharmony_civoid svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci if (!svgfile) 22362306a36Sopenharmony_ci return; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 22662306a36Sopenharmony_ci fprintf(svgfile, "<title>#%d blocked %s</title>\n", cpu, 22762306a36Sopenharmony_ci time_to_string(end - start)); 22862306a36Sopenharmony_ci if (backtrace) 22962306a36Sopenharmony_ci fprintf(svgfile, "<desc>Blocked on:\n%s</desc>\n", backtrace); 23062306a36Sopenharmony_ci svg_box(Yslot, start, end, "blocked"); 23162306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_civoid svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci double text_size; 23762306a36Sopenharmony_ci const char *type; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (!svgfile) 24062306a36Sopenharmony_ci return; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci if (svg_highlight && end - start > svg_highlight) 24362306a36Sopenharmony_ci type = "sample_hi"; 24462306a36Sopenharmony_ci else 24562306a36Sopenharmony_ci type = "sample"; 24662306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci fprintf(svgfile, "<title>#%d running %s</title>\n", 24962306a36Sopenharmony_ci cpu, time_to_string(end - start)); 25062306a36Sopenharmony_ci if (backtrace) 25162306a36Sopenharmony_ci fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); 25262306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"%s\"/>\n", 25362306a36Sopenharmony_ci time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, 25462306a36Sopenharmony_ci type); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci text_size = (time2pixels(end)-time2pixels(start)); 25762306a36Sopenharmony_ci if (cpu > 9) 25862306a36Sopenharmony_ci text_size = text_size/2; 25962306a36Sopenharmony_ci if (text_size > 1.25) 26062306a36Sopenharmony_ci text_size = 1.25; 26162306a36Sopenharmony_ci text_size = round_text_size(text_size); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (text_size > MIN_TEXT_SIZE) 26462306a36Sopenharmony_ci fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\" font-size=\"%.8fpt\">%i</text>\n", 26562306a36Sopenharmony_ci time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic char *time_to_string(u64 duration) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci static char text[80]; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci text[0] = 0; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if (duration < NSEC_PER_USEC) /* less than 1 usec */ 27762306a36Sopenharmony_ci return text; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (duration < NSEC_PER_MSEC) { /* less than 1 msec */ 28062306a36Sopenharmony_ci sprintf(text, "%.1f us", duration / (double)NSEC_PER_USEC); 28162306a36Sopenharmony_ci return text; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci sprintf(text, "%.1f ms", duration / (double)NSEC_PER_MSEC); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return text; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_civoid svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace) 28962306a36Sopenharmony_ci{ 29062306a36Sopenharmony_ci char *text; 29162306a36Sopenharmony_ci const char *style; 29262306a36Sopenharmony_ci double font_size; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci if (!svgfile) 29562306a36Sopenharmony_ci return; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci style = "waiting"; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (end-start > 10 * NSEC_PER_MSEC) /* 10 msec */ 30062306a36Sopenharmony_ci style = "WAITING"; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci text = time_to_string(end-start); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci font_size = 1.0 * (time2pixels(end)-time2pixels(start)); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci if (font_size > 3) 30762306a36Sopenharmony_ci font_size = 3; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci font_size = round_text_size(font_size); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); 31262306a36Sopenharmony_ci fprintf(svgfile, "<title>#%d waiting %s</title>\n", cpu, time_to_string(end - start)); 31362306a36Sopenharmony_ci if (backtrace) 31462306a36Sopenharmony_ci fprintf(svgfile, "<desc>Waiting on:\n%s</desc>\n", backtrace); 31562306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"0\" width=\"%.8f\" y=\"0\" height=\"%.1f\" class=\"%s\"/>\n", 31662306a36Sopenharmony_ci time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); 31762306a36Sopenharmony_ci if (font_size > MIN_TEXT_SIZE) 31862306a36Sopenharmony_ci fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%.8fpt\"> %s</text>\n", 31962306a36Sopenharmony_ci font_size, text); 32062306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cistatic char *cpu_model(void) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci static char cpu_m[255]; 32662306a36Sopenharmony_ci char buf[256]; 32762306a36Sopenharmony_ci FILE *file; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci cpu_m[0] = 0; 33062306a36Sopenharmony_ci /* CPU type */ 33162306a36Sopenharmony_ci file = fopen("/proc/cpuinfo", "r"); 33262306a36Sopenharmony_ci if (file) { 33362306a36Sopenharmony_ci while (fgets(buf, 255, file)) { 33462306a36Sopenharmony_ci if (strcasestr(buf, "model name")) { 33562306a36Sopenharmony_ci strlcpy(cpu_m, &buf[13], 255); 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci fclose(file); 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci /* CPU type */ 34362306a36Sopenharmony_ci file = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies", "r"); 34462306a36Sopenharmony_ci if (file) { 34562306a36Sopenharmony_ci while (fgets(buf, 255, file)) { 34662306a36Sopenharmony_ci unsigned int freq; 34762306a36Sopenharmony_ci freq = strtoull(buf, NULL, 10); 34862306a36Sopenharmony_ci if (freq > max_freq) 34962306a36Sopenharmony_ci max_freq = freq; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci fclose(file); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci return cpu_m; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_civoid svg_cpu_box(int cpu, u64 __max_freq, u64 __turbo_freq) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci char cpu_string[80]; 35962306a36Sopenharmony_ci if (!svgfile) 36062306a36Sopenharmony_ci return; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci max_freq = __max_freq; 36362306a36Sopenharmony_ci turbo_frequency = __turbo_freq; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\" class=\"cpu\"/>\n", 36862306a36Sopenharmony_ci time2pixels(first_time), 36962306a36Sopenharmony_ci time2pixels(last_time)-time2pixels(first_time), 37062306a36Sopenharmony_ci cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci sprintf(cpu_string, "CPU %i", (int)cpu); 37362306a36Sopenharmony_ci fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\">%s</text>\n", 37462306a36Sopenharmony_ci 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci fprintf(svgfile, "<text transform=\"translate(%.8f,%.8f)\" font-size=\"1.25pt\">%s</text>\n", 37762306a36Sopenharmony_ci 10+time2pixels(first_time), cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - 4, cpu_model()); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_civoid svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci double width; 38562306a36Sopenharmony_ci const char *type; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if (!svgfile) 38862306a36Sopenharmony_ci return; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (svg_highlight && end - start >= svg_highlight) 39162306a36Sopenharmony_ci type = "sample_hi"; 39262306a36Sopenharmony_ci else if (svg_highlight_name && strstr(name, svg_highlight_name)) 39362306a36Sopenharmony_ci type = "sample_hi"; 39462306a36Sopenharmony_ci else 39562306a36Sopenharmony_ci type = "sample"; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\">\n", time2pixels(start), cpu2y(cpu)); 39862306a36Sopenharmony_ci fprintf(svgfile, "<title>%d %s running %s</title>\n", pid, name, time_to_string(end - start)); 39962306a36Sopenharmony_ci if (backtrace) 40062306a36Sopenharmony_ci fprintf(svgfile, "<desc>Switched because:\n%s</desc>\n", backtrace); 40162306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"0\" width=\"%.8f\" y=\"0\" height=\"%.1f\" class=\"%s\"/>\n", 40262306a36Sopenharmony_ci time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); 40362306a36Sopenharmony_ci width = time2pixels(end)-time2pixels(start); 40462306a36Sopenharmony_ci if (width > 6) 40562306a36Sopenharmony_ci width = 6; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci width = round_text_size(width); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci if (width > MIN_TEXT_SIZE) 41062306a36Sopenharmony_ci fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%.8fpt\">%s</text>\n", 41162306a36Sopenharmony_ci width, name); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_civoid svg_cstate(int cpu, u64 start, u64 end, int type) 41762306a36Sopenharmony_ci{ 41862306a36Sopenharmony_ci double width; 41962306a36Sopenharmony_ci char style[128]; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (!svgfile) 42262306a36Sopenharmony_ci return; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci if (type > 6) 42862306a36Sopenharmony_ci type = 6; 42962306a36Sopenharmony_ci sprintf(style, "c%i", type); 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci fprintf(svgfile, "<rect class=\"%s\" x=\"%.8f\" width=\"%.8f\" y=\"%.1f\" height=\"%.1f\"/>\n", 43262306a36Sopenharmony_ci style, 43362306a36Sopenharmony_ci time2pixels(start), time2pixels(end)-time2pixels(start), 43462306a36Sopenharmony_ci cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci width = (time2pixels(end)-time2pixels(start))/2.0; 43762306a36Sopenharmony_ci if (width > 6) 43862306a36Sopenharmony_ci width = 6; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci width = round_text_size(width); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci if (width > MIN_TEXT_SIZE) 44362306a36Sopenharmony_ci fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\" font-size=\"%.8fpt\">C%i</text>\n", 44462306a36Sopenharmony_ci time2pixels(start), cpu2y(cpu)+width, width, type); 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic char *HzToHuman(unsigned long hz) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci static char buffer[1024]; 45262306a36Sopenharmony_ci unsigned long long Hz; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci memset(buffer, 0, 1024); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci Hz = hz; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* default: just put the Number in */ 45962306a36Sopenharmony_ci sprintf(buffer, "%9lli", Hz); 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci if (Hz > 1000) 46262306a36Sopenharmony_ci sprintf(buffer, " %6lli Mhz", (Hz+500)/1000); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci if (Hz > 1500000) 46562306a36Sopenharmony_ci sprintf(buffer, " %6.2f Ghz", (Hz+5000.0)/1000000); 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci if (Hz == turbo_frequency) 46862306a36Sopenharmony_ci sprintf(buffer, "Turbo"); 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci return buffer; 47162306a36Sopenharmony_ci} 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_civoid svg_pstate(int cpu, u64 start, u64 end, u64 freq) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci double height = 0; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (!svgfile) 47862306a36Sopenharmony_ci return; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (max_freq) 48362306a36Sopenharmony_ci height = freq * 1.0 / max_freq * (SLOT_HEIGHT + SLOT_MULT); 48462306a36Sopenharmony_ci height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; 48562306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" x2=\"%.8f\" y1=\"%.1f\" y2=\"%.1f\" class=\"pstate\"/>\n", 48662306a36Sopenharmony_ci time2pixels(start), time2pixels(end), height, height); 48762306a36Sopenharmony_ci fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\" font-size=\"0.25pt\">%s</text>\n", 48862306a36Sopenharmony_ci time2pixels(start), height+0.9, HzToHuman(freq)); 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_civoid svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci double height; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (!svgfile) 49962306a36Sopenharmony_ci return; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci fprintf(svgfile, "<title>%s wakes up %s</title>\n", 50562306a36Sopenharmony_ci desc1 ? desc1 : "?", 50662306a36Sopenharmony_ci desc2 ? desc2 : "?"); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (backtrace) 50962306a36Sopenharmony_ci fprintf(svgfile, "<desc>%s</desc>\n", backtrace); 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci if (row1 < row2) { 51262306a36Sopenharmony_ci if (row1) { 51362306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 51462306a36Sopenharmony_ci time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); 51562306a36Sopenharmony_ci if (desc2) 51662306a36Sopenharmony_ci fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s ></text></g>\n", 51762306a36Sopenharmony_ci time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2); 51862306a36Sopenharmony_ci } 51962306a36Sopenharmony_ci if (row2) { 52062306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 52162306a36Sopenharmony_ci time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT); 52262306a36Sopenharmony_ci if (desc1) 52362306a36Sopenharmony_ci fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s ></text></g>\n", 52462306a36Sopenharmony_ci time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1); 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci } else { 52762306a36Sopenharmony_ci if (row2) { 52862306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 52962306a36Sopenharmony_ci time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); 53062306a36Sopenharmony_ci if (desc1) 53162306a36Sopenharmony_ci fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s <</text></g>\n", 53262306a36Sopenharmony_ci time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1); 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci if (row1) { 53562306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 53662306a36Sopenharmony_ci time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT); 53762306a36Sopenharmony_ci if (desc2) 53862306a36Sopenharmony_ci fprintf(svgfile, "<g transform=\"translate(%.8f,%.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s <</text></g>\n", 53962306a36Sopenharmony_ci time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2); 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci } 54262306a36Sopenharmony_ci height = row1 * SLOT_MULT; 54362306a36Sopenharmony_ci if (row2 > row1) 54462306a36Sopenharmony_ci height += SLOT_HEIGHT; 54562306a36Sopenharmony_ci if (row1) 54662306a36Sopenharmony_ci fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", 54762306a36Sopenharmony_ci time2pixels(start), height); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_civoid svg_wakeline(u64 start, int row1, int row2, const char *backtrace) 55362306a36Sopenharmony_ci{ 55462306a36Sopenharmony_ci double height; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (!svgfile) 55762306a36Sopenharmony_ci return; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (backtrace) 56362306a36Sopenharmony_ci fprintf(svgfile, "<desc>%s</desc>\n", backtrace); 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (row1 < row2) 56662306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 56762306a36Sopenharmony_ci time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT); 56862306a36Sopenharmony_ci else 56962306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 57062306a36Sopenharmony_ci time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci height = row1 * SLOT_MULT; 57362306a36Sopenharmony_ci if (row2 > row1) 57462306a36Sopenharmony_ci height += SLOT_HEIGHT; 57562306a36Sopenharmony_ci fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(32,255,32)\"/>\n", 57662306a36Sopenharmony_ci time2pixels(start), height); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_civoid svg_interrupt(u64 start, int row, const char *backtrace) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci if (!svgfile) 58462306a36Sopenharmony_ci return; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci fprintf(svgfile, "<title>Wakeup from interrupt</title>\n"); 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci if (backtrace) 59162306a36Sopenharmony_ci fprintf(svgfile, "<desc>%s</desc>\n", backtrace); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", 59462306a36Sopenharmony_ci time2pixels(start), row * SLOT_MULT); 59562306a36Sopenharmony_ci fprintf(svgfile, "<circle cx=\"%.8f\" cy=\"%.2f\" r = \"0.01\" style=\"fill:rgb(255,128,128)\"/>\n", 59662306a36Sopenharmony_ci time2pixels(start), row * SLOT_MULT + SLOT_HEIGHT); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 59962306a36Sopenharmony_ci} 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_civoid svg_text(int Yslot, u64 start, const char *text) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci if (!svgfile) 60462306a36Sopenharmony_ci return; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci fprintf(svgfile, "<text x=\"%.8f\" y=\"%.8f\">%s</text>\n", 60762306a36Sopenharmony_ci time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_cistatic void svg_legenda_box(int X, const char *text, const char *style) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci double boxsize; 61362306a36Sopenharmony_ci boxsize = SLOT_HEIGHT / 2; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci fprintf(svgfile, "<rect x=\"%i\" width=\"%.8f\" y=\"0\" height=\"%.1f\" class=\"%s\"/>\n", 61662306a36Sopenharmony_ci X, boxsize, boxsize, style); 61762306a36Sopenharmony_ci fprintf(svgfile, "<text transform=\"translate(%.8f, %.8f)\" font-size=\"%.8fpt\">%s</text>\n", 61862306a36Sopenharmony_ci X + boxsize + 5, boxsize, 0.8 * boxsize, text); 61962306a36Sopenharmony_ci} 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_civoid svg_io_legenda(void) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci if (!svgfile) 62462306a36Sopenharmony_ci return; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 62762306a36Sopenharmony_ci svg_legenda_box(0, "Disk", "disk"); 62862306a36Sopenharmony_ci svg_legenda_box(100, "Network", "net"); 62962306a36Sopenharmony_ci svg_legenda_box(200, "Sync", "sync"); 63062306a36Sopenharmony_ci svg_legenda_box(300, "Poll", "poll"); 63162306a36Sopenharmony_ci svg_legenda_box(400, "Error", "error"); 63262306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_civoid svg_legenda(void) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci if (!svgfile) 63862306a36Sopenharmony_ci return; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci fprintf(svgfile, "<g>\n"); 64162306a36Sopenharmony_ci svg_legenda_box(0, "Running", "sample"); 64262306a36Sopenharmony_ci svg_legenda_box(100, "Idle","c1"); 64362306a36Sopenharmony_ci svg_legenda_box(200, "Deeper Idle", "c3"); 64462306a36Sopenharmony_ci svg_legenda_box(350, "Deepest Idle", "c6"); 64562306a36Sopenharmony_ci svg_legenda_box(550, "Sleeping", "process2"); 64662306a36Sopenharmony_ci svg_legenda_box(650, "Waiting for cpu", "waiting"); 64762306a36Sopenharmony_ci svg_legenda_box(800, "Blocked on IO", "blocked"); 64862306a36Sopenharmony_ci fprintf(svgfile, "</g>\n"); 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_civoid svg_time_grid(double min_thickness) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci u64 i; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (!svgfile) 65662306a36Sopenharmony_ci return; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci i = first_time; 65962306a36Sopenharmony_ci while (i < last_time) { 66062306a36Sopenharmony_ci int color = 220; 66162306a36Sopenharmony_ci double thickness = 0.075; 66262306a36Sopenharmony_ci if ((i % 100000000) == 0) { 66362306a36Sopenharmony_ci thickness = 0.5; 66462306a36Sopenharmony_ci color = 192; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci if ((i % 1000000000) == 0) { 66762306a36Sopenharmony_ci thickness = 2.0; 66862306a36Sopenharmony_ci color = 128; 66962306a36Sopenharmony_ci } 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (thickness >= min_thickness) 67262306a36Sopenharmony_ci fprintf(svgfile, "<line x1=\"%.8f\" y1=\"%.2f\" x2=\"%.8f\" y2=\"%" PRIu64 "\" style=\"stroke:rgb(%i,%i,%i);stroke-width:%.3f\"/>\n", 67362306a36Sopenharmony_ci time2pixels(i), SLOT_MULT/2, time2pixels(i), 67462306a36Sopenharmony_ci total_height, color, color, color, thickness); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci i += 10000000; 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_civoid svg_close(void) 68162306a36Sopenharmony_ci{ 68262306a36Sopenharmony_ci if (svgfile) { 68362306a36Sopenharmony_ci fprintf(svgfile, "</svg>\n"); 68462306a36Sopenharmony_ci fclose(svgfile); 68562306a36Sopenharmony_ci svgfile = NULL; 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci#define cpumask_bits(maskp) ((maskp)->bits) 69062306a36Sopenharmony_citypedef struct { DECLARE_BITMAP(bits, MAX_NR_CPUS); } cpumask_t; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistruct topology { 69362306a36Sopenharmony_ci cpumask_t *sib_core; 69462306a36Sopenharmony_ci int sib_core_nr; 69562306a36Sopenharmony_ci cpumask_t *sib_thr; 69662306a36Sopenharmony_ci int sib_thr_nr; 69762306a36Sopenharmony_ci}; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cistatic void scan_thread_topology(int *map, struct topology *t, int cpu, 70062306a36Sopenharmony_ci int *pos, int nr_cpus) 70162306a36Sopenharmony_ci{ 70262306a36Sopenharmony_ci int i; 70362306a36Sopenharmony_ci int thr; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci for (i = 0; i < t->sib_thr_nr; i++) { 70662306a36Sopenharmony_ci if (!test_bit(cpu, cpumask_bits(&t->sib_thr[i]))) 70762306a36Sopenharmony_ci continue; 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci for_each_set_bit(thr, cpumask_bits(&t->sib_thr[i]), nr_cpus) 71062306a36Sopenharmony_ci if (map[thr] == -1) 71162306a36Sopenharmony_ci map[thr] = (*pos)++; 71262306a36Sopenharmony_ci } 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_cistatic void scan_core_topology(int *map, struct topology *t, int nr_cpus) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci int pos = 0; 71862306a36Sopenharmony_ci int i; 71962306a36Sopenharmony_ci int cpu; 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci for (i = 0; i < t->sib_core_nr; i++) 72262306a36Sopenharmony_ci for_each_set_bit(cpu, cpumask_bits(&t->sib_core[i]), nr_cpus) 72362306a36Sopenharmony_ci scan_thread_topology(map, t, cpu, &pos, nr_cpus); 72462306a36Sopenharmony_ci} 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_cistatic int str_to_bitmap(char *s, cpumask_t *b, int nr_cpus) 72762306a36Sopenharmony_ci{ 72862306a36Sopenharmony_ci int i; 72962306a36Sopenharmony_ci int ret = 0; 73062306a36Sopenharmony_ci struct perf_cpu_map *m; 73162306a36Sopenharmony_ci struct perf_cpu c; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci m = perf_cpu_map__new(s); 73462306a36Sopenharmony_ci if (!m) 73562306a36Sopenharmony_ci return -1; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci for (i = 0; i < perf_cpu_map__nr(m); i++) { 73862306a36Sopenharmony_ci c = perf_cpu_map__cpu(m, i); 73962306a36Sopenharmony_ci if (c.cpu >= nr_cpus) { 74062306a36Sopenharmony_ci ret = -1; 74162306a36Sopenharmony_ci break; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci __set_bit(c.cpu, cpumask_bits(b)); 74562306a36Sopenharmony_ci } 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci perf_cpu_map__put(m); 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return ret; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ciint svg_build_topology_map(struct perf_env *env) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci int i, nr_cpus; 75562306a36Sopenharmony_ci struct topology t; 75662306a36Sopenharmony_ci char *sib_core, *sib_thr; 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci nr_cpus = min(env->nr_cpus_online, MAX_NR_CPUS); 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci t.sib_core_nr = env->nr_sibling_cores; 76162306a36Sopenharmony_ci t.sib_thr_nr = env->nr_sibling_threads; 76262306a36Sopenharmony_ci t.sib_core = calloc(env->nr_sibling_cores, sizeof(cpumask_t)); 76362306a36Sopenharmony_ci t.sib_thr = calloc(env->nr_sibling_threads, sizeof(cpumask_t)); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci sib_core = env->sibling_cores; 76662306a36Sopenharmony_ci sib_thr = env->sibling_threads; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci if (!t.sib_core || !t.sib_thr) { 76962306a36Sopenharmony_ci fprintf(stderr, "topology: no memory\n"); 77062306a36Sopenharmony_ci goto exit; 77162306a36Sopenharmony_ci } 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci for (i = 0; i < env->nr_sibling_cores; i++) { 77462306a36Sopenharmony_ci if (str_to_bitmap(sib_core, &t.sib_core[i], nr_cpus)) { 77562306a36Sopenharmony_ci fprintf(stderr, "topology: can't parse siblings map\n"); 77662306a36Sopenharmony_ci goto exit; 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci sib_core += strlen(sib_core) + 1; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci for (i = 0; i < env->nr_sibling_threads; i++) { 78362306a36Sopenharmony_ci if (str_to_bitmap(sib_thr, &t.sib_thr[i], nr_cpus)) { 78462306a36Sopenharmony_ci fprintf(stderr, "topology: can't parse siblings map\n"); 78562306a36Sopenharmony_ci goto exit; 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci sib_thr += strlen(sib_thr) + 1; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci topology_map = malloc(sizeof(int) * nr_cpus); 79262306a36Sopenharmony_ci if (!topology_map) { 79362306a36Sopenharmony_ci fprintf(stderr, "topology: no memory\n"); 79462306a36Sopenharmony_ci goto exit; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci for (i = 0; i < nr_cpus; i++) 79862306a36Sopenharmony_ci topology_map[i] = -1; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci scan_core_topology(topology_map, &t, nr_cpus); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci return 0; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ciexit: 80562306a36Sopenharmony_ci zfree(&t.sib_core); 80662306a36Sopenharmony_ci zfree(&t.sib_thr); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci return -1; 80962306a36Sopenharmony_ci} 810