[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] tools: delete gtraceview and gtracestat
commit 158dd1bdca161a6456ee6be293969f87ecde3922 Author: Wei Liu <wei.liu2@xxxxxxxxxx> AuthorDate: Mon Aug 15 16:27:27 2016 +0100 Commit: Wei Liu <wei.liu2@xxxxxxxxxx> CommitDate: Fri Sep 2 14:28:35 2016 +0100 tools: delete gtraceview and gtracestat There has not been any substantial update to them since 2011. My quick check shows that they don't work. Just delete them. It would be easy to resurrect them from git log should people still need them. Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> Acked-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> --- .gitignore | 2 - .hgignore | 2 - tools/misc/Makefile | 8 - tools/misc/gtracestat.c | 1110 ---------------------------------------------- tools/misc/gtraceview.c | 1111 ----------------------------------------------- 5 files changed, 2233 deletions(-) diff --git a/.gitignore b/.gitignore index a061f4a..43c6f93 100644 --- a/.gitignore +++ b/.gitignore @@ -193,8 +193,6 @@ tools/misc/xen-livepatch tools/misc/xenperf tools/misc/xenpm tools/misc/xen-hvmctx -tools/misc/gtraceview -tools/misc/gtracestat tools/misc/xenlockprof tools/misc/lowmemd tools/misc/xencov diff --git a/.hgignore b/.hgignore index 0bd29a1..8342f36 100644 --- a/.hgignore +++ b/.hgignore @@ -205,8 +205,6 @@ ^tools/misc/xenpm$ ^tools/misc/xen-hvmctx$ ^tools/misc/xen-lowmemd$ -^tools/misc/gtraceview$ -^tools/misc/gtracestat$ ^tools/misc/xenlockprof$ ^tools/misc/xencov$ ^tools/pygrub/build/.*$ diff --git a/tools/misc/Makefile b/tools/misc/Makefile index cee2b99..8152f7b 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -17,8 +17,6 @@ INSTALL_BIN += xencov_split INSTALL_BIN += $(INSTALL_BIN-y) # Everything to be installed in regular sbin/ -INSTALL_SBIN += gtracestat -INSTALL_SBIN += gtraceview INSTALL_SBIN += xen-bugtool INSTALL_SBIN-$(CONFIG_MIGRATE) += xen-hptool INSTALL_SBIN-$(CONFIG_X86) += xen-hvmcrash @@ -85,9 +83,6 @@ xenperf: xenperf.o xenpm: xenpm.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) -gtracestat: gtracestat.o - $(CC) $(LDFLAGS) -o $@ $< $(APPEND_LDFLAGS) - xenlockprof: xenlockprof.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) @@ -110,9 +105,6 @@ xen-livepatch: xen-livepatch.o xen-lowmemd: xen-lowmemd.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenevtchn) $(LDLIBS_libxenctrl) $(LDLIBS_libxenstore) $(APPEND_LDFLAGS) -gtraceview: gtraceview.o - $(CC) $(LDFLAGS) -o $@ $< $(CURSES_LIBS) $(TINFO_LIBS) $(APPEND_LDFLAGS) - xencov: xencov.o $(CC) $(LDFLAGS) -o $@ $< $(LDLIBS_libxenctrl) $(APPEND_LDFLAGS) diff --git a/tools/misc/gtracestat.c b/tools/misc/gtracestat.c deleted file mode 100644 index 67cb003..0000000 --- a/tools/misc/gtracestat.c +++ /dev/null @@ -1,1110 +0,0 @@ -/* - * gtracestat.c: list the statistics information for a dumped xentrace file. - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <getopt.h> -#include <inttypes.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <xenctrl.h> -#include <xen/trace.h> - -#define CHECK_DUP_CX 0 - -/********** MACROS **********/ -#define MAX_CPU_NR 32 -#define MAX_CX_NR 8 -#define MAX_MODE_NR 16 -#define MAX_PX_NR 100 - -/* simplified xentrace record */ -struct rec { - uint64_t tsc; - int cpu; - unsigned char cx; - unsigned char irqs[4]; - unsigned int predicted; - unsigned int expected; - int px; -}; - -/********** FORWARD DECLARATION **********/ -static void show_help(void); -static void show_version(void); -static int load_file(char *fname); -static void do_digest(uint64_t start, uint64_t end, uint64_t scale); -static void do_breakevents(void); -static void do_count(void); -static void do_px_count(void); -static void do_maxmin(void); -static void do_average(void); -static void do_exp_ratio(void); -static void do_exp_pred(void); - -/********** GLOBAL VARIABLES **********/ -/* store simplified xentrace data */ -static struct rec *data; -static int64_t data_nr, data_cur; -/* store max cx state number and cpu number */ -static int max_cx_num = -1, max_cpu_num = -1; -static int px_freq_table[MAX_PX_NR]; -static int max_px_num = 0; - -static int is_menu_gov_enabled = 0; - -/* user specified translation unit */ -static uint64_t tsc2ms = 2793000UL; -static uint64_t tsc2us = 2793UL; -static uint64_t tsc2phase = 55800000UL; - -/* each cpu column width */ -static int width = 0; - -/* digest mode variables */ -static struct rec *evt[MAX_CPU_NR]; -static int evt_len[MAX_CPU_NR]; - -/* hand-crafted min() */ -static inline uint64_t min(uint64_t a, uint64_t b) -{ - return a < b ? a : b; -} - -static int is_px = 0; - -int main(int argc, char *argv[]) -{ - char *fname = NULL; - /* operation flags */ - int is_breakevents = 0; - int is_count = 0; - int is_maxmin = 0; - int is_average = 0; - int is_digest = 0; - int is_exp_ratio = 0; - int is_exp = 0; - uint64_t start_time = 0; - uint64_t time_scale = 0; - uint64_t end_time = 0; - - struct option long_options [] = { - /* short options are listed correspondingly */ - { "version", 0, NULL, 'v' }, - { "help", 0, NULL, 'h' }, - /* list Cx entires one by one */ - { "digest", 0, NULL, 'd' }, - /* ignored when digest is disabled */ - { "start", 1, NULL, 's' }, - { "end", 1, NULL, 'e' }, - { "scale", 1, NULL, 'l' }, - /* give summary about breakevents info */ - { "breakevents", 0, NULL, 'b' }, - { "count", 0, NULL, 'c' }, - { "average", 0, NULL, 'a' }, - /* list max/min residency for each Cx */ - { "maxmin", 0, NULL, 'm' }, - { "tsc2us", 1, NULL, 'u' }, - { "px", 0, NULL, 'p' }, - { "tsc2phase", 1, NULL, 'n' }, - { "exp-ratio", 0, NULL, 'z' }, - { "exp-pred", 0, NULL, 'x' }, - { NULL, 0, NULL, 0 }, - }; - - if ( argc == 1 ) { - show_help(); - exit(EXIT_SUCCESS); - } - while (1) { - int ch, opt_idx; - ch = getopt_long(argc, argv, "vhds:e:l:bcmau:pn:zx", - long_options, &opt_idx); - if (ch == -1) - break; - switch (ch) { - case 'v': - show_version(); - exit(EXIT_SUCCESS); - case 'h': - show_help(); - exit(EXIT_SUCCESS); - case 'p': - is_px = 1; - break; - case 'x': - is_exp = 1; - break; - case 'z': - is_exp_ratio = 1; - break; - case 'n': - tsc2phase = atoll(optarg); - if (tsc2phase <= 0) - tsc2phase = 55800000UL; - break; - case 'd': - is_digest = 1; - break; - case 's': - start_time = atoll(optarg); - break; - case 'e': - end_time = atoll(optarg); - break; - case 'l': - time_scale = atoll(optarg); - break; - case 'b': - is_breakevents = 1; - break; - case 'c': - is_count = 1; - break; - case 'm': - is_maxmin = 1; - break; - case 'a': - is_average = 1; - break; - case 'u': - tsc2us = atoll(optarg); - tsc2ms = tsc2us * 1000UL; - break; - case '?': - default: - show_help(); - exit(EXIT_FAILURE); - } - } - - if (argc - optind > 1) { - printf("Multiple file specified?\n"); - show_help(); - exit(EXIT_FAILURE); - } - fname = argv[optind]; - - if (load_file(fname)) - exit(EXIT_FAILURE); - - width = 10; - if (is_digest) { - /* if people not specify the time related number, - * use the default one from the record. - */ - if (!start_time) - start_time = data[0].tsc; - if (!end_time) - end_time = data[data_cur-1].tsc; - if (!time_scale) - time_scale = 10UL * tsc2ms; /* default: 10 ms */ - do_digest(start_time, end_time, time_scale); - } - - if (is_breakevents) - do_breakevents(); - - if (is_count && !is_px) - do_count(); - if (is_count && is_px) - do_px_count(); - - if (is_maxmin) - do_maxmin(); - - if (is_average) - do_average(); - - if (is_exp_ratio) - do_exp_ratio(); - - if (is_exp) - do_exp_pred(); - - exit(EXIT_SUCCESS); -} - -/* used for qsort() */ -/* sort by cpu first, then by tsc */ -static int data_cmp(const void *_a, const void *_b) -{ - struct rec *a = (struct rec *)_a; - struct rec *b = (struct rec *)_b; - if (a->cpu == b->cpu) - return a->tsc > b->tsc ? 1 : -1; - return a->cpu > b->cpu ? 1 : -1; -} - -/* load file and make them a list of records - * update these following variables: - * data, data_cur, data_nr - * max_cpu_num, max_cx_num - */ -#define LIST_PX 0 -static int load_file(char *fname) -{ - /* file descriptor for raw xentrace file */ - int fd; - /* current cpu during xentrace data parse */ - int cur_cpu = -1; - int i; - - fd = open(fname, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "file %s cannot open\n", fname); - return 1; - } - - /* the initial number is 1024, - * and when it overflows, this number doubles. - */ - data_nr = 1024; - data_cur = 0; - data = malloc(sizeof(struct rec) * data_nr); - if (!data) { - fprintf(stderr, "not enough memory\n"); - close(fd); - return 1; - } - - while (1) { - struct t_rec rec; - ssize_t ret, size; - - ret = read(fd, &rec, sizeof(uint32_t)); - if (!ret) - break; - if (ret != sizeof(uint32_t)) { - fprintf(stderr, "reading header error\n"); - break; - } - - size = 0; - if (rec.cycles_included) - size += sizeof(uint64_t); - size += sizeof(uint32_t) * rec.extra_u32; - - ret = read(fd, (char *)&rec + sizeof(uint32_t), size); - if (!ret && size) - break; - if (ret != size) { - fprintf(stderr, "reading data error\n"); - break; - } - - if (rec.event == 0x1f003) { - /* cpu change event */ - cur_cpu = 0; - if (rec.extra_u32 > 0) - cur_cpu = rec.u.nocycles.extra_u32[0]; - continue; - } else if (!rec.cycles_included || - (rec.event != TRC_PM_IDLE_ENTRY && - rec.event != TRC_PM_IDLE_EXIT && - rec.event != TRC_PM_FREQ_CHANGE)) { - /* we care about only idle events now */ - continue; - } - - /* add one record */ - if (data_cur == data_nr) { - data_nr <<= 1; - if (data_nr < 0) { - fprintf(stderr, "too many entries\n"); - close(fd); - return 1; - } - data = realloc(data, sizeof(struct rec) * data_nr); - if (!data) { - fprintf(stderr, "not enough memory\n"); - close(fd); - return 1; - } - } - data[data_cur].tsc = rec.u.cycles.cycles_hi; - data[data_cur].tsc <<= 32; - data[data_cur].tsc |= rec.u.cycles.cycles_lo; - data[data_cur].cpu = cur_cpu; - if (is_px) { - if (rec.event != TRC_PM_FREQ_CHANGE) - continue; - /* FREQ_CHANGE */ - if (rec.u.cycles.extra_u32[0] == - rec.u.cycles.extra_u32[1]) - continue; - data[data_cur].px = rec.u.cycles.extra_u32[1]; - for (i = 0; i < max_px_num; i++) - if (px_freq_table[i] == data[data_cur].px) - break; - if (i == max_px_num) - px_freq_table[max_px_num++] = data[data_cur].px; - } else { - if (rec.event == TRC_PM_IDLE_ENTRY) { - data[data_cur].cx = rec.u.cycles.extra_u32[0]; - if (rec.extra_u32 >= 4) { - data[data_cur].expected = rec.u.cycles.extra_u32[2]; - data[data_cur].predicted = rec.u.cycles.extra_u32[3]; - is_menu_gov_enabled = 1; - } else - is_menu_gov_enabled = 0; - } else if (rec.event == TRC_PM_IDLE_EXIT) { - /* IDLE_EXIT default to C0 */ - data[data_cur].cx = 0; - /* store the reasons why it exits */ - data[data_cur].irqs[0] = rec.u.cycles.extra_u32[2]; - data[data_cur].irqs[1] = rec.u.cycles.extra_u32[3]; - data[data_cur].irqs[2] = rec.u.cycles.extra_u32[4]; - data[data_cur].irqs[3] = rec.u.cycles.extra_u32[5]; - } else - continue; - /* update max info */ - if (data[data_cur].cx > max_cx_num) - max_cx_num = data[data_cur].cx; - } - - if (data[data_cur].cpu > max_cpu_num) - max_cpu_num = data[data_cur].cpu; - - data_cur++; - } - close(fd); - - /* sort data array according to TSC time line */ - qsort(data, data_cur, sizeof(struct rec), data_cmp); - - max_cpu_num++; - max_cx_num++; - - for (i = 0; i < max_cpu_num; i++) { - evt_len[i] = 0; - evt[i] = NULL; - } - for (i = data_cur-1; i >= 0; i--) { - evt[data[i].cpu] = data+i; - evt_len[data[i].cpu]++; - } -#if CHECK_DUP_CX - int xx, yy; - int err = 0; - printf("Checking %s...\n", fname); - for (xx = 0; xx < max_cpu_num; xx++) { - // printf("............ CPU %d .............\n", xx); - for (yy = 0; yy+1 < evt_len[xx]; yy++) - if ( evt[xx][yy].cx > 0 && evt[xx][yy+1].cx > 0) { - printf("same witht next one %"PRIu64" %d %d\n", - evt[xx][yy].tsc, evt[xx][yy].cpu, evt[xx][yy].cx); - err++; - } - } - exit(err); -#endif -#if LIST_PX - int x, y; - for (x = 0; x < max_cpu_num; x++) { - printf("CPU%d**************************************\n", x); - for (y = 0; y+1 < evt_len[x]; y++) { - printf("[%dHz]: phase: %d\n", - evt[x][y].px, - (int)((evt[x][y+1].tsc - evt[x][y].tsc)/tsc2phase)); - } - } -#endif - return 0; -} - -static void show_version(void) -{ - printf("gtracestat - (C) 2009-2011 Intel Corporation\n"); -} - -static void show_help(void) -{ - show_version(); - printf("gtracestat <trace.data> [-vhdselbcmau]\n"); - printf(" trace.data raw data got by 'xentrace -e 0x80f000 trace.dat'\n"); - printf(" -v / --version show version message\n"); - printf(" -h / --help show this message\n"); - printf(" -d / --digest digest mode, more variables to specify.\n"); - printf(" -s / --start <start_time> specify start time (only in digest mode)\n"); - printf(" -e / --end <end_time> specify end time (only in digest mode)\n"); - printf(" -l / --scale <scale> specify time scale (only in digest mode)\n"); - printf(" -b / --breakevents give breakevents summary info\n"); - printf(" -c / --count give count summary info\n"); - printf(" -a / --average give total/average residency info\n"); - printf(" -m / --maxmin show man/min residency summary info\n"); - printf(" -u / --tsc2us <tsc-per-us> specify how many tsc is a us unit\n"); - printf(" -p / --px operate on Px entries\n"); - printf(" -n / --tsc2phase <tsc-per-phase> specify how many tsc is a phase unit (only in px)\n"); - printf(" -z / --exp-ratio show the ratio of early break events\n"); - printf(" -x / --exp-pred show the ratio of expected / predicted in Cx entry\n"); -} - -static inline int len_of_number(uint64_t n) -{ - int l = 0; - do { - l++; - n /= 10; - } while (n); - return l; -} - -/* determine the cx at time t - * take advantage of evt and evt_len. - */ -static int determine_cx(int c, uint64_t t) -{ - int i; - - i = 0; - while (i < evt_len[c] && evt[c][i].tsc <= t) - i++; - /* if there are any events happening, - * it must be in a Cx state now. - */ - if (i) - return evt[c][i-1].cx; - /* look forward to see whether it will enter - * a Cx state, if so, it must be in C0 state. - * we can't determine a Cx state from exit event. - */ - if (i < evt_len[c] && evt[c][i].cx > 0) - return 0; - return -1; -} - -/* c - cpu - * t - start time - * s - scale - * cx_i - number of cx index - * cx_r - residency of each cx entry - */ -static int process(int c, uint64_t t, uint64_t s, int *cx_i, uint64_t *cx_r) -{ - int cx; - uint64_t len; - int i, n; - - cx = determine_cx(c, t); - i = 0; - while (i < evt_len[c] && evt[c][i].tsc < t) - i++; - n = 0; - if (cx >= 0 && i < evt_len[c]) { - cx_i[n] = cx; - cx_r[n] = evt[c][i].tsc - t; - if (cx_r[n]) - n++; - } - while (i < evt_len[c] && evt[c][i].tsc < t+s) { - /* we are now at [t, t+s) */ - cx = evt[c][i].cx; - len = min((i+1 < evt_len[c] ? evt[c][i+1].tsc : t+s), t+s) - - evt[c][i].tsc; - - cx_i[n] = cx; - cx_r[n] = len; - n++; - - i++; - } - - return n; -} - -static void nr_putchar(int nr, int ch) -{ - int i; - for (i = 0; i < nr; i++) - putchar(ch); -} - -#define MAX_INTERVAL_ENTRY 1000 -/* process period [start_time, start_time + time_scale) */ -static void single_digest(uint64_t start_time, uint64_t time_scale) -{ - int cpu; - int cx_i[MAX_CPU_NR][MAX_INTERVAL_ENTRY]; - uint64_t cx_r[MAX_CPU_NR][MAX_INTERVAL_ENTRY]; - int cx_n[MAX_CPU_NR]; - int max_n; - - memset(cx_i, 0, sizeof(int) * MAX_CPU_NR * MAX_INTERVAL_ENTRY); - memset(cx_r, 0, sizeof(uint64_t) * MAX_CPU_NR * MAX_INTERVAL_ENTRY); - memset(cx_n, 0, sizeof(int) * MAX_CPU_NR); - - max_n = 0; - for (cpu = 0; cpu < max_cpu_num; cpu++) { - cx_n[cpu] = process(cpu, start_time, time_scale, cx_i[cpu], cx_r[cpu]); - if (cx_n[cpu] > max_n) - max_n = cx_n[cpu]; - } - - /* means how many lines will be consumed */ - while (--max_n >= 0) { - for (cpu = 0; cpu < max_cpu_num; cpu++) { - if (cx_n[cpu] > 0) { - int i; - /* find the available cx index */ - for (i = 0; i < MAX_INTERVAL_ENTRY && cx_i[cpu][i] == -1; i++) - ; - if (i < MAX_INTERVAL_ENTRY) { - int len; - /* print it */ - len= printf("C%d,%"PRIu64".%d", cx_i[cpu][i], - cx_r[cpu][i]/tsc2ms, - (unsigned int)(cx_r[cpu][i]/(tsc2ms/10))%10); - nr_putchar(width-len, ' '); - - cx_i[cpu][i] = -1; - } else - nr_putchar(width, ' '); - - cx_n[cpu]--; - } else - nr_putchar(width, ' '); - } - nr_putchar(1, '\n'); - } -} - -static void do_digest(uint64_t start, uint64_t end, uint64_t scale) -{ - int i; - uint64_t ms = 0; - uint64_t delta_ms = scale / tsc2ms; - - for (i = 0; i < max_cpu_num; i++) { - int len = 0; - len = printf("CPU%d", i); - nr_putchar(width-len, ' '); - } - nr_putchar(1, '\n'); - while (start < end) { - /* print --- xxx ms --- line */ - int off = (max_cpu_num * width - len_of_number(ms) - 2)/2; - nr_putchar(off, '-'); - off += printf("%"PRIu64"ms", ms); - off += printf(" (%"PRIu64")", start); - nr_putchar(max_cpu_num * width-off, '-'); - nr_putchar(1, '\n'); - /* print each digest entries */ - single_digest(start, scale); - - start += scale; - ms += delta_ms; - } -} - -/* [min, max) */ -struct cond_rec { - uint64_t min; - uint64_t max; - uint64_t cnt; - uint64_t res; -}; - -static void cond_rec_inc(uint64_t cur, struct cond_rec *r) -{ - if (r->min <= cur && cur < r->max) { - r->cnt++; - r->res += cur; - } -} - -/* c - current cpu to scan - * cx - cx state to track - * a - conditonal array - * n - how many entries there are - */ -static void do_count_per_cpu(int c, int cx, struct cond_rec *a, int n) -{ - int i; - /* find Cx entry first */ - i = 0; - while (i < evt_len[c] && evt[c][i].cx == 0) - i++; - /* check evt[c][i] and evt[c][i+1] */ - while (i + 1 < evt_len[c]) { - if (evt[c][i].cx == cx) { - uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc; - int j; - /* check for each condition */ - for (j = 0; j < n; j++) - cond_rec_inc(len, a+j); - } - i++; - } -} - -static struct cond_rec *make_cond_rec(uint64_t *a, int n) -{ - int i; - struct cond_rec *t = malloc(sizeof(struct cond_rec) * (n+1)); - if (!t) - return NULL; - for (i = 0; i < n; i++) { - t[i].max = a[i]; - t[i+1].min = a[i]; - t[i].cnt = 0; - t[i].res = 0; - } - t[0].min = 0; - t[n].max = (uint64_t) -1; - t[n].cnt = 0; - t[n].res = 0; - - return t; -} - -static uint64_t max_res[MAX_CPU_NR][MAX_CX_NR]; -static uint64_t min_res[MAX_CPU_NR][MAX_CX_NR]; -static uint64_t max_tm[MAX_CPU_NR][MAX_CX_NR]; -static uint64_t min_tm[MAX_CPU_NR][MAX_CX_NR]; - -static void do_maxmin_per_cpu(int c) -{ - int i; - /* find Cx entry first */ - i = 0; - while (i < evt_len[c] && evt[c][i].cx == 0) - i++; - /* check evt[c][i] and evt[c][i+1] */ - while (i + 1 < evt_len[c]) { - int cx = evt[c][i].cx; - uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc; - if (len > max_res[c][cx]) { - max_res[c][cx] = len; - max_tm[c][cx] = evt[c][i].tsc; - } - if (len < min_res[c][cx]) { - min_res[c][cx] = len; - min_tm[c][cx] = evt[c][i].tsc; - } - i++; - } -} - -static void do_maxmin(void) -{ - int i, j; - /* init */ - for (i = 0; i < max_cpu_num; i++) - for (j = 0; j < max_cx_num; j++) { - max_res[i][j] = 0; - min_res[i][j] = (uint64_t) -1; - } - - for (i = 0; i < max_cpu_num; i++) - do_maxmin_per_cpu(i); - - for (i = 0; i < max_cpu_num; i++) { - printf("********* CPU%d *********\n", i); - for (j = 0; j < max_cx_num; j++) - if (max_res[i][j] == 0) - printf(" not found "); - else - printf("%7"PRIu64"us (%15"PRIu64") ", max_res[i][j]/tsc2us, max_tm[i][j]); - printf("\n"); - for (j = 0; j < max_cx_num; j++) - if (max_res[i][j] == 0) - printf(" not found "); - else - printf("%7"PRIu64"us (%15"PRIu64") ", min_res[i][j]/tsc2us, min_tm[i][j]); - printf("\n\n"); - } -} - -static void do_count(void) -{ - uint64_t scale[100] = { 50UL, 100UL, 200UL, 400UL, 800UL, 1000UL }; - int a; - int scale_len = 6; - int len = 0; - int i, j; - - printf("Please input the period: (Ctrl+D to quit)\n"); - printf("The default is: 50 100 200 400 800 1000\n" - "(unit is us, DO NOT specify ZERO as any entry, keep entries in INCREASING order.)\n"); - while (scanf("%d", &a) == 1) { - scale[len++] = a; - scale_len = len; - } - for (i = 0; i < scale_len; i++) - scale[i] = scale[i] * tsc2us; - - for (i = 0; i < max_cpu_num; i++) { - struct cond_rec *r[MAX_CX_NR]; - uint64_t sum[MAX_CX_NR]; - int k; - - printf("********** CPU%d *********\n", i); - for (j = 0; j < max_cx_num; j++) { - r[j] = make_cond_rec(scale, scale_len); - if (!r[j]) - continue; - do_count_per_cpu(i, j, r[j], scale_len+1); - - /* print */ - sum[j] = 0; - for (k = 0; k < scale_len+1; k++) - sum[j] += r[j][k].cnt; - if (sum[j] == 0) - sum[j] = 1; - } - printf(" "); - for (j = 0; j < max_cx_num; j++) - printf(" C%d ", j); - printf("\n"); - for (k = 0; k < scale_len+1; k++) { - if (k == scale_len) - printf("%5"PRIu64" us -> MAX us:", r[0][k].min/tsc2us); - else - printf("%5"PRIu64" us -> %5"PRIu64" us:", - r[0][k].min/tsc2us, r[0][k].max/tsc2us); - for (j = 0; j < max_cx_num; j++) - printf(" %10"PRIu64" (%5.2f%%)", - r[j][k].cnt, 100.0 * (double) r[j][k].cnt / (double)sum[j]); - printf("\n"); - } - for (j = 0; j < max_cx_num; j++) - free(r[j]); - } -} - -static void do_px_count_per_cpu(int c, int px, struct cond_rec *cond, int n) -{ - int i, j; - uint64_t len; - - i = 0; - while (i+1 < evt_len[c]) { - if (evt[c][i].px == px) { - len = evt[c][i+1].tsc - evt[c][i].tsc; - /* check each condition */ - for (j = 0; j < n; j++) - cond_rec_inc(len, cond+j); - } - i++; - } -} - -static void do_px_count(void) -{ - int a[100]; - uint64_t scale[100]; - int n, i, c, j; - - printf("Please input phases series: (Ctrl+D to quit)\n"); - printf("The default is 1, 2, 4, 8, 16, 32.\n"); - printf("Please be in increasing order.\n"); - scale[0] = tsc2phase; - scale[1] = 2 * tsc2phase; - scale[2] = 4 * tsc2phase; - scale[3] = 8 * tsc2phase; - scale[4] = 16 * tsc2phase; - scale[5] = 32 * tsc2phase; - n = 0; - while (scanf("%d", &a[n]) == 1) - n++; - if (n) { - for (i = 0; i < n; i++) - scale[i] = a[i] * tsc2phase; - } else - n = 6; - for (c = 0; c < max_cpu_num; c++) { - struct cond_rec *p[MAX_PX_NR]; - int k; - - printf("***** CPU%d *****\n", c); - for (i = 0; i < max_px_num; i++) { - p[i] = make_cond_rec(scale, n); - if (!p[i]) - continue; - do_px_count_per_cpu(c, px_freq_table[i], p[i], n+1); - } - /* print */ - nr_putchar(16, ' '); - for (j = 0; j < max_px_num; j++) - printf("P%d\t", px_freq_table[j]); - printf("\n"); - for (k = 0; k < n+1; k++) { - if (k == n) - printf("%5"PRIu64" -> MAX : ", p[0][k].min/tsc2phase); - else - printf("%5"PRIu64" -> %5"PRIu64": ", - p[0][k].min/tsc2phase, p[0][k].max/tsc2phase); - for (j = 0; j < max_px_num; j++) { - printf("%"PRIu64"\t", p[j][k].cnt); - } - printf("\n"); - } - printf("---\n"); - printf("Count: "); - for (j = 0; j < max_px_num; j++) { - int sum = 0; - for (k = 0; k < n+1; k++) { - sum += (int)p[j][k].cnt; - } - /* print count */ - printf("%d\t", sum); - } - printf("\nAverage: "); - for (j = 0; j < max_px_num; j++) { - int sum = 0; - int s_res = 0; - for (k = 0; k < n+1; k++) { - sum += (int)p[j][k].cnt; - s_res += (int)(p[j][k].res/tsc2phase); - } - /* print average */ - if (sum == 0) - sum = 1; - printf("%.1f\t", (double)s_res/(double)sum); - } - printf("\nTotal: "); - for (j = 0; j < max_px_num; j++) { - int s_res = 0; - for (k = 0; k < n+1; k++) { - s_res += (int)(p[j][k].res/tsc2phase); - } - /* print total */ - printf("%d\t", s_res); - } - printf("\n"); - } -} - -static void do_breakevents(void) -{ - int br[MAX_CPU_NR][257]; - float pc[MAX_CPU_NR][257]; - int i, j, k, l; - - memset(br, 0, sizeof(int) * MAX_CPU_NR * 257); - memset(pc, 0, sizeof(int) * MAX_CPU_NR * 257); - - for (i = 0; i < max_cpu_num; i++) { - int sum = 0; - for (j = 0; j < evt_len[i]; j++) { - if (evt[i][j].cx == 0) { - /* EXIT */ - /* collect breakevents information */ - int xx = 0; - for (k = 0; k < 4; k++) { - int irq = evt[i][j].irqs[k]; - if (irq) { - br[i][irq]++; - sum++; - xx++; - } - } - if (!xx) { - br[i][256]++; - sum++; - } - } - } - for (j = 0; j < 257; j++) - pc[i][j] = 100.0 * br[i][j]/sum; - } - /* print the results */ - width = 13; - printf(" "); - for (i = 0; i < max_cpu_num; i++) { - l = 0; - l += printf("CPU%d", i); - nr_putchar(width-l, ' '); - } - printf("\n"); - - for (j = 0; j < 257; j++) { - int n = 0; - for (i = 0; i < max_cpu_num; i++) - if (br[i][j]) - n++; - if (n) { - if (j == 256) - printf("[N/A] "); - else - printf("[%03x] ", j); - for (i = 0; i < max_cpu_num; i++) { - if (br[i][j]) { - l = 0; - l += printf("%.1f%%,%d ", pc[i][j], br[i][j]); - nr_putchar(width-l, ' '); - } else { - nr_putchar(width, ' '); - } - } - printf("\n"); - } - } -} - -static void do_average_per_cpu(int c) -{ - int i; - uint64_t tot[MAX_CX_NR] = { 0 }; - uint64_t cnt[MAX_CX_NR] = { 0 }; - uint64_t sum = 0; - - /* find Cx entry first */ - i = 0; - while (i < evt_len[c] && evt[c][i].cx == 0) - i++; - /* check evt[c][i] and evt[c][i+1] */ - while (i + 1 < evt_len[c]) { - uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc; - int cx = evt[c][i].cx; - tot[cx] += len; - cnt[cx]++; - sum += len; - i++; - } - /* prevent divide zero error */ - if (!sum) - sum = 1; - /* print */ - printf("CPU%d:\tResidency(ms)\t\tAvg Res(ms)\n", c); - for (i = 0; i < max_cx_num; i++) { - /* prevent divide zero error */ - if (!cnt[i]) - cnt[i] = 1; - printf(" C%d\t%"PRIu64"\t(%6.2f%%)\t%.2f\n", i, - tot[i]/tsc2ms, 100.0 * tot[i] / (double)sum, - (double)tot[i]/cnt[i]/tsc2ms ); - } - printf("\n"); -} - -static void do_average(void) -{ - int i; - - for (i = 0; i < max_cpu_num; i++) - do_average_per_cpu(i); -} - -static void do_exp_ratio_per_cpu(int c) -{ - int i; - uint64_t expected[MAX_CX_NR] = { 0 }, sum[MAX_CX_NR] = { 0 }; - - i = 0; - while (i < evt_len[c] && evt[c][i].cx == 0) - i++; - /* check evt[c][i] and evt[c][i+1] */ - while (i + 1 < evt_len[c]) { - uint64_t len; - int cx; - - if ((evt[c][i].cx == 0 && evt[c][i+1].cx == 0) || - (evt[c][i].cx > 0 && evt[c][i+1].cx > 0)) { - i++; - continue; - } - len = evt[c][i+1].tsc - evt[c][i].tsc; - cx = evt[c][i].cx; - if (cx > 0) { - if ((len/tsc2us) <= evt[c][i].expected) - expected[cx]++; - sum[cx]++; - } - - i++; - } - printf("********** CPU%d **********\n", c); - for (i = 1; i < max_cx_num; i++) { - if (sum[i] == 0) - printf("C%d\t0\t0\t00.00%%\n", i); - else - printf("C%d\t%"PRIu64"\t%"PRIu64"\t%4.2f%%\n", - i, expected[i], sum[i], 100.0 * (double)expected[i]/(double)sum[i]); - } -} - -static void do_exp_ratio(void) -{ - int i; - - if (!is_menu_gov_enabled) { - printf("The file seems doesn't consists the expected/predicted information.\n"); - return; - } - - printf("Cx\tearly\ttot\tratio(%%)\n"); - for (i = 0; i < max_cpu_num; i++) - do_exp_ratio_per_cpu(i); -} - -static void do_exp_pred_per_cpu(int c) -{ - int i; - uint64_t expected[MAX_CX_NR] = { 0 }, sum[MAX_CX_NR] = { 0 }; - - i = 0; - while (i < evt_len[c] && evt[c][i].cx == 0) - i++; - /* check evt[c][i] and evt[c][i+1] */ - while (i + 1 < evt_len[c]) { - int cx; - - if ((evt[c][i].cx == 0 && evt[c][i+1].cx == 0) || - (evt[c][i].cx > 0 && evt[c][i+1].cx > 0)) { - i++; - continue; - } - cx = evt[c][i].cx; - if (cx > 0) { - if (evt[c][i].expected <= evt[c][i].predicted) - expected[cx]++; - sum[cx]++; - } - - i++; - } - printf("********** CPU%d **********\n", c); - for (i = 1; i < max_cx_num; i++) { - if (sum[i] == 0) - printf("C%d\t0\t0\t00.00%%\n", i); - else - printf("C%d\t%"PRIu64"\t%"PRIu64"\t%4.2f%%\n", - i, expected[i], sum[i], 100.0 * (double)expected[i]/(double)sum[i]); - } -} - -static void do_exp_pred(void) -{ - int i; - - if (!is_menu_gov_enabled) { - printf("The file seems doesn't consists the expected/predicted information.\n"); - return; - } - - printf("Cx\texp\ttot\tratio(%%)\n"); - for (i = 0; i < max_cpu_num; i++) - do_exp_pred_per_cpu(i); -} - diff --git a/tools/misc/gtraceview.c b/tools/misc/gtraceview.c deleted file mode 100644 index 52190a5..0000000 --- a/tools/misc/gtraceview.c +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * gtraceview.c: list Cx events in a ncurse way to help find abnormal behaviour. - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <unistd.h> -#include <fcntl.h> -#include <inttypes.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <xenctrl.h> -#include <xen/trace.h> - -/* get curses header from configure */ -#include INCLUDE_CURSES_H - -/********** MACROS **********/ -#define MAX_CPU_NR 32 -#define MAX_MODE_NR 16 -#define MAX_STRING_LEN 1024 - -/********** STRUCTURE DEFINITIONS **********/ -enum { - FLAG_FUZZY = 0, - FLAG_LEVEL, - FLAG_EDGE, - FLAG_UNKNOWN, - NR_FLAGS -}; - -struct string { - int len; - char str[MAX_STRING_LEN+1]; -}; - -int num_of_cpus(void); -void string_nr_addch(struct string *str, int nr, char ch) -{ - int i; - for (i = 0; i < nr; i++) - str->str[str->len++] = ch; - str->str[str->len] = '\0'; -} - -int string_print(struct string *str, char *fmt, ...) -{ - va_list ap; - int l = 0; - - va_start(ap, fmt); - l = vsprintf(str->str + str->len, fmt, ap); - va_end(ap); - str->len += l; - str->str[str->len] = '\0'; - return l; -} - -struct cpu { - unsigned char cx; - // unsigned char cx_prev; - unsigned char flag; - unsigned char irqs[4]; - unsigned int expected; - unsigned int predicted; -}; - -struct state { - uint64_t tsc; - struct cpu cpu[MAX_CPU_NR]; -}; - -struct mode { - const char *name; - int offset; - int width; - int row; - int scroll_h; - struct state *state; - int state_nr; - uint64_t time_scale; - uint64_t start_time; - int cpu_bitmap[MAX_CPU_NR]; - int initialized; - int (*init)(void); - void (*show)(void); - void (*exit)(void); -}; - -/* simplified xentrace record */ -struct rec { - uint64_t tsc; - int cpu; - unsigned int expected; - unsigned int predicted; - unsigned char cx; - unsigned char irqs[4]; -}; - -/********** FORWARD DECLARATION **********/ -void show_help(void); -void show_version(void); -int load_file(char *fname); -void crt_init(void); -int mode_init(void); -void mode_show(void); - -/* event mode handler */ -int event_mode_init(void); -void event_mode_show(void); -void event_mode_exit(void); - -/* time mode handler */ -int time_mode_init(void); -int time_mode_rebuild(uint64_t start_time, uint64_t time_scale); - -/********** GLOBAL VARIABLES **********/ -/* store simplified xentrace data */ -struct rec *data; -int64_t data_nr, data_cur; -/* store max cx state number and cpu number */ -int max_cx_num = -1, max_cpu_num = -1; -int is_irq_enabled = -1; -int is_menu_gov_enabled = -1; -int is_link = 0; -uint64_t tsc2us = 2793UL; - -struct rec *data_evt; -struct rec *evt[MAX_CPU_NR]; -int evt_len[MAX_CPU_NR]; - -int cur_row = 0; -struct mode modes[] = { - { - .name = "Event", - .init = event_mode_init, - .show = event_mode_show, - .exit = event_mode_exit, - }, - { - .name = "Time", - .init = time_mode_init, - /* use the same show and exit with event mode */ - .show = event_mode_show, - .exit = event_mode_exit, - }, -}; -struct mode *this = NULL; - -/* hand-crafted min() */ -static inline int min(int a, int b) -{ - return a < b ? a : b; -} - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -void choose_cpus(void); -void help_screen(void); -int main(int argc, char *argv[]) -{ - char *fname = NULL; - int arg; - int quit = 0; - uint64_t s_time = 0; - uint64_t last_tsc = 0; - - for (arg = 1; arg < argc; arg++) { - if (!strcmp(argv[arg], "--version")) { - show_version(); - exit(EXIT_SUCCESS); - } else if (!strcmp(argv[arg], "--help")) { - show_help(); - exit(EXIT_SUCCESS); - } else { - /* assume it's a file */ - fname = argv[arg]; - break; - } - } - - if (!fname) { - show_help(); - exit(EXIT_FAILURE); - } - - if (load_file(fname)) - exit(EXIT_FAILURE); - - if (!data_cur) { - fprintf(stderr, "file %s doesn't contain any valid record\n", fname); - exit(EXIT_FAILURE); - } - - if (mode_init()) - exit(EXIT_FAILURE); - - crt_init(); - - cur_row = 1; - this = &modes[0]; - while (!quit) { - int ch; - - clear(); - this->show(); - ch = getch(); - switch (ch) { - case '!': - is_link = !is_link; - break; - case 'u': - move(LINES-1, 0); - clrtoeol(); - printw("us = ? TSCs (default: 2793):"); - echo(); - curs_set(1); - scanw("%"PRIu64, &tsc2us); - curs_set(0); - noecho(); - if (tsc2us <= 0) - tsc2us = 2793UL; - break; - case '/': - move(LINES-1, 0); - clrtoeol(); - printw("Input start time:"); - echo(); - curs_set(1); - scanw("%"PRIu64, &s_time); - curs_set(0); - noecho(); - if (s_time >= this->state[0].tsc && - s_time <= this->state[this->state_nr-1].tsc) { - int i = 0; - while (i < this->state_nr && - this->state[i].tsc < s_time) - i++; - this->row = i; - cur_row = 1; - } - break; - case '+': - if (!strcmp(this->name, "Time")) { - this->time_scale -= this->time_scale/10; - this->start_time = this->state[this->row+cur_row-1].tsc - (cur_row-1)*this->time_scale; - if (this->start_time < data[0].tsc) - this->start_time = data[0].tsc; - time_mode_rebuild(this->start_time, this->time_scale); - } - break; - case '-': - if (!strcmp(this->name, "Time")) { - this->time_scale += this->time_scale/10; - this->start_time = this->state[this->row+cur_row-1].tsc - (cur_row-1)*this->time_scale; - if (this->start_time < data[0].tsc) - this->start_time = data[0].tsc; - time_mode_rebuild(this->start_time, this->time_scale); - } - break; - case KEY_RESIZE: - break; - case KEY_UP: - if (--cur_row < 1) { - cur_row = 1; - if (--this->row < 0) - this->row = 0; - } - break; - case KEY_DOWN: - if (++cur_row > LINES-2) { - cur_row = LINES-2; - this->row = min(this->state_nr-LINES+2, this->row+1); - } - break; - case KEY_LEFT: - this->scroll_h -= 3; - if (this->scroll_h < 0) - this->scroll_h = 0; - break; - case KEY_RIGHT: - this->scroll_h += 3; - if (this->scroll_h >= this->width*num_of_cpus()) - this->scroll_h = this->width*num_of_cpus(); - break; - case KEY_HOME: - cur_row = 1; - this->row = 0; - break; - case KEY_END: - cur_row = LINES-2; - this->row = this->state_nr-LINES+2; - break; - case KEY_NPAGE: - this->row = min(this->state_nr-LINES+2, this->row+20); - break; - case KEY_PPAGE: - if (this->row >= 20) - this->row -= 20; - break; - case KEY_F(2): - /* change to another mode */ - if (is_link) - last_tsc = this->state[this->row+cur_row-1].tsc; - - if (this == &modes[sizeof(modes)/sizeof(modes[0])-1]) - this = &modes[0]; - else - this++; - clear(); - if (is_link) { - if (!strcmp(this->name, "Time")) { - this->start_time = last_tsc - (cur_row-1)*this->time_scale; - if (this->start_time < data[0].tsc) - this->start_time = data[0].tsc; - time_mode_rebuild(this->start_time, this->time_scale); - } else if (!strcmp(this->name, "Event")) { - int x; - for (x = 0; x < this->state_nr && this->state[x].tsc < last_tsc; x++) - ; - this->row = x-(cur_row-1); - } - } - break; - case KEY_F(3): - if (!strcmp(this->name, "Time")) { - /* only meaningful in Time mode */ - move(LINES-1, 0); - clrtoeol(); - printw("Input time scale and start time:"); - echo(); - curs_set(1); - scanw("%"PRIu64" %"PRIu64, - &this->time_scale, &this->start_time); - curs_set(0); - noecho(); - time_mode_rebuild(this->start_time, - this->time_scale); - } - break; - case KEY_F(4): - /* quit */ - quit = 1; - break; - case KEY_F(5): - /* choose which CPUs to display */ - choose_cpus(); - break; - case 'h': - help_screen(); - break; - } - } - - exit(EXIT_SUCCESS); -} -/* used for qsort() */ -static int evt_data_cmp(const void *_a, const void *_b) -{ - struct rec *a = (struct rec *)_a; - struct rec *b = (struct rec *)_b; - if (a->cpu == b->cpu) - return a->tsc > b->tsc ? 1 : -1; - return a->cpu > b->cpu ? 1 : -1; -} - -static int data_cmp(const void *_a, const void *_b) -{ - struct rec *a = (struct rec *)_a; - struct rec *b = (struct rec *)_b; - return a->tsc > b->tsc ? 1 : -1; -} - -/* load file and make them a list of records - * update these following variables: - * data, data_cur, data_nr - * max_cpu_num, max_cx_num - */ -int load_file(char *fname) -{ - /* file descriptor for raw xentrace file */ - int fd; - /* current cpu during xentrace data parse */ - int cur_cpu = -1; - int i; - - fd = open(fname, O_RDONLY); - if (fd < 0) { - fprintf(stderr, "file %s cannot open\n", fname); - return 1; - } - - /* the initial number is 1024, - * and when it overflows, this number doubles. - */ - data_nr = 1024; - data_cur = 0; - data = malloc(sizeof(struct rec) * data_nr); - if (!data) { - fprintf(stderr, "not enough memory\n"); - close(fd); - return 1; - } - - while (1) { - struct t_rec rec; - ssize_t ret, size; - - ret = read(fd, &rec, sizeof(uint32_t)); - if (!ret) - break; - if (ret != sizeof(uint32_t)) { - fprintf(stderr, "reading header error\n"); - break; - } - - size = 0; - if (rec.cycles_included) - size += sizeof(uint64_t); - size += sizeof(uint32_t) * rec.extra_u32; - - ret = read(fd, (char *)&rec + sizeof(uint32_t), size); - if (!ret && size) - break; - if (ret != size) { - fprintf(stderr, "reading data error\n"); - break; - } - - if (rec.event == 0x1f003) { - /* cpu change event */ - cur_cpu = 0; - if (rec.extra_u32 > 0) - cur_cpu = rec.u.nocycles.extra_u32[0]; - continue; - } else if (!rec.cycles_included || - (rec.event != TRC_PM_IDLE_ENTRY && - rec.event != TRC_PM_IDLE_EXIT && - rec.event != TRC_PM_FREQ_CHANGE)) { - continue; - } - - /* add one record */ - if (data_cur == data_nr) { - data_nr <<= 1; - if (data_nr < 0) { - fprintf(stderr, "too many entries\n"); - close(fd); - return 1; - } - data = realloc(data, sizeof(struct rec) * data_nr); - if (!data) { - fprintf(stderr, "not enough memory\n"); - close(fd); - return 1; - } - } - data[data_cur].tsc = rec.u.cycles.cycles_hi; - data[data_cur].tsc <<= 32; - data[data_cur].tsc |= rec.u.cycles.cycles_lo; - data[data_cur].cpu = cur_cpu; - /* extra_u32[1] is omitted, as it's pm ticks. */ - if (rec.event == TRC_PM_IDLE_ENTRY) { - data[data_cur].cx = rec.u.cycles.extra_u32[0]; - if (rec.extra_u32 >= 4) { - data[data_cur].expected = rec.u.cycles.extra_u32[2]; - data[data_cur].predicted = rec.u.cycles.extra_u32[3]; - is_menu_gov_enabled = 1; - } else - is_menu_gov_enabled = 0; - } else if (rec.event == TRC_PM_IDLE_EXIT) { - /* IDLE_EXIT default to C0 */ - data[data_cur].cx = 0; - /* store the reasons why it exits */ - if (rec.extra_u32 == 6) { - data[data_cur].irqs[0] = rec.u.cycles.extra_u32[2]; - data[data_cur].irqs[1] = rec.u.cycles.extra_u32[3]; - data[data_cur].irqs[2] = rec.u.cycles.extra_u32[4]; - data[data_cur].irqs[3] = rec.u.cycles.extra_u32[5]; - is_irq_enabled = 1; - } else - is_irq_enabled = 0; - } else { - /* FREQ CHANGE */ - } - - /* update max info */ - if (data[data_cur].cx > max_cx_num) - max_cx_num = data[data_cur].cx; - if (data[data_cur].cpu > max_cpu_num) - max_cpu_num = data[data_cur].cpu; - - data_cur++; - } - close(fd); - - data_evt = malloc(sizeof(struct rec) * data_cur); - memcpy(data_evt, data, sizeof(struct rec) * data_cur); - - qsort(data_evt, data_cur, sizeof(struct rec), evt_data_cmp); - for (i = 0; i < max_cpu_num; i++) { - evt_len[i] = 0; - evt[i] = NULL; - } - for (i = data_cur-1; i >= 0; i--) { - evt[data_evt[i].cpu] = data_evt+i; - evt_len[data_evt[i].cpu]++; - } - - /* sort data array according to TSC time line */ - qsort(data, data_cur, sizeof(struct rec), data_cmp); - - max_cpu_num++; - max_cx_num++; - - return 0; -} - -void show_version(void) -{ - printf("gtraceview - (C) 2009 Intel Corporation\n"); -} - -void show_help(void) -{ - show_version(); - printf("gtraceview <trace.data> [--version] [--help]\n"); - printf(" trace.data raw data got by " - "'xentrace -e 0x80f000 trace.dat'\n"); - printf(" --version show version information\n"); - printf(" --help show this message\n"); - printf("For more help messages, please press 'h' in the window\n"); -} - -void crt_done(void) -{ - curs_set(1); - endwin(); -} - -void help_screen(void) -{ - clear(); - mvprintw(0, 0, " HELP SCREEN"); - mvprintw(1, 0, "1. LEFT and RIGHT arrow key to move off-screen outputs"); - mvprintw(2, 0, "2. UP and DOWN arrow key to move the highlighted line"); - mvprintw(3, 0, "3. F2 to switch between Event and Time mode"); - mvprintw(4, 0, "4. '/' to search the TSC stamp"); - mvprintw(5, 0, "5. '+' to zoom in and '-' to zoom out"); - mvprintw(6, 0, "6. F3 to set start time and time manually"); - mvprintw(7, 0, "7. F4 to quit"); - mvprintw(8, 0, "8. F5 to select which CPUs we want to see"); - mvprintw(9, 0, "9. Irq exit reason shown on Cx exit record (patch needed)"); - mvprintw(10, 0, "10. Menu governor criteria shown on bottom line (patch needed)"); - mvprintw(11, 0, "11. PAGEDOWN, PAGEUP, HOME and END to navigate"); - mvprintw(12, 0, "12. 'h' to show this screen"); - mvprintw(13, 0, "13. 'u' to edit how many TSCs is a us unit"); - - mvprintw(LINES-1, 0, "Press any key to continue..."); - getch(); -} - -void crt_init(void) -{ - char *term; - - initscr(); - noecho(); - nonl(); - intrflush(stdscr, false); - keypad(stdscr, true); - curs_set(0); - /* hook exit() */ - atexit(crt_done); - /* we love colorful screens :-) */ - start_color(); - init_pair(1, COLOR_BLACK, COLOR_CYAN); - init_pair(2, COLOR_BLACK, COLOR_GREEN); - init_pair(3, COLOR_BLACK, COLOR_RED); - - /* some term tunings */ - term = getenv("TERM"); - if (!strcmp(term, "xterm") || - !strcmp(term, "xterm-color") || - !strcmp(term, "vt220")) { - define_key("\033[1~", KEY_HOME); - define_key("\033[4~", KEY_END); - define_key("\033OP", KEY_F(1)); - define_key("\033OQ", KEY_F(2)); - define_key("\033OR", KEY_F(3)); - define_key("\033OS", KEY_F(4)); - define_key("\033[11~", KEY_F(1)); - define_key("\033[12~", KEY_F(2)); - define_key("\033[13~", KEY_F(3)); - define_key("\033[14~", KEY_F(4)); - define_key("\033[[D", KEY_LEFT); - } -} - -void nr_addch(int nr, int ch) -{ - int i; - int y, x; - getyx(stdscr, y, x); - for (i = 0; i < nr; i++) { - if (x == COLS-1) - break; - addch(ch); - } -} - -int event_mode_init(void) -{ - int i, j; - struct state *state; - int index; - struct cpu cur_state[MAX_CPU_NR]; - - if (this->initialized) - free(this->state); - state = malloc(sizeof(struct state) * data_cur); - if (!state) - return 1; - this->state = state; - this->row = 0; - this->width = 9; - this->offset = 33; - this->scroll_h = 0; - - /* otherwise, respect cpu_bitmap[] */ - if (!this->initialized) { - this->initialized = 1; - for (i = 0; i < max_cpu_num; i++) - this->cpu_bitmap[i] = 1; - } - - for (i = 0; i < max_cpu_num; i++) - if (this->cpu_bitmap[i]) - cur_state[i].flag = FLAG_UNKNOWN; - - for (i = 0, index = 0; i < data_cur; i++) { - /* data[i] */ - int cpu = data[i].cpu; - if (cpu < 0) - continue; - if (!this->cpu_bitmap[cpu]) - continue; - - /* TODO: use the same structure */ - /* copy cx, expected, predicted and irqs */ - cur_state[cpu].cx = data[i].cx; - cur_state[cpu].expected = data[i].expected; - cur_state[cpu].predicted = data[i].predicted; - memcpy(cur_state[cpu].irqs, data[i].irqs, - sizeof(unsigned char) * 4); - /* as long as it comes here, - * it means that we have an event. - */ - cur_state[cpu].flag = FLAG_EDGE; - - state[index].tsc = data[i].tsc; - for (j = 0; j < max_cpu_num; j++) { - if (!this->cpu_bitmap[j]) - continue; - - /* copy cx, irqs and flags */ - state[index].cpu[j].cx = cur_state[j].cx; - state[index].cpu[j].expected = cur_state[j].expected; - state[index].cpu[j].predicted = cur_state[j].predicted; - memcpy(state[index].cpu[j].irqs, cur_state[j].irqs, - sizeof(unsigned char) * 4); - state[index].cpu[j].flag = cur_state[j].flag; - - /* chage flag in cur_state accordingly */ - if (cur_state[j].flag == FLAG_EDGE) - cur_state[j].flag = FLAG_LEVEL; - } - index++; - } - - this->state_nr = index; - return 0; -} - -static inline int len_of_number(uint64_t n) -{ - int l = 0; - if (!n) - return 1; - do { - l++; - n /= 10; - } while (n); - return l; -} - -static inline void display_number(uint64_t n, int l) -{ - static char sym[] = { ' ', 'K', 'M', 'G', 'T' }; - int nr = 0; - - if (len_of_number(n) <= l) { - nr_addch(l-len_of_number(n), ' '); - printw("%"PRIu64, n); - return; - } - do { - n /= 1000UL; - nr++; - } while (len_of_number(n) > l-1); - nr_addch(l-1-len_of_number(n), ' '); - printw("%"PRIu64, n); - nr_addch(1, sym[nr]); -} - -void draw_cpu_state(struct string *s, struct cpu *c, int width) -{ - int cx = c->cx; - int flag = c->flag; - - switch (flag) { - case FLAG_FUZZY: - string_nr_addch(s, max_cx_num, '#'); - string_nr_addch(s, width-max_cx_num, ' '); - break; - case FLAG_UNKNOWN: - string_nr_addch(s, 1, '?'); - string_nr_addch(s, width-1, ' '); - break; - case FLAG_LEVEL: - string_nr_addch(s, cx, ' '); - string_nr_addch(s, 1, '|'); - string_nr_addch(s, width-1-cx, ' '); - break; - case FLAG_EDGE: - if (cx > 0) { - /* ENTRY */ - string_nr_addch(s, 1, '>'); - string_nr_addch(s, cx-1, '-'); - string_nr_addch(s, 1, '+'); - string_nr_addch(s, width-cx-1, ' '); - } else { - /* EXIT */ - string_nr_addch(s, 1, '<'); - if (is_irq_enabled == 1) { - int k, len = 0; - for (k = 0; k < 4; k++) { - unsigned char irq = c->irqs[k]; - if (irq) { - string_print(s, "%02x", irq); - len += 2; - } - } - if (len > 0) - string_nr_addch(s, width-len-1, ' '); - else { - string_print(s, "noirq"); - string_nr_addch(s, width-1-5, ' '); - } - } else { - string_nr_addch(s, 1, '-'); - string_nr_addch(s, width-2, ' '); - } - } - break; - } -} - -void event_mode_show(void) -{ - struct state *state = this->state; - struct string s; - int idx = this->row; - int idx_hl = 0; - int i, j, l; - - /* draw headline */ - s.len = 0; - move(0, 0); - attron(COLOR_PAIR(2)); - nr_addch(this->offset, ' '); - for (i = 0; i < max_cpu_num; i++) { - if (this->cpu_bitmap[i]) { - string_print(&s, "CPU%d", i); - string_nr_addch(&s, this->width-len_of_number(i)-3, ' '); - } - } - mvaddnstr(0, this->offset, s.str+this->scroll_h, - MIN(s.len-this->scroll_h, this->width*num_of_cpus())); - attroff(COLOR_PAIR(2)); - - /* draw body */ - for (i = 1; i < LINES-1; i++, idx++) { - move(i, 0); - /* highlight the current row */ - if (i == cur_row) { - attron(COLOR_PAIR(1)); - idx_hl = idx; - } - - if (idx >= this->state_nr) { - /* do not show this line */ - nr_addch(this->offset+this->width*num_of_cpus(), ' '); - } else { - if (!strcmp(this->name, "Event")) { - uint64_t delta = 0; - if (idx) - delta = (state[idx].tsc - state[idx-1].tsc)/tsc2us; - printw("%20"PRIu64"(", state[idx].tsc); - display_number(delta, 8); - printw("us) "); - } else if (!strcmp(this->name, "Time")) { - printw("%20"PRIu64" ", state[idx].tsc); - } - - s.len = 0; - for (j = 0; j < max_cpu_num; j++) { - /* draw cpu state */ - if (this->cpu_bitmap[j]) - draw_cpu_state(&s, &state[idx].cpu[j], this->width); - } - /* draw the line accordingly */ - mvaddnstr(i, this->offset, s.str+this->scroll_h, - MIN(s.len-this->scroll_h, this->width*num_of_cpus())); - } - /* pair of the highlight logics */ - if (i == cur_row) - attroff(COLOR_PAIR(1)); - } - - /* draw tail line */ - attron(COLOR_PAIR(2)); - s.len = 0; - l = 0; - l += string_print(&s, "%s Mode [%sLINKED]", this->name, is_link ? "" : "NOT "); - if (!strcmp(this->name, "Time")) { -#if 0 - l += string_print(&s, " [%"PRIu64":%"PRIu64"]", - this->start_time, this->time_scale); -#endif - l += string_print(&s, " [%"PRIu64"]", - this->time_scale); - } - if (is_menu_gov_enabled == 1) { - for (i = 0; i < max_cpu_num; i++) { - if (this->cpu_bitmap[i] && - state[idx_hl].cpu[i].flag == FLAG_EDGE && - state[idx_hl].cpu[i].cx > 0) - l += string_print(&s, " (CPU%d,%lu,%lu)", - i, - state[idx_hl].cpu[i].expected, - state[idx_hl].cpu[i].predicted); - } - } - /* add cx exit residency info */ - for (i = 0; i < max_cpu_num; i++) { - if (this->cpu_bitmap[i] && - state[idx_hl].cpu[i].flag == FLAG_EDGE && - state[idx_hl].cpu[i].cx == 0) { - uint64_t tsc = state[idx_hl].tsc; - int k; - - k = 0; - while (k < evt_len[i] && - evt[i][k].tsc < tsc) - k++; - k--; - if (k >= 0 && k+1 < evt_len[i] && evt[i][k].cx > 0) { - l += string_print(&s, " (CPU%d, %"PRIu64"us)", - i, - (evt[i][k+1].tsc - evt[i][k].tsc)/tsc2us); - } - } - } - - string_nr_addch(&s, this->offset+this->width*num_of_cpus()-l, ' '); - mvaddstr(LINES-1, 0, s.str); - attroff(COLOR_PAIR(2)); - refresh(); -} - -void event_mode_exit(void) -{ - free(this->state); - this->initialized = 0; -} - -void mode_exit(void) -{ - int nr = sizeof(modes)/sizeof(modes[0]); - int i; - - for (i = 0; i < nr; i++) { - this = &modes[i]; - if (this->initialized) - this->exit(); - } -} - -int mode_init(void) -{ - int nr = sizeof(modes)/sizeof(modes[0]); - int i, r = 0; - - for (i = 0; i < nr; i++) { - this = &modes[i]; - this->initialized = 0; - r += this->init(); - } - - this = &modes[0]; - - /* hook into exit */ - atexit(mode_exit); - - return r; -} - -int time_mode_rebuild(uint64_t start_time, uint64_t time_scale) -{ - int i, j; - struct cpu cur_state[MAX_CPU_NR]; - uint64_t tsc = start_time; - struct state *state; - uint64_t number, temp = 0; - int state_cur = 0; - - for (i = 0; i < max_cpu_num; i++) - cur_state[i].flag = FLAG_UNKNOWN; - - /* allocate spaces, it may be huge... */ - if (time_scale) - temp = (data[data_cur-1].tsc - start_time)/time_scale; - number = 10000UL; - if (temp < number) - number = temp; - number += 2; - state = malloc(sizeof(struct state) * number); - if (!state) - return 1; - free(this->state); - this->state = state; - this->width = 9; - this->row = 0; - - /* determine the current Cx state */ - /* check [data[0].tsc, tsc) */ - i = 0; - while (i < data_cur && data[i].tsc < tsc) { - int cpu = data[i].cpu; - cur_state[cpu].cx = data[i].cx; - cur_state[cpu].flag = FLAG_LEVEL; - i++; - } - while (i < data_cur && state_cur < number) { - int num[MAX_CPU_NR]; - int last_idx[MAX_CPU_NR]; - -#if 0 - printf("XXXXX %d tsc: %"PRIu64" data[i].tsc: %"PRIu64"\n", - i, tsc, data[i].tsc); -#endif - /* ensure they are zero */ - memset(num, 0, sizeof(int) * MAX_CPU_NR); - memset(last_idx, 0, sizeof(int) * MAX_CPU_NR); - - /* check [tsc, tsc+time_scale) */ - while (i < data_cur && data[i].tsc < tsc+time_scale) { - int cpu = data[i].cpu; - num[cpu]++; - last_idx[cpu] = i; - i++; - } - /* TODO */ - if (i >= data_cur) - break; - for (j = 0; j < max_cpu_num; j++) { - if (num[j] == 1) { - /* only one event, it's an edge*/ - cur_state[j].cx = data[last_idx[j]].cx; - cur_state[j].flag = FLAG_EDGE; - } else if (num[j] > 1) { - /* more than one event, it's fuzzy */ - cur_state[j].cx = data[last_idx[j]].cx; - cur_state[j].flag = FLAG_FUZZY; - } else if (cur_state[j].flag == FLAG_FUZZY) { - /* no event, fuzzy state can't be passed down - * notice that cx is set in the fuzzy state, - * it's not changed here afterwards. - */ - cur_state[j].flag = FLAG_LEVEL; - } - } - - /* copy tsc */ - state[state_cur].tsc = tsc; - for (j = 0; j < max_cpu_num; j++) { - /* copy cx and flag */ - state[state_cur].cpu[j].cx = cur_state[j].cx; - state[state_cur].cpu[j].flag = cur_state[j].flag; - - /* update flag in cur_state */ - if (cur_state[j].flag == FLAG_EDGE) { - cur_state[j].flag = FLAG_LEVEL; - if (cur_state[j].cx == 0) { - /* EXIT */ - /* copy irqs conditionally */ - memcpy(state[state_cur].cpu[j].irqs, - data[last_idx[j]].irqs, - sizeof(unsigned char) * 4); - } else { - /* ENTRY */ - state[state_cur].cpu[j].expected = - data[last_idx[j]].expected; - state[state_cur].cpu[j].predicted = - data[last_idx[j]].predicted; - } - } - } - state_cur++; - tsc += time_scale; - } - this->state_nr = state_cur; - this->row = 0; - - return 0; -} - -int time_mode_init(void) -{ - int i; - this->offset = 21; - this->scroll_h = 0; - this->time_scale = (data[data_cur-1].tsc -data[0].tsc)/10000UL; - this->start_time = data[0].tsc; - for (i = 0; i < max_cpu_num; i++) - this->cpu_bitmap[i] = 1; - return time_mode_rebuild(this->start_time, - this->time_scale); -} - -void choose_cpus(void) -{ - int i; - int temp_row = 1; - int ch; - - clear(); - mvprintw(0, 0, "How many CPUs to track? Press space to toggle. Press 'q' or 'Q' to quit."); - - while (1) { - for (i = 0; i < max_cpu_num; i++) { - if (temp_row == i+1) - attron(COLOR_PAIR(2)); - mvprintw(i+1, 0, "[%s] CPU%d", this->cpu_bitmap[i] ? "x" : " ", i); - if (temp_row == i+1) - attroff(COLOR_PAIR(2)); - } - ch = getch(); - switch (ch) { - case KEY_UP: - if (--temp_row < 1) - temp_row = 1; - break; - case KEY_DOWN: - if (++temp_row > max_cpu_num) - temp_row = max_cpu_num; - break; - case ' ': - this->cpu_bitmap[temp_row-1] = !this->cpu_bitmap[temp_row-1]; - break; - case 'q': - case 'Q': - if (num_of_cpus() >= 1) { - if (!strcmp(this->name, "Event")) - this->init(); - return; - } - /* fallthrough */ - case KEY_F(4): - exit(EXIT_SUCCESS); - } - } -} - -int num_of_cpus(void) -{ - int i, nr = 0; - for (i = 0; i < max_cpu_num; i++) - if (this->cpu_bitmap[i]) - nr++; - return nr; -} - -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |