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