debuggers.hg

annotate tools/misc/gtracestat.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents 902f4ae65123
children
rev   line source
keir@19906 1 /*
keir@19906 2 * gtracestat.c: list the statistics information for a dumped xentrace file.
keir@19906 3 * Copyright (c) 2009, Intel Corporation.
keir@19906 4 *
keir@19906 5 * This program is free software; you can redistribute it and/or modify it
keir@19906 6 * under the terms and conditions of the GNU General Public License,
keir@19906 7 * version 2, as published by the Free Software Foundation.
keir@19906 8 *
keir@19906 9 * This program is distributed in the hope it will be useful, but WITHOUT
keir@19906 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
keir@19906 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
keir@19906 12 * more details.
keir@19906 13 *
keir@19906 14 * You should have received a copy of the GNU General Public License along with
keir@19906 15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
keir@19906 16 * Place - Suite 330, Boston, MA 02111-1307 USA.
keir@19906 17 */
keir@19906 18
keir@19906 19 #include <stdio.h>
keir@19906 20 #include <stdlib.h>
keir@19906 21 #include <string.h>
keir@19906 22 #include <unistd.h>
keir@19906 23 #include <fcntl.h>
keir@19906 24 #include <getopt.h>
keir@19906 25 #include <inttypes.h>
keir@19906 26 #include <sys/time.h>
keir@19906 27 #include <sys/types.h>
keir@19906 28 #include <sys/stat.h>
keir@19906 29
keir@19906 30 #include <xenctrl.h>
keir@19906 31 #include <xen/trace.h>
keir@19906 32
keir@19906 33 #define CHECK_DUP_CX 0
keir@19906 34
keir@19906 35 /********** MACROS **********/
keir@19906 36 #define MAX_CPU_NR 32
keir@19906 37 #define MAX_CX_NR 8
keir@19906 38 #define MAX_MODE_NR 16
keir@19906 39 #define MAX_PX_NR 100
keir@19906 40
keir@19906 41 /* simplified xentrace record */
keir@19906 42 struct rec {
keir@19906 43 uint64_t tsc;
keir@19906 44 int cpu;
keir@19906 45 unsigned char cx;
keir@19906 46 unsigned char irqs[4];
keir@19906 47 unsigned int predicted;
keir@19906 48 unsigned int expected;
keir@19906 49 int px;
keir@19906 50 };
keir@19906 51
keir@19906 52 /********** FORWARD DECLARATION **********/
keir@19906 53 void show_help(void);
keir@19906 54 void show_version(void);
keir@19906 55 int load_file(char *fname);
keir@19906 56 void do_digest(uint64_t start, uint64_t end, uint64_t scale);
keir@19906 57 void do_breakevents(void);
keir@19906 58 void do_count(void);
keir@19906 59 void do_px_count(void);
keir@19906 60 void do_maxmin(void);
keir@19906 61 void do_average(void);
keir@19906 62 void do_cstate(uint64_t start, uint64_t end);
keir@19906 63 void do_exp_ratio(void);
keir@19906 64 void do_exp_pred(void);
keir@19906 65
keir@19906 66 /********** GLOBAL VARIABLES **********/
keir@19906 67 /* store simplified xentrace data */
keir@19906 68 struct rec *data;
keir@19906 69 int64_t data_nr, data_cur;
keir@19906 70 /* store max cx state number and cpu number */
keir@19906 71 int max_cx_num = -1, max_cpu_num = -1;
keir@19906 72 int px_freq_table[MAX_PX_NR];
keir@19906 73 int max_px_num = 0;
keir@19906 74
keir@19906 75 int is_menu_gov_enabled = 0;
keir@19906 76
keir@19906 77 /* user specified translation unit */
keir@19906 78 uint64_t tsc2ms = 2793000UL;
keir@19906 79 uint64_t tsc2us = 2793UL;
keir@19906 80 uint64_t tsc2phase = 55800000UL;
keir@19906 81
keir@19906 82 /* each cpu column width */
keir@19906 83 int width = 0;
keir@19906 84
keir@19906 85 /* digest mode variables */
keir@19906 86 struct rec *evt[MAX_CPU_NR];
keir@19906 87 int evt_len[MAX_CPU_NR];
keir@19906 88
keir@19906 89 /* hand-crafted min() */
keir@19906 90 static inline uint64_t min(uint64_t a, uint64_t b)
keir@19906 91 {
keir@19906 92 return a < b ? a : b;
keir@19906 93 }
keir@19906 94 static inline uint64_t max(uint64_t a, uint64_t b)
keir@19906 95 {
keir@19906 96 return a > b ? a : b;
keir@19906 97 }
keir@19906 98
keir@19906 99 int is_px = 0;
keir@19906 100
keir@19906 101 int main(int argc, char *argv[])
keir@19906 102 {
keir@19906 103 char *fname = NULL;
keir@19906 104 /* operation flags */
keir@19906 105 int is_breakevents = 0;
keir@19906 106 int is_count = 0;
keir@19906 107 int is_maxmin = 0;
keir@19906 108 int is_average = 0;
keir@19906 109 int is_digest = 0;
keir@19906 110 int is_exp_ratio = 0;
keir@19906 111 int is_exp = 0;
keir@19906 112 uint64_t start_time = 0;
keir@19906 113 uint64_t time_scale = 0;
keir@19906 114 uint64_t end_time = 0;
keir@19906 115
keir@19906 116 struct option long_options [] = {
keir@19906 117 /* short options are listed correspondingly */
keir@19906 118 { "version", 0, NULL, 'v' },
keir@19906 119 { "help", 0, NULL, 'h' },
keir@19906 120 /* list Cx entires one by one */
keir@19906 121 { "digest", 0, NULL, 'd' },
keir@19906 122 /* ignored when digest is disabled */
keir@19906 123 { "start", 1, NULL, 's' },
keir@19906 124 { "end", 1, NULL, 'e' },
keir@19906 125 { "scale", 1, NULL, 'l' },
keir@19906 126 /* give summary about breakevents info */
keir@19906 127 { "breakevents", 0, NULL, 'b' },
keir@19906 128 { "count", 0, NULL, 'c' },
keir@19906 129 { "average", 0, NULL, 'a' },
keir@19906 130 /* list max/min residency for each Cx */
keir@19906 131 { "maxmin", 0, NULL, 'm' },
keir@19906 132 { "tsc2us", 1, NULL, 'u' },
keir@19906 133 { "px", 0, NULL, 'p' },
keir@19906 134 { "tsc2phase", 1, NULL, 'n' },
keir@19906 135 { "exp-ratio", 0, NULL, 'z' },
keir@19906 136 { "exp-pred", 0, NULL, 'x' },
keir@19906 137 { NULL, 0, NULL, 0 },
keir@19906 138 };
keir@19906 139
keir@19906 140 while (1) {
keir@19906 141 int ch, opt_idx;
keir@19906 142 ch = getopt_long(argc, argv, "vhds:e:l:bcmaupnzx",
keir@19906 143 long_options, &opt_idx);
keir@19906 144 if (ch == -1)
keir@19906 145 break;
keir@19906 146 switch (ch) {
keir@19906 147 case 'v':
keir@19906 148 show_version();
keir@19906 149 exit(EXIT_SUCCESS);
keir@19906 150 case 'h':
keir@19906 151 show_help();
keir@19906 152 exit(EXIT_SUCCESS);
keir@19906 153 case 'p':
keir@19906 154 is_px = 1;
keir@19906 155 break;
keir@19906 156 case 'x':
keir@19906 157 is_exp = 1;
keir@19906 158 break;
keir@19906 159 case 'z':
keir@19906 160 is_exp_ratio = 1;
keir@19906 161 break;
keir@19906 162 case 'n':
keir@19906 163 tsc2phase = atoll(optarg);
keir@19906 164 if (tsc2phase <= 0)
keir@19906 165 tsc2phase = 55800000UL;
keir@19906 166 case 'd':
keir@19906 167 is_digest = 1;
keir@19906 168 break;
keir@19906 169 case 's':
keir@19906 170 start_time = atoll(optarg);
keir@19906 171 break;
keir@19906 172 case 'e':
keir@19906 173 end_time = atoll(optarg);
keir@19906 174 break;
keir@19906 175 case 'l':
keir@19906 176 time_scale = atoll(optarg);
keir@19906 177 break;
keir@19906 178 case 'b':
keir@19906 179 is_breakevents = 1;
keir@19906 180 break;
keir@19906 181 case 'c':
keir@19906 182 is_count = 1;
keir@19906 183 break;
keir@19906 184 case 'm':
keir@19906 185 is_maxmin = 1;
keir@19906 186 break;
keir@19906 187 case 'a':
keir@19906 188 is_average = 1;
keir@19906 189 break;
keir@19906 190 case 'u':
keir@19906 191 tsc2us = atoll(optarg);
keir@19906 192 tsc2ms = tsc2us * 1000UL;
keir@19906 193 break;
keir@19906 194 case '?':
keir@19906 195 default:
keir@19906 196 show_help();
keir@19906 197 exit(EXIT_FAILURE);
keir@19906 198 }
keir@19906 199 }
keir@19906 200
keir@19906 201 if (argc - optind > 1) {
keir@19906 202 printf("Multiple file specified?\n");
keir@19906 203 show_help();
keir@19906 204 exit(EXIT_FAILURE);
keir@19906 205 }
keir@19906 206 fname = argv[optind];
keir@19906 207
keir@19906 208 if (load_file(fname))
keir@19906 209 exit(EXIT_FAILURE);
keir@19906 210
keir@19906 211 width = 10;
keir@19906 212 if (is_digest) {
keir@19906 213 /* if people not specify the time related number,
keir@19906 214 * use the default one from the record.
keir@19906 215 */
keir@19906 216 if (!start_time)
keir@19906 217 start_time = data[0].tsc;
keir@19906 218 if (!end_time)
keir@19906 219 end_time = data[data_cur-1].tsc;
keir@19906 220 if (!time_scale)
keir@19906 221 time_scale = 10UL * tsc2ms; /* default: 10 ms */
keir@19906 222 do_digest(start_time, end_time, time_scale);
keir@19906 223 }
keir@19906 224
keir@19906 225 if (is_breakevents)
keir@19906 226 do_breakevents();
keir@19906 227
keir@19906 228 if (is_count && !is_px)
keir@19906 229 do_count();
keir@19906 230 if (is_count && is_px)
keir@19906 231 do_px_count();
keir@19906 232
keir@19906 233 if (is_maxmin)
keir@19906 234 do_maxmin();
keir@19906 235
keir@19906 236 if (is_average)
keir@19906 237 do_average();
keir@19906 238
keir@19906 239 if (is_exp_ratio)
keir@19906 240 do_exp_ratio();
keir@19906 241
keir@19906 242 if (is_exp)
keir@19906 243 do_exp_pred();
keir@19906 244
keir@19906 245 exit(EXIT_SUCCESS);
keir@19906 246 }
keir@19906 247
keir@19906 248 /* used for qsort() */
keir@19906 249 /* sort by cpu first, then by tsc */
keir@19906 250 static int data_cmp(const void *_a, const void *_b)
keir@19906 251 {
keir@19906 252 struct rec *a = (struct rec *)_a;
keir@19906 253 struct rec *b = (struct rec *)_b;
keir@19906 254 if (a->cpu == b->cpu)
keir@19906 255 return a->tsc > b->tsc ? 1 : -1;
keir@19906 256 return a->cpu > b->cpu ? 1 : -1;
keir@19906 257 }
keir@19906 258
keir@19906 259 /* load file and make them a list of records
keir@19906 260 * update these following variables:
keir@19906 261 * data, data_cur, data_nr
keir@19906 262 * max_cpu_num, max_cx_num
keir@19906 263 */
keir@19906 264 #define LIST_PX 0
keir@19906 265 int load_file(char *fname)
keir@19906 266 {
keir@19906 267 /* file descriptor for raw xentrace file */
keir@19906 268 int fd;
keir@19906 269 /* current cpu during xentrace data parse */
keir@19906 270 int cur_cpu = -1;
keir@19906 271 int i;
keir@19906 272
keir@19906 273 fd = open(fname, O_RDONLY);
keir@19906 274 if (fd < 0) {
keir@19906 275 fprintf(stderr, "file %s cannot open\n", fname);
keir@19906 276 return 1;
keir@19906 277 }
keir@19906 278
keir@19906 279 /* the initial number is 1024,
keir@19906 280 * and when it overflows, this number doubles.
keir@19906 281 */
keir@19906 282 data_nr = 1024;
keir@19906 283 data_cur = 0;
keir@19906 284 data = malloc(sizeof(struct rec) * data_nr);
keir@19906 285 if (!data) {
keir@19906 286 fprintf(stderr, "not enough memory\n");
keir@19906 287 close(fd);
keir@19906 288 return 1;
keir@19906 289 }
keir@19906 290
keir@19906 291 while (1) {
keir@19906 292 struct t_rec rec;
keir@19906 293 ssize_t ret, size;
keir@19906 294
keir@19906 295 ret = read(fd, &rec, sizeof(uint32_t));
keir@19906 296 if (!ret)
keir@19906 297 break;
keir@19906 298 if (ret != sizeof(uint32_t)) {
keir@19906 299 fprintf(stderr, "reading header error\n");
keir@19906 300 break;
keir@19906 301 }
keir@19906 302
keir@19906 303 size = 0;
keir@19906 304 if (rec.cycles_included)
keir@19906 305 size += sizeof(uint64_t);
keir@19906 306 size += sizeof(uint32_t) * rec.extra_u32;
keir@19906 307
keir@19906 308 ret = read(fd, (char *)&rec + sizeof(uint32_t), size);
keir@19906 309 if (!ret && size)
keir@19906 310 break;
keir@19906 311 if (ret != size) {
keir@19906 312 fprintf(stderr, "reading data error\n");
keir@19906 313 break;
keir@19906 314 }
keir@19906 315
keir@19906 316 if (rec.event == 0x1f003) {
keir@19906 317 /* cpu change event */
keir@19906 318 cur_cpu = 0;
keir@19906 319 if (rec.extra_u32 > 0)
keir@19906 320 cur_cpu = rec.u.nocycles.extra_u32[0];
keir@19906 321 continue;
keir@19906 322 } else if (!rec.cycles_included ||
keir@19906 323 (rec.event != TRC_PM_IDLE_ENTRY &&
keir@19906 324 rec.event != TRC_PM_IDLE_EXIT &&
keir@19906 325 rec.event != TRC_PM_FREQ_CHANGE)) {
keir@19906 326 /* we care about only idle events now */
keir@19906 327 continue;
keir@19906 328 }
keir@19906 329
keir@19906 330 /* add one record */
keir@19906 331 if (data_cur == data_nr) {
keir@19906 332 data_nr <<= 1;
keir@19906 333 if (data_nr < 0) {
keir@19906 334 fprintf(stderr, "too many entries\n");
keir@19906 335 close(fd);
keir@19906 336 return 1;
keir@19906 337 }
keir@19906 338 data = realloc(data, sizeof(struct rec) * data_nr);
keir@19906 339 if (!data) {
keir@19906 340 fprintf(stderr, "not enough memory\n");
keir@19906 341 close(fd);
keir@19906 342 return 1;
keir@19906 343 }
keir@19906 344 }
keir@19906 345 data[data_cur].tsc = rec.u.cycles.cycles_hi;
keir@19906 346 data[data_cur].tsc <<= 32;
keir@19906 347 data[data_cur].tsc |= rec.u.cycles.cycles_lo;
keir@19906 348 data[data_cur].cpu = cur_cpu;
keir@19906 349 if (is_px) {
keir@19906 350 if (rec.event != TRC_PM_FREQ_CHANGE)
keir@19906 351 continue;
keir@19906 352 /* FREQ_CHANGE */
keir@19906 353 if (rec.u.cycles.extra_u32[0] ==
keir@19906 354 rec.u.cycles.extra_u32[1])
keir@19906 355 continue;
keir@19906 356 data[data_cur].px = rec.u.cycles.extra_u32[1];
keir@19906 357 for (i = 0; i < max_px_num; i++)
keir@19906 358 if (px_freq_table[i] == data[data_cur].px)
keir@19906 359 break;
keir@19906 360 if (i == max_px_num)
keir@19906 361 px_freq_table[max_px_num++] = data[data_cur].px;
keir@19906 362 } else {
keir@19906 363 if (rec.event == TRC_PM_IDLE_ENTRY) {
keir@19906 364 data[data_cur].cx = rec.u.cycles.extra_u32[0];
keir@19906 365 if (rec.extra_u32 >= 4) {
keir@19906 366 data[data_cur].expected = rec.u.cycles.extra_u32[2];
keir@19906 367 data[data_cur].predicted = rec.u.cycles.extra_u32[3];
keir@19906 368 is_menu_gov_enabled = 1;
keir@19906 369 } else
keir@19906 370 is_menu_gov_enabled = 0;
keir@19906 371 } else if (rec.event == TRC_PM_IDLE_EXIT) {
keir@19906 372 /* IDLE_EXIT default to C0 */
keir@19906 373 data[data_cur].cx = 0;
keir@19906 374 /* store the reasons why it exits */
keir@19906 375 data[data_cur].irqs[0] = rec.u.cycles.extra_u32[2];
keir@19906 376 data[data_cur].irqs[1] = rec.u.cycles.extra_u32[3];
keir@19906 377 data[data_cur].irqs[2] = rec.u.cycles.extra_u32[4];
keir@19906 378 data[data_cur].irqs[3] = rec.u.cycles.extra_u32[5];
keir@19906 379 } else
keir@19906 380 continue;
keir@19906 381 /* update max info */
keir@19906 382 if (data[data_cur].cx > max_cx_num)
keir@19906 383 max_cx_num = data[data_cur].cx;
keir@19906 384 }
keir@19906 385
keir@19906 386 if (data[data_cur].cpu > max_cpu_num)
keir@19906 387 max_cpu_num = data[data_cur].cpu;
keir@19906 388
keir@19906 389 data_cur++;
keir@19906 390 }
keir@19906 391 close(fd);
keir@19906 392
keir@19906 393 /* sort data array according to TSC time line */
keir@19906 394 qsort(data, data_cur, sizeof(struct rec), data_cmp);
keir@19906 395
keir@19906 396 max_cpu_num++;
keir@19906 397 max_cx_num++;
keir@19906 398
keir@19906 399 for (i = 0; i < max_cpu_num; i++) {
keir@19906 400 evt_len[i] = 0;
keir@19906 401 evt[i] = NULL;
keir@19906 402 }
keir@19906 403 for (i = data_cur-1; i >= 0; i--) {
keir@19906 404 evt[data[i].cpu] = data+i;
keir@19906 405 evt_len[data[i].cpu]++;
keir@19906 406 }
keir@19906 407 #if CHECK_DUP_CX
keir@19906 408 int xx, yy;
keir@19906 409 int err = 0;
keir@19906 410 printf("Checking %s...\n", fname);
keir@19906 411 for (xx = 0; xx < max_cpu_num; xx++) {
keir@19906 412 // printf("............ CPU %d .............\n", xx);
keir@19906 413 for (yy = 0; yy+1 < evt_len[xx]; yy++)
keir@19906 414 if ( evt[xx][yy].cx > 0 && evt[xx][yy+1].cx > 0) {
keir@19906 415 printf("same witht next one %"PRIu64" %d %d\n",
keir@19906 416 evt[xx][yy].tsc, evt[xx][yy].cpu, evt[xx][yy].cx);
keir@19906 417 err++;
keir@19906 418 }
keir@19906 419 }
keir@19906 420 exit(err);
keir@19906 421 #endif
keir@19906 422 #if LIST_PX
keir@19906 423 int x, y;
keir@19906 424 for (x = 0; x < max_cpu_num; x++) {
keir@19906 425 printf("CPU%d**************************************\n", x);
keir@19906 426 for (y = 0; y+1 < evt_len[x]; y++) {
keir@19906 427 printf("[%dHz]: phase: %d\n",
keir@19906 428 evt[x][y].px,
keir@19906 429 (int)((evt[x][y+1].tsc - evt[x][y].tsc)/tsc2phase));
keir@19906 430 }
keir@19906 431 }
keir@19906 432 #endif
keir@19906 433 return 0;
keir@19906 434 }
keir@19906 435
keir@19906 436 void show_version(void)
keir@19906 437 {
keir@19906 438 printf("gtracestat - (C) 2009 Intel Corporation\n");
keir@19906 439 }
keir@19906 440
keir@19906 441 void show_help(void)
keir@19906 442 {
keir@19906 443 show_version();
keir@19906 444 printf("tracestat <trace.data> [-vhdselbcmau]\n");
keir@20121 445 printf(" trace.data raw data got by 'xentrace -e 0x80f000 trace.dat'\n");
keir@19906 446 printf(" -v / --version show version message\n");
keir@19906 447 printf(" -h / --help show this message\n");
keir@19906 448 printf(" -d / --digest digest mode, more variables to specify.\n");
keir@19906 449 printf(" -s / --start <start_time> specify start time (only in digest mode)\n");
keir@19906 450 printf(" -e / --end <end_time> specify end time (only in digest mode)\n");
keir@19906 451 printf(" -l / --scale <scale> specify time scale (only in digest mode)\n");
keir@19906 452 printf(" -b / --breakevents give breakevents summary info\n");
keir@19906 453 printf(" -c / --count give count summary info\n");
keir@19906 454 printf(" -a / --average give total/average residency info\n");
keir@19906 455 printf(" -m / --maxmin show man/min residency summary info\n");
keir@19906 456 printf(" -u / --tsc2us specify how many tsc is a us unit\n");
keir@19906 457 printf(" -p / --px operate on Px entries\n");
keir@19906 458 printf(" -n / --tsc2phase specify how many tsc is a phase unit (only in px)\n");
keir@19906 459 printf(" -z / --exp-ratio show the ratio of early break events\n");
keir@19906 460 printf(" -x / --exp-pred show the ratio of expected / predicted in Cx entry\n");
keir@19906 461 }
keir@19906 462
keir@19906 463 static inline int len_of_number(uint64_t n)
keir@19906 464 {
keir@19906 465 int l = 0;
keir@19906 466 do {
keir@19906 467 l++;
keir@19906 468 n /= 10;
keir@19906 469 } while (n);
keir@19906 470 return l;
keir@19906 471 }
keir@19906 472
keir@19906 473 /* determine the cx at time t
keir@19906 474 * take advantage of evt and evt_len.
keir@19906 475 */
keir@19906 476 int determine_cx(int c, uint64_t t)
keir@19906 477 {
keir@19906 478 int i;
keir@19906 479
keir@19906 480 i = 0;
keir@19906 481 while (i < evt_len[c] && evt[c][i].tsc <= t)
keir@19906 482 i++;
keir@19906 483 /* if there are any events happening,
keir@19906 484 * it must be in a Cx state now.
keir@19906 485 */
keir@19906 486 if (i)
keir@19906 487 return evt[c][i-1].cx;
keir@19906 488 /* look forward to see whether it will enter
keir@19906 489 * a Cx state, if so, it must be in C0 state.
keir@19906 490 * we can't determine a Cx state from exit event.
keir@19906 491 */
keir@19906 492 if (i < evt_len[c] && evt[c][i].cx > 0)
keir@19906 493 return 0;
keir@19906 494 return -1;
keir@19906 495 }
keir@19906 496
keir@19906 497 /* c - cpu
keir@19906 498 * t - start time
keir@19906 499 * s - scale
keir@19906 500 * cx_i - number of cx index
keir@19906 501 * cx_r - residency of each cx entry
keir@19906 502 */
keir@19906 503 int process(int c, uint64_t t, uint64_t s, int *cx_i, uint64_t *cx_r)
keir@19906 504 {
keir@19906 505 int cx;
keir@19906 506 uint64_t len;
keir@19906 507 int i, n;
keir@19906 508
keir@19906 509 cx = determine_cx(c, t);
keir@19906 510 i = 0;
keir@19906 511 while (i < evt_len[c] && evt[c][i].tsc < t)
keir@19906 512 i++;
keir@19906 513 n = 0;
keir@19906 514 if (cx >= 0 && i < evt_len[c]) {
keir@19906 515 cx_i[n] = cx;
keir@19906 516 cx_r[n] = evt[c][i].tsc - t;
keir@19906 517 if (cx_r[n])
keir@19906 518 n++;
keir@19906 519 }
keir@19906 520 while (i < evt_len[c] && evt[c][i].tsc < t+s) {
keir@19906 521 /* we are now at [t, t+s) */
keir@19906 522 cx = evt[c][i].cx;
keir@19906 523 len = min((i+1 < evt_len[c] ? evt[c][i+1].tsc : t+s), t+s)
keir@19906 524 - evt[c][i].tsc;
keir@19906 525
keir@19906 526 cx_i[n] = cx;
keir@19906 527 cx_r[n] = len;
keir@19906 528 n++;
keir@19906 529
keir@19906 530 i++;
keir@19906 531 }
keir@19906 532
keir@19906 533 return n;
keir@19906 534 }
keir@19906 535
keir@19906 536 void nr_putchar(int nr, int ch)
keir@19906 537 {
keir@19906 538 int i;
keir@19906 539 for (i = 0; i < nr; i++)
keir@19906 540 putchar(ch);
keir@19906 541 }
keir@19906 542
keir@19906 543 #define MAX_INTERVAL_ENTRY 1000
keir@19906 544 /* process period [start_time, start_time + time_scale) */
keir@19906 545 void single_digest(uint64_t start_time, uint64_t time_scale)
keir@19906 546 {
keir@19906 547 int cpu;
keir@19906 548 int cx_i[MAX_CPU_NR][MAX_INTERVAL_ENTRY];
keir@19906 549 uint64_t cx_r[MAX_CPU_NR][MAX_INTERVAL_ENTRY];
keir@19906 550 int cx_n[MAX_CPU_NR];
keir@19906 551 int max_n;
keir@19906 552
keir@19906 553 memset(cx_i, 0, sizeof(int) * MAX_CPU_NR * MAX_INTERVAL_ENTRY);
keir@19906 554 memset(cx_r, 0, sizeof(uint64_t) * MAX_CPU_NR * MAX_INTERVAL_ENTRY);
keir@19906 555 memset(cx_n, 0, sizeof(int) * MAX_CPU_NR);
keir@19906 556
keir@19906 557 max_n = 0;
keir@19906 558 for (cpu = 0; cpu < max_cpu_num; cpu++) {
keir@19906 559 cx_n[cpu] = process(cpu, start_time, time_scale, cx_i[cpu], cx_r[cpu]);
keir@19906 560 if (cx_n[cpu] > max_n)
keir@19906 561 max_n = cx_n[cpu];
keir@19906 562 }
keir@19906 563
keir@19906 564 /* means how many lines will be consumed */
keir@19906 565 while (--max_n >= 0) {
keir@19906 566 for (cpu = 0; cpu < max_cpu_num; cpu++) {
keir@19906 567 if (cx_n[cpu] > 0) {
keir@19906 568 int i;
keir@19906 569 /* find the available cx index */
keir@19906 570 for (i = 0; i < MAX_INTERVAL_ENTRY && cx_i[cpu][i] == -1; i++)
keir@19906 571 ;
keir@19906 572 if (i < MAX_INTERVAL_ENTRY) {
keir@19906 573 int len;
keir@19906 574 /* print it */
keir@19906 575 len= printf("C%d,%"PRIu64".%d", cx_i[cpu][i],
keir@19906 576 cx_r[cpu][i]/tsc2ms,
keir@19906 577 (unsigned int)(cx_r[cpu][i]/(tsc2ms/10))%10);
keir@19906 578 nr_putchar(width-len, ' ');
keir@19906 579
keir@19906 580 cx_i[cpu][i] = -1;
keir@19906 581 } else
keir@19906 582 nr_putchar(width, ' ');
keir@19906 583
keir@19906 584 cx_n[cpu]--;
keir@19906 585 } else
keir@19906 586 nr_putchar(width, ' ');
keir@19906 587 }
keir@19906 588 nr_putchar(1, '\n');
keir@19906 589 }
keir@19906 590 }
keir@19906 591
keir@19906 592 void do_digest(uint64_t start, uint64_t end, uint64_t scale)
keir@19906 593 {
keir@19906 594 int i;
keir@19906 595 uint64_t ms = 0;
keir@19906 596 uint64_t delta_ms = scale / tsc2ms;
keir@19906 597
keir@19906 598 for (i = 0; i < max_cpu_num; i++) {
keir@19906 599 int len = 0;
keir@19906 600 len = printf("CPU%d", i);
keir@19906 601 nr_putchar(width-len, ' ');
keir@19906 602 }
keir@19906 603 nr_putchar(1, '\n');
keir@19906 604 while (start < end) {
keir@19906 605 /* print --- xxx ms --- line */
keir@19906 606 int off = (max_cpu_num * width - len_of_number(ms) - 2)/2;
keir@19906 607 nr_putchar(off, '-');
keir@19906 608 off += printf("%"PRIu64"ms", ms);
keir@19906 609 off += printf(" (%"PRIu64")", start);
keir@19906 610 nr_putchar(max_cpu_num * width-off, '-');
keir@19906 611 nr_putchar(1, '\n');
keir@19906 612 /* print each digest entries */
keir@19906 613 single_digest(start, scale);
keir@19906 614
keir@19906 615 start += scale;
keir@19906 616 ms += delta_ms;
keir@19906 617 }
keir@19906 618 }
keir@19906 619
keir@19906 620 /* [min, max) */
keir@19906 621 struct cond_rec {
keir@19906 622 uint64_t min;
keir@19906 623 uint64_t max;
keir@19906 624 uint64_t cnt;
keir@19906 625 uint64_t res;
keir@19906 626 };
keir@19906 627
keir@19906 628 void cond_rec_init(struct cond_rec *r, uint64_t min, uint64_t max)
keir@19906 629 {
keir@19906 630 r->min = min;
keir@19906 631 r->max = max;
keir@19906 632 r->cnt = 0;
keir@19906 633 }
keir@19906 634
keir@19906 635 void cond_rec_inc(uint64_t cur, struct cond_rec *r)
keir@19906 636 {
keir@19906 637 if (r->min <= cur && cur < r->max) {
keir@19906 638 r->cnt++;
keir@19906 639 r->res += cur;
keir@19906 640 }
keir@19906 641 }
keir@19906 642
keir@19906 643 /* c - current cpu to scan
keir@19906 644 * cx - cx state to track
keir@19906 645 * a - conditonal array
keir@19906 646 * n - how many entries there are
keir@19906 647 */
keir@19906 648 void do_count_per_cpu(int c, int cx, struct cond_rec *a, int n)
keir@19906 649 {
keir@19906 650 int i;
keir@19906 651 /* find Cx entry first */
keir@19906 652 i = 0;
keir@19906 653 while (i < evt_len[c] && evt[c][i].cx == 0)
keir@19906 654 i++;
keir@19906 655 /* check evt[c][i] and evt[c][i+1] */
keir@19906 656 while (i + 1 < evt_len[c]) {
keir@19906 657 if (evt[c][i].cx == cx) {
keir@19906 658 uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc;
keir@19906 659 int j;
keir@19906 660 /* check for each condition */
keir@19906 661 for (j = 0; j < n; j++)
keir@19906 662 cond_rec_inc(len, a+j);
keir@19906 663 }
keir@19906 664 i++;
keir@19906 665 }
keir@19906 666 }
keir@19906 667
keir@19906 668 struct cond_rec *make_cond_rec(uint64_t *a, int n)
keir@19906 669 {
keir@19906 670 int i;
keir@19906 671 struct cond_rec *t = malloc(sizeof(struct cond_rec) * (n+1));
keir@19906 672 if (!t)
keir@19906 673 return NULL;
keir@19906 674 for (i = 0; i < n; i++) {
keir@19906 675 t[i].max = a[i];
keir@19906 676 t[i+1].min = a[i];
keir@19906 677 t[i].cnt = 0;
keir@19906 678 t[i].res = 0;
keir@19906 679 }
keir@19906 680 t[0].min = 0;
keir@19906 681 t[n].max = (uint64_t) -1;
keir@19906 682 t[n].cnt = 0;
keir@19906 683 t[n].res = 0;
keir@19906 684
keir@19906 685 return t;
keir@19906 686 }
keir@19906 687
keir@19906 688 uint64_t max_res[MAX_CPU_NR][MAX_CX_NR];
keir@19906 689 uint64_t min_res[MAX_CPU_NR][MAX_CX_NR];
keir@19906 690 uint64_t max_tm[MAX_CPU_NR][MAX_CX_NR];
keir@19906 691 uint64_t min_tm[MAX_CPU_NR][MAX_CX_NR];
keir@19906 692
keir@19906 693 void do_maxmin_per_cpu(int c)
keir@19906 694 {
keir@19906 695 int i;
keir@19906 696 /* find Cx entry first */
keir@19906 697 i = 0;
keir@19906 698 while (i < evt_len[c] && evt[c][i].cx == 0)
keir@19906 699 i++;
keir@19906 700 /* check evt[c][i] and evt[c][i+1] */
keir@19906 701 while (i + 1 < evt_len[c]) {
keir@19906 702 int cx = evt[c][i].cx;
keir@19906 703 uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc;
keir@19906 704 if (len > max_res[c][cx]) {
keir@19906 705 max_res[c][cx] = len;
keir@19906 706 max_tm[c][cx] = evt[c][i].tsc;
keir@19906 707 }
keir@19906 708 if (len < min_res[c][cx]) {
keir@19906 709 min_res[c][cx] = len;
keir@19906 710 min_tm[c][cx] = evt[c][i].tsc;
keir@19906 711 }
keir@19906 712 i++;
keir@19906 713 }
keir@19906 714 }
keir@19906 715
keir@19906 716 void do_maxmin(void)
keir@19906 717 {
keir@19906 718 int i, j;
keir@19906 719 /* init */
keir@19906 720 for (i = 0; i < max_cpu_num; i++)
keir@19906 721 for (j = 0; j < max_cx_num; j++) {
keir@19906 722 max_res[i][j] = 0;
keir@19906 723 min_res[i][j] = (uint64_t) -1;
keir@19906 724 }
keir@19906 725
keir@19906 726 for (i = 0; i < max_cpu_num; i++)
keir@19906 727 do_maxmin_per_cpu(i);
keir@19906 728
keir@19906 729 for (i = 0; i < max_cpu_num; i++) {
keir@19906 730 printf("********* CPU%d *********\n", i);
keir@19906 731 for (j = 0; j < max_cx_num; j++)
keir@19906 732 if (max_res[i][j] == 0)
keir@19906 733 printf(" not found ");
keir@19906 734 else
keir@19906 735 printf("%7"PRIu64"us (%15"PRIu64") ", max_res[i][j]/tsc2us, max_tm[i][j]);
keir@19906 736 printf("\n");
keir@19906 737 for (j = 0; j < max_cx_num; j++)
keir@19906 738 if (max_res[i][j] == 0)
keir@19906 739 printf(" not found ");
keir@19906 740 else
keir@19906 741 printf("%7"PRIu64"us (%15"PRIu64") ", min_res[i][j]/tsc2us, min_tm[i][j]);
keir@19906 742 printf("\n\n");
keir@19906 743 }
keir@19906 744 }
keir@19906 745
keir@19906 746 void do_count(void)
keir@19906 747 {
keir@19906 748 uint64_t scale[100] = { 50000UL, 100000UL, 200000UL, 400000UL, 800000UL, 1000000UL };
keir@19906 749 int a[100];
keir@19906 750 int scale_len = 6;
keir@19906 751 int len = 0;
keir@19906 752 int i, j;
keir@19906 753
keir@19906 754 printf("Please input the period: (Ctrl+D to quit)\n");
keir@19906 755 printf("The default is 50us, 100us, 200us, 400us, 800us, 1000us.\n(unit is us, you DO NOT need to add us and specify ZERO us and please be in INCREASING order.)\n");
keir@19906 756 while (scanf("%d", &a[len]) == 1)
keir@19906 757 len++;
keir@19906 758 if (len) {
keir@19906 759 for (i = 0; i < len; i++)
keir@19906 760 scale[i] = a[i] * tsc2us;
keir@19906 761 scale_len = len;
keir@19906 762 }
keir@19906 763 for (i = 0; i < max_cpu_num; i++) {
keir@19906 764 struct cond_rec *r[MAX_CX_NR];
keir@19906 765 uint64_t sum[MAX_CX_NR];
keir@19906 766 int k;
keir@19906 767
keir@19906 768 printf("********** CPU%d *********\n", i);
keir@19906 769 for (j = 0; j < max_cx_num; j++) {
keir@19906 770 r[j] = make_cond_rec(scale, scale_len);
keir@19906 771 if (!r[j])
keir@19906 772 continue;
keir@19906 773 do_count_per_cpu(i, j, r[j], scale_len+1);
keir@19906 774
keir@19906 775 /* print */
keir@19906 776 sum[j] = 0;
keir@19906 777 for (k = 0; k < scale_len+1; k++)
keir@19906 778 sum[j] += r[j][k].cnt;
keir@19906 779 if (sum[j] == 0)
keir@19906 780 sum[j] = 1;
keir@19906 781 }
keir@19906 782 printf(" ");
keir@19906 783 for (j = 0; j < max_cx_num; j++)
keir@19906 784 printf(" C%d ", j);
keir@19906 785 printf("\n");
keir@19906 786 for (k = 0; k < scale_len+1; k++) {
keir@19906 787 if (k == scale_len)
keir@19906 788 printf("%5"PRIu64" us -> MAX us:", r[0][k].min/tsc2us);
keir@19906 789 else
keir@19906 790 printf("%5"PRIu64" us -> %5"PRIu64" us:",
keir@19906 791 r[0][k].min/tsc2us, r[0][k].max/tsc2us);
keir@19906 792 for (j = 0; j < max_cx_num; j++)
keir@19906 793 printf(" %10"PRIu64" (%5.2f%%)",
keir@19906 794 r[j][k].cnt, 100.0 * (double) r[j][k].cnt / (double)sum[j]);
keir@19906 795 printf("\n");
keir@19906 796 }
keir@19906 797 for (j = 0; j < max_cx_num; j++)
keir@19906 798 free(r[j]);
keir@19906 799 }
keir@19906 800 }
keir@19906 801
keir@19906 802 static void do_px_count_per_cpu(int c, int px, struct cond_rec *cond, int n)
keir@19906 803 {
keir@19906 804 int i, j;
keir@19906 805 uint64_t len;
keir@19906 806
keir@19906 807 i = 0;
keir@19906 808 while (i+1 < evt_len[c]) {
keir@19906 809 if (evt[c][i].px == px) {
keir@19906 810 len = evt[c][i+1].tsc - evt[c][i].tsc;
keir@19906 811 /* check each condition */
keir@19906 812 for (j = 0; j < n; j++)
keir@19906 813 cond_rec_inc(len, cond+j);
keir@19906 814 }
keir@19906 815 i++;
keir@19906 816 }
keir@19906 817 }
keir@19906 818
keir@19906 819 void do_px_count(void)
keir@19906 820 {
keir@19906 821 int a[100];
keir@19906 822 uint64_t scale[100];
keir@19906 823 int n, i, c, j;
keir@19906 824
keir@19906 825 printf("Please input phases series: (Ctrl+D to quit)\n");
keir@19906 826 printf("The default is 1, 2, 4, 8, 16, 32.\n");
keir@19906 827 printf("Please be in increasing order.\n");
keir@19906 828 scale[0] = tsc2phase;
keir@19906 829 scale[1] = 2 * tsc2phase;
keir@19906 830 scale[2] = 4 * tsc2phase;
keir@19906 831 scale[3] = 8 * tsc2phase;
keir@19906 832 scale[4] = 16 * tsc2phase;
keir@19906 833 scale[5] = 32 * tsc2phase;
keir@19906 834 n = 0;
keir@19906 835 while (scanf("%d", &a[n]) == 1)
keir@19906 836 n++;
keir@19906 837 if (n) {
keir@19906 838 for (i = 0; i < n; i++)
keir@19906 839 scale[i] = a[i] * tsc2phase;
keir@19906 840 } else
keir@19906 841 n = 6;
keir@19906 842 for (c = 0; c < max_cpu_num; c++) {
keir@19906 843 struct cond_rec *p[MAX_PX_NR];
keir@19906 844 int k;
keir@19906 845
keir@19906 846 printf("***** CPU%d *****\n", c);
keir@19906 847 for (i = 0; i < max_px_num; i++) {
keir@19906 848 p[i] = make_cond_rec(scale, n);
keir@19906 849 if (!p[i])
keir@19906 850 continue;
keir@19906 851 do_px_count_per_cpu(c, px_freq_table[i], p[i], n+1);
keir@19906 852 }
keir@19906 853 /* print */
keir@19906 854 nr_putchar(16, ' ');
keir@19906 855 for (j = 0; j < max_px_num; j++)
keir@19906 856 printf("P%d\t", px_freq_table[j]);
keir@19906 857 printf("\n");
keir@19906 858 for (k = 0; k < n+1; k++) {
keir@19906 859 if (k == n)
keir@19906 860 printf("%5"PRIu64" -> MAX : ", p[0][k].min/tsc2phase);
keir@19906 861 else
keir@19906 862 printf("%5"PRIu64" -> %5"PRIu64": ",
keir@19906 863 p[0][k].min/tsc2phase, p[0][k].max/tsc2phase);
keir@19906 864 for (j = 0; j < max_px_num; j++) {
keir@19906 865 printf("%"PRIu64"\t", p[j][k].cnt);
keir@19906 866 }
keir@19906 867 printf("\n");
keir@19906 868 }
keir@19906 869 printf("---\n");
keir@19906 870 printf("Count: ");
keir@19906 871 for (j = 0; j < max_px_num; j++) {
keir@19906 872 int sum = 0;
keir@19906 873 for (k = 0; k < n+1; k++) {
keir@19906 874 sum += (int)p[j][k].cnt;
keir@19906 875 }
keir@19906 876 /* print count */
keir@19906 877 printf("%d\t", sum);
keir@19906 878 }
keir@19906 879 printf("\nAverage: ");
keir@19906 880 for (j = 0; j < max_px_num; j++) {
keir@19906 881 int sum = 0;
keir@19906 882 int s_res = 0;
keir@19906 883 for (k = 0; k < n+1; k++) {
keir@19906 884 sum += (int)p[j][k].cnt;
keir@19906 885 s_res += (int)(p[j][k].res/tsc2phase);
keir@19906 886 }
keir@19906 887 /* print average */
keir@19906 888 if (sum == 0)
keir@19906 889 sum = 1;
keir@19906 890 printf("%.1f\t", (double)s_res/(double)sum);
keir@19906 891 }
keir@19906 892 printf("\nTotal: ");
keir@19906 893 for (j = 0; j < max_px_num; j++) {
keir@19906 894 int s_res = 0;
keir@19906 895 for (k = 0; k < n+1; k++) {
keir@19906 896 s_res += (int)(p[j][k].res/tsc2phase);
keir@19906 897 }
keir@19906 898 /* print total */
keir@19906 899 printf("%d\t", s_res);
keir@19906 900 }
keir@19906 901 printf("\n");
keir@19906 902 }
keir@19906 903 }
keir@19906 904
keir@19906 905 void do_breakevents(void)
keir@19906 906 {
keir@19906 907 int br[MAX_CPU_NR][257];
keir@19906 908 float pc[MAX_CPU_NR][257];
keir@19906 909 int i, j, k, l;
keir@19906 910
keir@19906 911 memset(br, 0, sizeof(int) * MAX_CPU_NR * 257);
keir@19906 912 memset(pc, 0, sizeof(int) * MAX_CPU_NR * 257);
keir@19906 913
keir@19906 914 for (i = 0; i < max_cpu_num; i++) {
keir@19906 915 int sum = 0;
keir@19906 916 for (j = 0; j < evt_len[i]; j++) {
keir@19906 917 if (evt[i][j].cx == 0) {
keir@19906 918 /* EXIT */
keir@19906 919 /* collect breakevents information */
keir@19906 920 int xx = 0;
keir@19906 921 for (k = 0; k < 4; k++) {
keir@19906 922 int irq = evt[i][j].irqs[k];
keir@19906 923 if (irq) {
keir@19906 924 br[i][irq]++;
keir@19906 925 sum++;
keir@19906 926 xx++;
keir@19906 927 }
keir@19906 928 }
keir@19906 929 if (!xx) {
keir@19906 930 br[i][256]++;
keir@19906 931 sum++;
keir@19906 932 }
keir@19906 933 }
keir@19906 934 }
keir@19906 935 for (j = 0; j < 257; j++)
keir@19906 936 pc[i][j] = 100.0 * br[i][j]/sum;
keir@19906 937 }
keir@19906 938 /* print the results */
keir@19906 939 width = 13;
keir@19906 940 printf(" ");
keir@19906 941 for (i = 0; i < max_cpu_num; i++) {
keir@19906 942 l = 0;
keir@19906 943 l += printf("CPU%d", i);
keir@19906 944 nr_putchar(width-l, ' ');
keir@19906 945 }
keir@19906 946 printf("\n");
keir@19906 947
keir@19906 948 for (j = 0; j < 257; j++) {
keir@19906 949 int n = 0;
keir@19906 950 for (i = 0; i < max_cpu_num; i++)
keir@19906 951 if (br[i][j])
keir@19906 952 n++;
keir@19906 953 if (n) {
keir@19906 954 if (j == 256)
keir@19906 955 printf("[N/A] ");
keir@19906 956 else
keir@19906 957 printf("[%03x] ", j);
keir@19906 958 for (i = 0; i < max_cpu_num; i++) {
keir@19906 959 if (br[i][j]) {
keir@19906 960 l = 0;
keir@19906 961 l += printf("%.1f%%,%d ", pc[i][j], br[i][j]);
keir@19906 962 nr_putchar(width-l, ' ');
keir@19906 963 } else {
keir@19906 964 nr_putchar(width, ' ');
keir@19906 965 }
keir@19906 966 }
keir@19906 967 printf("\n");
keir@19906 968 }
keir@19906 969 }
keir@19906 970 }
keir@19906 971
keir@19906 972 void single_cstate(int c, uint64_t t, uint64_t e,
keir@19906 973 uint64_t *a,
keir@19906 974 uint64_t *max_res,
keir@19906 975 uint64_t *min_res,
keir@19906 976 uint64_t *num);
keir@19906 977 void do_cstate(uint64_t start, uint64_t end)
keir@19906 978 {
keir@19906 979 uint64_t cxtime[MAX_CX_NR];
keir@19906 980 uint64_t max_res[MAX_CX_NR];
keir@19906 981 uint64_t min_res[MAX_CX_NR];
keir@19906 982 uint64_t num[MAX_CX_NR];
keir@19906 983 int i, j;
keir@19906 984
keir@19906 985 width = 20;
keir@19906 986 printf(" ");
keir@19906 987 for (i = 0; i < max_cx_num; i++) {
keir@19906 988 int l = printf("C%d", i);
keir@19906 989 nr_putchar(width-l, ' ');
keir@19906 990 }
keir@19906 991 printf("\n");
keir@19906 992
keir@19906 993 for (i = 0; i < max_cpu_num; i++) {
keir@19906 994 uint64_t sum = 0;
keir@19906 995 single_cstate(i, start, end, cxtime, max_res, min_res, num);
keir@19906 996 printf("CPU%2d ", i);
keir@19906 997 for (j = 0; j < max_cx_num; j++)
keir@19906 998 sum += cxtime[i];
keir@19906 999 for (j = 0; j < max_cx_num; j++) {
keir@19906 1000 int l = printf("%.1f%%, %"PRIu64".%d, %"PRIu64".%d, %"PRIu64,
keir@19906 1001 100.0 * cxtime[j]/sum,
keir@19906 1002 max_res[j]/tsc2ms,
keir@19906 1003 (unsigned int)(max_res[j]/(tsc2ms/10))%10,
keir@19906 1004 min_res[j]/tsc2ms,
keir@19906 1005 (unsigned int)(min_res[j]/(tsc2ms/10))%10,
keir@19906 1006 cxtime[j]/num[j]/tsc2ms);
keir@19906 1007 nr_putchar(width - l, ' ');
keir@19906 1008 }
keir@19906 1009 }
keir@19906 1010 }
keir@19906 1011
keir@19906 1012 void single_cstate(int c, uint64_t t, uint64_t e,
keir@19906 1013 uint64_t *a,
keir@19906 1014 uint64_t *max_res,
keir@19906 1015 uint64_t *min_res,
keir@19906 1016 uint64_t *num)
keir@19906 1017 {
keir@19906 1018 int cx;
keir@19906 1019 int i;
keir@19906 1020 int first = 1;
keir@19906 1021
keir@19906 1022 for (i = 0; i < max_cx_num; i++) {
keir@19906 1023 a[i] = 0;
keir@19906 1024 max_res[i] = 0;
keir@19906 1025 min_res[i] = (uint64_t) -1;
keir@19906 1026 num[i] = 0;
keir@19906 1027 }
keir@19906 1028
keir@19906 1029 cx = determine_cx(c, t);
keir@19906 1030 i = 0;
keir@19906 1031 while (i < evt_len[c] && evt[c][i].tsc <= t)
keir@19906 1032 i++;
keir@19906 1033 for (; i+1 < evt_len[c] && evt[c][i].tsc <= e; i++) {
keir@19906 1034 int cxidx = evt[c][i].cx;
keir@19906 1035 uint64_t delta;
keir@19906 1036
keir@19906 1037 if (first && cx >= 0) {
keir@19906 1038 /* Partial Cx, only once */
keir@19906 1039 first = 0;
keir@19906 1040
keir@19906 1041 cxidx = cx;
keir@19906 1042 delta = evt[c][i].tsc - max(evt[c][i-1].tsc, t);
keir@19906 1043 a[cxidx] += delta;
keir@19906 1044 num[cxidx]++;
keir@19906 1045
keir@19906 1046 /* update min and max residency */
keir@19906 1047 if (delta > max_res[cxidx])
keir@19906 1048 max_res[cxidx] = delta;
keir@19906 1049 if (delta < min_res[cxidx])
keir@19906 1050 min_res[cxidx] = delta;
keir@19906 1051 }
keir@19906 1052 delta = evt[c][i+1].tsc - evt[c][i].tsc;
keir@19906 1053 a[cxidx] += delta;
keir@19906 1054 num[cxidx]++;
keir@19906 1055
keir@19906 1056 /* update min and max residency */
keir@19906 1057 if (delta > max_res[cxidx])
keir@19906 1058 max_res[cxidx] = delta;
keir@19906 1059 if (delta < min_res[cxidx])
keir@19906 1060 min_res[cxidx] = delta;
keir@19906 1061 }
keir@19906 1062 }
keir@19906 1063
keir@19906 1064 void do_average_per_cpu(int c)
keir@19906 1065 {
keir@19906 1066 int i;
keir@19906 1067 uint64_t tot[MAX_CX_NR] = { 0 };
keir@19906 1068 uint64_t cnt[MAX_CX_NR] = { 0 };
keir@19906 1069 uint64_t sum = 0;
keir@19906 1070
keir@19906 1071 /* find Cx entry first */
keir@19906 1072 i = 0;
keir@19906 1073 while (i < evt_len[c] && evt[c][i].cx == 0)
keir@19906 1074 i++;
keir@19906 1075 /* check evt[c][i] and evt[c][i+1] */
keir@19906 1076 while (i + 1 < evt_len[c]) {
keir@19906 1077 uint64_t len = evt[c][i+1].tsc - evt[c][i].tsc;
keir@19906 1078 int cx = evt[c][i].cx;
keir@19906 1079 tot[cx] += len;
keir@19906 1080 cnt[cx]++;
keir@19906 1081 sum += len;
keir@19906 1082 i++;
keir@19906 1083 }
keir@19906 1084 /* prevent divide zero error */
keir@19906 1085 if (!sum)
keir@19906 1086 sum = 1;
keir@19906 1087 /* print */
keir@19906 1088 printf("CPU%d:\tResidency(ms)\t\tAvg Res(ms)\n", c);
keir@19906 1089 for (i = 0; i < max_cx_num; i++) {
keir@19906 1090 /* prevent divide zero error */
keir@19906 1091 if (!cnt[i])
keir@19906 1092 cnt[i] = 1;
keir@19906 1093 printf(" C%d\t%"PRIu64"\t(%6.2f%%)\t%.2f\n", i,
keir@19906 1094 tot[i]/tsc2ms, 100.0 * tot[i] / (double)sum,
keir@19906 1095 (double)tot[i]/cnt[i]/tsc2ms );
keir@19906 1096 }
keir@19906 1097 printf("\n");
keir@19906 1098 }
keir@19906 1099
keir@19906 1100 void do_average(void)
keir@19906 1101 {
keir@19906 1102 int i;
keir@19906 1103
keir@19906 1104 for (i = 0; i < max_cpu_num; i++)
keir@19906 1105 do_average_per_cpu(i);
keir@19906 1106 }
keir@19906 1107
keir@19906 1108 static void do_exp_ratio_per_cpu(int c)
keir@19906 1109 {
keir@19906 1110 int i;
keir@19906 1111 uint64_t expected[MAX_CX_NR] = { 0 }, sum[MAX_CX_NR] = { 0 };
keir@19906 1112
keir@19906 1113 i = 0;
keir@19906 1114 while (i < evt_len[c] && evt[c][i].cx == 0)
keir@19906 1115 i++;
keir@19906 1116 /* check evt[c][i] and evt[c][i+1] */
keir@19906 1117 while (i + 1 < evt_len[c]) {
keir@19906 1118 uint64_t len;
keir@19906 1119 int cx;
keir@19906 1120
keir@19906 1121 if ((evt[c][i].cx == 0 && evt[c][i+1].cx == 0) ||
keir@19906 1122 (evt[c][i].cx > 0 && evt[c][i+1].cx > 0)) {
keir@19906 1123 i++;
keir@19906 1124 continue;
keir@19906 1125 }
keir@19906 1126 len = evt[c][i+1].tsc - evt[c][i].tsc;
keir@19906 1127 cx = evt[c][i].cx;
keir@19906 1128 if (cx > 0) {
keir@19906 1129 if ((len/tsc2us) <= evt[c][i].expected)
keir@19906 1130 expected[cx]++;
keir@19906 1131 sum[cx]++;
keir@19906 1132 }
keir@19906 1133
keir@19906 1134 i++;
keir@19906 1135 }
keir@19906 1136 printf("********** CPU%d **********\n", c);
keir@19906 1137 for (i = 1; i < max_cx_num; i++) {
keir@19906 1138 if (sum[i] == 0)
keir@19906 1139 printf("C%d\t0\t0\t00.00%%\n", i);
keir@19906 1140 else
keir@19906 1141 printf("C%d\t%"PRIu64"\t%"PRIu64"\t%4.2f%%\n",
keir@19906 1142 i, expected[i], sum[i], 100.0 * (double)expected[i]/(double)sum[i]);
keir@19906 1143 }
keir@19906 1144 }
keir@19906 1145
keir@19906 1146 void do_exp_ratio(void)
keir@19906 1147 {
keir@19906 1148 int i;
keir@19906 1149
keir@19906 1150 if (!is_menu_gov_enabled) {
keir@19906 1151 printf("The file seems doesn't consists the expected/predicted information.\n");
keir@19906 1152 return;
keir@19906 1153 }
keir@19906 1154
keir@19906 1155 printf("Cx\tearly\ttot\tratio(%%)\n");
keir@19906 1156 for (i = 0; i < max_cpu_num; i++)
keir@19906 1157 do_exp_ratio_per_cpu(i);
keir@19906 1158 }
keir@19906 1159
keir@19906 1160 static void do_exp_pred_per_cpu(int c)
keir@19906 1161 {
keir@19906 1162 int i;
keir@19906 1163 uint64_t expected[MAX_CX_NR] = { 0 }, sum[MAX_CX_NR] = { 0 };
keir@19906 1164
keir@19906 1165 i = 0;
keir@19906 1166 while (i < evt_len[c] && evt[c][i].cx == 0)
keir@19906 1167 i++;
keir@19906 1168 /* check evt[c][i] and evt[c][i+1] */
keir@19906 1169 while (i + 1 < evt_len[c]) {
keir@19906 1170 int cx;
keir@19906 1171
keir@19906 1172 if ((evt[c][i].cx == 0 && evt[c][i+1].cx == 0) ||
keir@19906 1173 (evt[c][i].cx > 0 && evt[c][i+1].cx > 0)) {
keir@19906 1174 i++;
keir@19906 1175 continue;
keir@19906 1176 }
keir@19906 1177 cx = evt[c][i].cx;
keir@19906 1178 if (cx > 0) {
keir@19906 1179 if (evt[c][i].expected <= evt[c][i].predicted)
keir@19906 1180 expected[cx]++;
keir@19906 1181 sum[cx]++;
keir@19906 1182 }
keir@19906 1183
keir@19906 1184 i++;
keir@19906 1185 }
keir@19906 1186 printf("********** CPU%d **********\n", c);
keir@19906 1187 for (i = 1; i < max_cx_num; i++) {
keir@19906 1188 if (sum[i] == 0)
keir@19906 1189 printf("C%d\t0\t0\t00.00%%\n", i);
keir@19906 1190 else
keir@19906 1191 printf("C%d\t%"PRIu64"\t%"PRIu64"\t%4.2f%%\n",
keir@19906 1192 i, expected[i], sum[i], 100.0 * (double)expected[i]/(double)sum[i]);
keir@19906 1193 }
keir@19906 1194 }
keir@19906 1195
keir@19906 1196 void do_exp_pred(void)
keir@19906 1197 {
keir@19906 1198 int i;
keir@19906 1199
keir@19906 1200 if (!is_menu_gov_enabled) {
keir@19906 1201 printf("The file seems doesn't consists the expected/predicted information.\n");
keir@19906 1202 return;
keir@19906 1203 }
keir@19906 1204
keir@19906 1205 printf("Cx\texp\ttot\tratio(%%)\n");
keir@19906 1206 for (i = 0; i < max_cpu_num; i++)
keir@19906 1207 do_exp_pred_per_cpu(i);
keir@19906 1208 }
keir@19906 1209