Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
perf_counter, powerpc, sparc: Fix compilation after perf_counter_overflow() change
perf_counter: x86: Fix PMU resource leak
perf util: SVG performance improvements
perf util: Make the timechart SVG width dynamic
perf timechart: Show the duration of scheduler delays in the SVG
perf timechart: Show the name of the waker/wakee in timechart

+170 -69
+1 -2
arch/powerpc/kernel/perf_counter.c
··· 1162 1162 */ 1163 1163 if (record) { 1164 1164 struct perf_sample_data data = { 1165 - .regs = regs, 1166 1165 .addr = 0, 1167 1166 .period = counter->hw.last_period, 1168 1167 }; ··· 1169 1170 if (counter->attr.sample_type & PERF_SAMPLE_ADDR) 1170 1171 perf_get_data_addr(regs, &data.addr); 1171 1172 1172 - if (perf_counter_overflow(counter, nmi, &data)) { 1173 + if (perf_counter_overflow(counter, nmi, &data, regs)) { 1173 1174 /* 1174 1175 * Interrupts are coming too fast - throttle them 1175 1176 * by setting the counter to 0, so it will be
+1 -2
arch/sparc/kernel/perf_counter.c
··· 493 493 494 494 regs = args->regs; 495 495 496 - data.regs = regs; 497 496 data.addr = 0; 498 497 499 498 cpuc = &__get_cpu_var(cpu_hw_counters); ··· 512 513 if (!sparc_perf_counter_set_period(counter, hwc, idx)) 513 514 continue; 514 515 515 - if (perf_counter_overflow(counter, 1, &data)) 516 + if (perf_counter_overflow(counter, 1, &data, regs)) 516 517 sparc_pmu_disable_counter(hwc, idx); 517 518 } 518 519
+6 -3
arch/x86/kernel/cpu/perf_counter.c
··· 924 924 if (err) 925 925 return err; 926 926 927 + counter->destroy = hw_perf_counter_destroy; 928 + 927 929 /* 928 930 * Generate PMC IRQs: 929 931 * (keep 'enabled' bit clear for now) ··· 954 952 if (!x86_pmu.apic) 955 953 return -EOPNOTSUPP; 956 954 } 957 - 958 - counter->destroy = hw_perf_counter_destroy; 959 955 960 956 /* 961 957 * Raw event type provide the config in the event structure ··· 2107 2107 int err; 2108 2108 2109 2109 err = __hw_perf_counter_init(counter); 2110 - if (err) 2110 + if (err) { 2111 + if (counter->destroy) 2112 + counter->destroy(counter); 2111 2113 return ERR_PTR(err); 2114 + } 2112 2115 2113 2116 return &pmu; 2114 2117 }
-17
include/linux/perf_counter.h
··· 849 849 static inline void perf_counter_fork(struct task_struct *tsk) { } 850 850 static inline void perf_counter_init(void) { } 851 851 852 - static inline int 853 - perf_output_begin(struct perf_output_handle *handle, struct perf_counter *c, 854 - unsigned int size, int nmi, int sample) { } 855 - static inline void perf_output_end(struct perf_output_handle *handle) { } 856 - static inline void 857 - perf_output_copy(struct perf_output_handle *handle, 858 - const void *buf, unsigned int len) { } 859 - static inline void 860 - perf_output_sample(struct perf_output_handle *handle, 861 - struct perf_event_header *header, 862 - struct perf_sample_data *data, 863 - struct perf_counter *counter) { } 864 - static inline void 865 - perf_prepare_sample(struct perf_event_header *header, 866 - struct perf_sample_data *data, 867 - struct perf_counter *counter, 868 - struct pt_regs *regs) { } 869 852 #endif 870 853 871 854 #define perf_output_put(handle, x) \
+3
tools/perf/Documentation/perf-timechart.txt
··· 28 28 -i:: 29 29 --input=:: 30 30 Select the input file (default: perf.data) 31 + -w:: 32 + --width=:: 33 + Select the width of the SVG file (default: 1000) 31 34 32 35 33 36 SEE ALSO
+15 -8
tools/perf/builtin-timechart.c
··· 752 752 we = wake_events; 753 753 while (we) { 754 754 int from = 0, to = 0; 755 + char *task_from = NULL, *task_to = NULL; 755 756 756 757 /* locate the column of the waker and wakee */ 757 758 p = all_data; ··· 761 760 c = p->all; 762 761 while (c) { 763 762 if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { 764 - if (p->pid == we->waker) 763 + if (p->pid == we->waker) { 765 764 from = c->Y; 766 - if (p->pid == we->wakee) 765 + task_from = c->comm; 766 + } 767 + if (p->pid == we->wakee) { 767 768 to = c->Y; 769 + task_to = c->comm; 770 + } 768 771 } 769 772 c = c->next; 770 773 } ··· 781 776 else if (from && to && abs(from - to) == 1) 782 777 svg_wakeline(we->time, from, to); 783 778 else 784 - svg_partial_wakeline(we->time, from, to); 779 + svg_partial_wakeline(we->time, from, task_from, to, task_to); 785 780 we = we->next; 786 781 } 787 782 } ··· 827 822 continue; 828 823 } 829 824 830 - svg_box(Y, p->start_time, p->end_time, "process"); 825 + svg_box(Y, c->start_time, c->end_time, "process"); 831 826 sample = c->samples; 832 827 while (sample) { 833 828 if (sample->type == TYPE_RUNNING) 834 - svg_sample(Y, sample->cpu, sample->start_time, sample->end_time, "sample"); 829 + svg_sample(Y, sample->cpu, sample->start_time, sample->end_time); 835 830 if (sample->type == TYPE_BLOCKED) 836 831 svg_box(Y, sample->start_time, sample->end_time, "blocked"); 837 832 if (sample->type == TYPE_WAITING) 838 - svg_box(Y, sample->start_time, sample->end_time, "waiting"); 833 + svg_waiting(Y, sample->start_time, sample->end_time); 839 834 sample = sample->next; 840 835 } 841 836 ··· 915 910 if (count < 15) 916 911 count = determine_display_tasks(TIME_THRESH / 10); 917 912 918 - open_svg(filename, numcpus, count); 913 + open_svg(filename, numcpus, count, first_time, last_time); 919 914 920 - svg_time_grid(first_time, last_time); 915 + svg_time_grid(); 921 916 svg_legenda(); 922 917 923 918 for (i = 0; i < numcpus; i++) ··· 1132 1127 "input file name"), 1133 1128 OPT_STRING('o', "output", &output_name, "file", 1134 1129 "output file name"), 1130 + OPT_INTEGER('w', "width", &svg_page_width, 1131 + "page width"), 1135 1132 OPT_END() 1136 1133 }; 1137 1134
+137 -33
tools/perf/util/svghelper.c
··· 25 25 26 26 #define SLOT_MULT 30.0 27 27 #define SLOT_HEIGHT 25.0 28 - #define WIDTH 1000.0 28 + 29 + int svg_page_width = 1000; 29 30 30 31 #define MIN_TEXT_SIZE 0.001 31 32 ··· 47 46 { 48 47 double X; 49 48 50 - X = WIDTH * (time - first_time) / (last_time - first_time); 49 + X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time); 51 50 return X; 52 51 } 53 52 54 - void open_svg(const char *filename, int cpus, int rows) 53 + /* 54 + * Round text sizes so that the svg viewer only needs a discrete 55 + * number of renderings of the font 56 + */ 57 + static double round_text_size(double size) 55 58 { 59 + int loop = 100; 60 + double target = 10.0; 61 + 62 + if (size >= 10.0) 63 + return size; 64 + while (loop--) { 65 + if (size >= target) 66 + return target; 67 + target = target / 2.0; 68 + } 69 + return size; 70 + } 71 + 72 + void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end) 73 + { 74 + int new_width; 56 75 57 76 svgfile = fopen(filename, "w"); 58 77 if (!svgfile) { 59 78 fprintf(stderr, "Cannot open %s for output\n", filename); 60 79 return; 61 80 } 81 + first_time = start; 82 + first_time = first_time / 100000000 * 100000000; 83 + last_time = end; 84 + 85 + /* 86 + * if the recording is short, we default to a width of 1000, but 87 + * for longer recordings we want at least 200 units of width per second 88 + */ 89 + new_width = (last_time - first_time) / 5000000; 90 + 91 + if (new_width > svg_page_width) 92 + svg_page_width = new_width; 93 + 62 94 total_height = (1 + rows + cpu2slot(cpus)) * SLOT_MULT; 63 95 fprintf(svgfile, "<?xml version=\"1.0\" standalone=\"no\"?> \n"); 64 - fprintf(svgfile, "<svg width=\"%4.1f\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", WIDTH, total_height); 96 + fprintf(svgfile, "<svg width=\"%i\" height=\"%llu\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", svg_page_width, total_height); 65 97 66 98 fprintf(svgfile, "<defs>\n <style type=\"text/css\">\n <![CDATA[\n"); 67 99 ··· 103 69 fprintf(svgfile, " rect.process2 { fill:rgb(180,180,180); fill-opacity:0.9; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 104 70 fprintf(svgfile, " rect.sample { fill:rgb( 0, 0,255); fill-opacity:0.8; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 105 71 fprintf(svgfile, " rect.blocked { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 106 - fprintf(svgfile, " rect.waiting { fill:rgb(255,255, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 72 + fprintf(svgfile, " rect.waiting { fill:rgb(214,214, 0); fill-opacity:0.3; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 73 + fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n"); 107 74 fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n"); 108 75 fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n"); 109 76 fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n"); ··· 127 92 time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); 128 93 } 129 94 130 - void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type) 95 + void svg_sample(int Yslot, int cpu, u64 start, u64 end) 131 96 { 132 97 double text_size; 133 98 if (!svgfile) 134 99 return; 135 100 136 - fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", 137 - time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT, type); 101 + fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"sample\"/>\n", 102 + time2pixels(start), time2pixels(end)-time2pixels(start), Yslot * SLOT_MULT, SLOT_HEIGHT); 138 103 139 104 text_size = (time2pixels(end)-time2pixels(start)); 140 105 if (cpu > 9) 141 106 text_size = text_size/2; 142 107 if (text_size > 1.25) 143 108 text_size = 1.25; 109 + text_size = round_text_size(text_size); 110 + 144 111 if (text_size > MIN_TEXT_SIZE) 145 - fprintf(svgfile, "<text transform=\"translate(%1.8f,%1.8f)\" font-size=\"%1.6fpt\">%i</text>\n", 112 + fprintf(svgfile, "<text x=\"%1.8f\" y=\"%1.8f\" font-size=\"%1.8fpt\">%i</text>\n", 146 113 time2pixels(start), Yslot * SLOT_MULT + SLOT_HEIGHT - 1, text_size, cpu + 1); 147 114 115 + } 116 + 117 + static char *time_to_string(u64 duration) 118 + { 119 + static char text[80]; 120 + 121 + text[0] = 0; 122 + 123 + if (duration < 1000) /* less than 1 usec */ 124 + return text; 125 + 126 + if (duration < 1000 * 1000) { /* less than 1 msec */ 127 + sprintf(text, "%4.1f us", duration / 1000.0); 128 + return text; 129 + } 130 + sprintf(text, "%4.1f ms", duration / 1000.0 / 1000); 131 + 132 + return text; 133 + } 134 + 135 + void svg_waiting(int Yslot, u64 start, u64 end) 136 + { 137 + char *text; 138 + const char *style; 139 + double font_size; 140 + 141 + if (!svgfile) 142 + return; 143 + 144 + style = "waiting"; 145 + 146 + if (end-start > 10 * 1000000) /* 10 msec */ 147 + style = "WAITING"; 148 + 149 + text = time_to_string(end-start); 150 + 151 + font_size = 1.0 * (time2pixels(end)-time2pixels(start)); 152 + 153 + if (font_size > 3) 154 + font_size = 3; 155 + 156 + font_size = round_text_size(font_size); 157 + 158 + fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), Yslot * SLOT_MULT); 159 + fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", 160 + time2pixels(end)-time2pixels(start), SLOT_HEIGHT, style); 161 + if (font_size > MIN_TEXT_SIZE) 162 + fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%1.8fpt\"> %s</text>\n", 163 + font_size, text); 164 + fprintf(svgfile, "</g>\n"); 148 165 } 149 166 150 167 static char *cpu_model(void) ··· 235 148 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); 236 149 237 150 sprintf(cpu_string, "CPU %i", (int)cpu+1); 238 - fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n", 151 + fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", 239 152 10+time2pixels(first_time), cpu2y(cpu) + SLOT_HEIGHT/2, cpu_string); 240 153 241 154 fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"1.25pt\">%s</text>\n", ··· 249 162 if (!svgfile) 250 163 return; 251 164 252 - fprintf(svgfile, "<rect x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\" class=\"%s\"/>\n", 253 - time2pixels(start), time2pixels(end)-time2pixels(start), cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT, type); 165 + 166 + fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\">\n", time2pixels(start), cpu2y(cpu)); 167 + fprintf(svgfile, "<rect x=\"0\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", 168 + time2pixels(end)-time2pixels(start), SLOT_MULT+SLOT_HEIGHT, type); 254 169 width = time2pixels(end)-time2pixels(start); 255 170 if (width > 6) 256 171 width = 6; 257 172 173 + width = round_text_size(width); 174 + 258 175 if (width > MIN_TEXT_SIZE) 259 - fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">%s</text>\n", 260 - time2pixels(start), cpu2y(cpu), width, name); 176 + fprintf(svgfile, "<text transform=\"rotate(90)\" font-size=\"%3.8fpt\">%s</text>\n", 177 + width, name); 178 + 179 + fprintf(svgfile, "</g>\n"); 261 180 } 262 181 263 182 void svg_cstate(int cpu, u64 start, u64 end, int type) ··· 284 191 time2pixels(start), time2pixels(end)-time2pixels(start), 285 192 cpu2y(cpu), SLOT_MULT+SLOT_HEIGHT); 286 193 287 - width = time2pixels(end)-time2pixels(start); 194 + width = (time2pixels(end)-time2pixels(start))/2.0; 288 195 if (width > 6) 289 196 width = 6; 290 197 198 + width = round_text_size(width); 199 + 291 200 if (width > MIN_TEXT_SIZE) 292 - fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f) rotate(90)\" font-size=\"%3.4fpt\">C%i</text>\n", 293 - time2pixels(start), cpu2y(cpu), width, type); 201 + fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"%3.8fpt\">C%i</text>\n", 202 + time2pixels(start), cpu2y(cpu)+width, width, type); 294 203 } 295 204 296 205 static char *HzToHuman(unsigned long hz) ··· 331 236 height = 1 + cpu2y(cpu) + SLOT_MULT + SLOT_HEIGHT - height; 332 237 fprintf(svgfile, "<line x1=\"%4.8f\" x2=\"%4.8f\" y1=\"%4.1f\" y2=\"%4.1f\" class=\"pstate\"/>\n", 333 238 time2pixels(start), time2pixels(end), height, height); 334 - fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\" font-size=\"0.25pt\">%s</text>\n", 239 + fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\" font-size=\"0.25pt\">%s</text>\n", 335 240 time2pixels(start), height+0.9, HzToHuman(freq)); 336 241 337 242 } 338 243 339 244 340 - void svg_partial_wakeline(u64 start, int row1, int row2) 245 + void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2) 341 246 { 342 247 double height; 343 248 ··· 346 251 347 252 348 253 if (row1 < row2) { 349 - if (row1) 254 + if (row1) { 350 255 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 351 256 time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); 352 - 353 - if (row2) 257 + if (desc2) 258 + fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n", 259 + time2pixels(start), row1 * SLOT_MULT + SLOT_HEIGHT + SLOT_HEIGHT/48, desc2); 260 + } 261 + if (row2) { 354 262 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 355 263 time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row2 * SLOT_MULT); 264 + if (desc1) 265 + fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &gt;</text></g>\n", 266 + time2pixels(start), row2 * SLOT_MULT - SLOT_MULT/32, desc1); 267 + } 356 268 } else { 357 - if (row2) 269 + if (row2) { 358 270 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 359 271 time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT, time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/32); 360 - 361 - if (row1) 272 + if (desc1) 273 + fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n", 274 + time2pixels(start), row2 * SLOT_MULT + SLOT_HEIGHT + SLOT_MULT/48, desc1); 275 + } 276 + if (row1) { 362 277 fprintf(svgfile, "<line x1=\"%4.8f\" y1=\"%4.2f\" x2=\"%4.8f\" y2=\"%4.2f\" style=\"stroke:rgb(32,255,32);stroke-width:0.009\"/>\n", 363 278 time2pixels(start), row1 * SLOT_MULT - SLOT_MULT/32, time2pixels(start), row1 * SLOT_MULT); 279 + if (desc2) 280 + fprintf(svgfile, "<g transform=\"translate(%4.8f,%4.8f)\"><text transform=\"rotate(90)\" font-size=\"0.02pt\">%s &lt;</text></g>\n", 281 + time2pixels(start), row1 * SLOT_MULT - SLOT_HEIGHT/32, desc2); 282 + } 364 283 } 365 284 height = row1 * SLOT_MULT; 366 285 if (row2 > row1) ··· 422 313 if (!svgfile) 423 314 return; 424 315 425 - fprintf(svgfile, "<text transform=\"translate(%4.8f,%4.8f)\">%s</text>\n", 316 + fprintf(svgfile, "<text x=\"%4.8f\" y=\"%4.8f\">%s</text>\n", 426 317 time2pixels(start), Yslot * SLOT_MULT+SLOT_HEIGHT/2, text); 427 318 } 428 319 ··· 433 324 434 325 fprintf(svgfile, "<rect x=\"%i\" width=\"%4.8f\" y=\"0\" height=\"%4.1f\" class=\"%s\"/>\n", 435 326 X, boxsize, boxsize, style); 436 - fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.4fpt\">%s</text>\n", 327 + fprintf(svgfile, "<text transform=\"translate(%4.8f, %4.8f)\" font-size=\"%4.8fpt\">%s</text>\n", 437 328 X + boxsize + 5, boxsize, 0.8 * boxsize, text); 438 329 } 439 330 ··· 451 342 svg_legenda_box(800, "Blocked on IO", "blocked"); 452 343 } 453 344 454 - void svg_time_grid(u64 start, u64 end) 345 + void svg_time_grid(void) 455 346 { 456 347 u64 i; 457 - 458 - first_time = start; 459 - last_time = end; 460 - 461 - first_time = first_time / 100000000 * 100000000; 462 348 463 349 if (!svgfile) 464 350 return;
+7 -4
tools/perf/util/svghelper.h
··· 3 3 4 4 #include "types.h" 5 5 6 - extern void open_svg(const char *filename, int cpus, int rows); 6 + extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); 7 7 extern void svg_box(int Yslot, u64 start, u64 end, const char *type); 8 - extern void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type); 8 + extern void svg_sample(int Yslot, int cpu, u64 start, u64 end); 9 + extern void svg_waiting(int Yslot, u64 start, u64 end); 9 10 extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); 10 11 11 12 ··· 15 14 extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); 16 15 17 16 18 - extern void svg_time_grid(u64 start, u64 end); 17 + extern void svg_time_grid(void); 19 18 extern void svg_legenda(void); 20 19 extern void svg_wakeline(u64 start, int row1, int row2); 21 - extern void svg_partial_wakeline(u64 start, int row1, int row2); 20 + extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2); 22 21 extern void svg_interrupt(u64 start, int row); 23 22 extern void svg_text(int Yslot, u64 start, const char *text); 24 23 extern void svg_close(void); 24 + 25 + extern int svg_page_width; 25 26 26 27 #endif