1/* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21#include "config.h" 22#include <strings.h> 23#include <stdlib.h> 24 25#include "util.h" 26#include "BaseMetric.h" 27#include "DbeSession.h" 28#include "Expression.h" 29 30int BaseMetric::last_id = 0; 31 32void 33BaseMetric::init (Type t) 34{ 35 id = last_id++; 36 type = t; 37 aux = NULL; 38 cmd = NULL; 39 username = NULL; 40 hw_ctr = NULL; 41 cond = NULL; 42 val = NULL; 43 expr = NULL; 44 cond_spec = NULL; 45 val_spec = NULL; 46 expr_spec = NULL; 47 legend = NULL; 48 definition = NULL; 49 dependent_bm = NULL; 50 zeroThreshold = 0; 51 clock_unit = (Presentation_clock_unit) 0; 52 for (int ii = 0; ii < NSUBTYPES; ii++) 53 default_visbits[ii] = VAL_NA; 54 valtype = VT_DOUBLE; 55 precision = METRIC_HR_PRECISION; 56 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 57 value_styles = VAL_TIMEVAL | VAL_PERCENT; 58} 59 60BaseMetric::BaseMetric (Type t) 61{ 62 init (t); 63 switch (t) 64 { 65 case CP_LMS_USER: 66 case CP_LMS_SYSTEM: 67 case CP_LMS_WAIT_CPU: 68 case CP_LMS_USER_LOCK: 69 case CP_LMS_TFAULT: 70 case CP_LMS_DFAULT: 71 case OMP_MASTER_THREAD: 72 case CP_TOTAL: 73 case CP_TOTAL_CPU: 74 case CP_LMS_TRAP: 75 case CP_LMS_KFAULT: 76 case CP_LMS_SLEEP: 77 case CP_LMS_STOPPED: 78 case OMP_NONE: 79 case OMP_OVHD: 80 case OMP_WORK: 81 case OMP_IBAR: 82 case OMP_EBAR: 83 case OMP_WAIT: 84 case OMP_SERL: 85 case OMP_RDUC: 86 case OMP_LKWT: 87 case OMP_CTWT: 88 case OMP_ODWT: 89 case OMP_MSTR: 90 case OMP_SNGL: 91 case OMP_ORDD: 92 case CP_KERNEL_CPU: 93 // all of these are floating point, precision = clock profile tick 94 valtype = VT_DOUBLE; 95 precision = METRIC_SIG_PRECISION; 96 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 97 value_styles = VAL_TIMEVAL | VAL_PERCENT; 98 break; 99 case SYNC_WAIT_TIME: 100 case IO_READ_TIME: 101 case IO_WRITE_TIME: 102 case IO_OTHER_TIME: 103 case IO_ERROR_TIME: 104 // all of these are floating point, precision = hrtime tick 105 valtype = VT_DOUBLE; 106 precision = METRIC_HR_PRECISION; 107 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 108 value_styles = VAL_TIMEVAL | VAL_PERCENT; 109 break; 110 case SYNC_WAIT_COUNT: 111 case HEAP_ALLOC_CNT: 112 case HEAP_LEAK_CNT: 113 case IO_READ_CNT: 114 case IO_WRITE_CNT: 115 case IO_OTHER_CNT: 116 case IO_ERROR_CNT: 117 valtype = VT_LLONG; 118 precision = 1; 119 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 120 value_styles = VAL_VALUE | VAL_PERCENT; 121 break; 122 case RACCESS: 123 case DEADLOCKS: 124 // all of these are integer 125 valtype = VT_LLONG; 126 precision = 1; 127 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 128 value_styles = VAL_VALUE | VAL_PERCENT; 129 zeroThreshold = 1; 130 break; 131 case HEAP_ALLOC_BYTES: 132 case HEAP_LEAK_BYTES: 133 case IO_READ_BYTES: 134 case IO_WRITE_BYTES: 135 // all of these are longlong 136 valtype = VT_ULLONG; 137 precision = 1; 138 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 139 value_styles = VAL_VALUE | VAL_PERCENT; 140 break; 141 case SIZES: 142 valtype = VT_LLONG; 143 precision = 1; 144 flavors = STATIC; 145 value_styles = VAL_VALUE; 146 break; 147 case ADDRESS: 148 valtype = VT_ADDRESS; 149 precision = 1; 150 flavors = STATIC; 151 value_styles = VAL_VALUE; 152 break; 153 case ONAME: 154 valtype = VT_LABEL; 155 precision = 0; 156 flavors = STATIC; 157 value_styles = VAL_VALUE; 158 break; 159 case HWCNTR: // We should call the other constructor for hwc metric 160 default: 161 abort (); 162 } 163 specify (); 164} 165 166// Constructor for linked HW counters (base counter) 167BaseMetric::BaseMetric (Hwcentry *ctr, const char* _aux, const char* _username, 168 int v_styles, BaseMetric* _dependent_bm) 169{ 170 hwc_init (ctr, _aux, _aux, _username, v_styles); 171 dependent_bm = _dependent_bm; 172} 173 174// Constructor for linked HW counters (derived counter) 175 176BaseMetric::BaseMetric (Hwcentry *ctr, const char *_aux, const char *_cmdname, 177 const char *_username, int v_styles) 178{ 179 hwc_init (ctr, _aux, _cmdname, _username, v_styles); 180} 181 182void 183BaseMetric::hwc_init (Hwcentry *ctr, const char* _aux, const char* _cmdname, 184 const char* _username, int v_styles) 185{ 186 init (HWCNTR); 187 aux = dbe_strdup (_aux); // HWC identifier 188 cmd = dbe_strdup (_cmdname); // may differ from _aux for cycles->time hwcs 189 username = dbe_strdup (_username); 190 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 191 value_styles = v_styles | VAL_PERCENT; 192 if ((value_styles & (VAL_TIMEVAL | VAL_VALUE)) == VAL_TIMEVAL) 193 valtype = VT_DOUBLE; 194 else 195 valtype = VT_ULLONG; 196 if (ABST_MEMSPACE_ENABLED (ctr->memop)) 197 flavors |= DATASPACE; // only for ctrs with memop definitions 198 hw_ctr = ctr; 199 specify (); 200} 201 202// Constructor for derived metrics 203BaseMetric::BaseMetric (const char *_cmd, const char *_username, 204 Definition *def) 205{ 206 init (DERIVED); 207 cmd = dbe_strdup (_cmd); 208 username = dbe_strdup (_username); 209 aux = dbe_strdup (_cmd); 210 definition = def; 211 flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; 212 clock_unit = CUNIT_NULL; // should it be CUNIT_TIME or 0 or something? 213 214 /* we're not going to process packets for derived metrics */ 215 packet_type = (ProfData_type) (-1); 216 value_styles = VAL_VALUE; 217 valtype = VT_DOUBLE; 218 precision = 1000; 219} 220 221// Copy constructor 222BaseMetric::BaseMetric (const BaseMetric& m) 223{ 224 id = m.id; 225 type = m.type; 226 aux = dbe_strdup (m.aux); 227 cmd = dbe_strdup (m.cmd); 228 username = dbe_strdup (m.username); 229 flavors = m.flavors; 230 value_styles = m.value_styles; 231 valtype = m.valtype; 232 precision = m.precision; 233 hw_ctr = m.hw_ctr; 234 packet_type = m.packet_type; 235 zeroThreshold = m.zeroThreshold; 236 clock_unit = m.clock_unit; 237 for (int ii = 0; ii < NSUBTYPES; ii++) 238 default_visbits[ii] = m.default_visbits[ii]; 239 if (m.cond_spec) 240 { 241 cond_spec = strdup (m.cond_spec); 242 cond = m.cond->copy (); 243 } 244 else 245 { 246 cond = NULL; 247 cond_spec = NULL; 248 } 249 if (m.val_spec) 250 { 251 val_spec = strdup (m.val_spec); 252 val = m.val->copy (); 253 } 254 else 255 { 256 val = NULL; 257 val_spec = NULL; 258 } 259 if (m.expr_spec) 260 { 261 expr_spec = strdup (m.expr_spec); 262 expr = m.expr->copy (); 263 } 264 else 265 { 266 expr = NULL; 267 expr_spec = NULL; 268 } 269 legend = dbe_strdup (m.legend); 270 definition = NULL; 271 if (m.definition) 272 definition = Definition::add_definition (m.definition->def); 273 dependent_bm = m.dependent_bm; 274} 275 276BaseMetric::~BaseMetric () 277{ 278 free (aux); 279 free (cmd); 280 free (cond_spec); 281 free (val_spec); 282 free (expr_spec); 283 free (legend); 284 free (username); 285 delete cond; 286 delete val; 287 delete expr; 288 delete definition; 289} 290 291bool 292BaseMetric::is_internal () 293{ 294 return (get_value_styles () & VAL_INTERNAL) != 0; 295} 296 297int 298BaseMetric::get_default_visbits (SubType subtype) 299{ 300 int rc = VAL_NA; 301 switch (subtype) 302 { 303 case STATIC: 304 case EXCLUSIVE: 305 rc = default_visbits[0]; 306 break; 307 case INCLUSIVE: 308 rc = default_visbits[1]; 309 break; 310 default: 311 break; 312 } 313 return rc; 314} 315 316void 317BaseMetric::set_default_visbits (SubType subtype, int _visbits) 318{ 319 switch (subtype) 320 { 321 case STATIC: 322 case EXCLUSIVE: 323 default_visbits[0] = _visbits; 324 break; 325 case INCLUSIVE: 326 default_visbits[1] = _visbits; 327 break; 328 default: 329 break; 330 } 331} 332 333void 334BaseMetric::set_cond_spec (char *_cond_spec) 335{ 336 if (cond_spec) 337 { 338 free (cond_spec); 339 delete cond; 340 cond_spec = NULL; 341 cond = NULL; 342 } 343 if (_cond_spec) 344 { 345 cond = dbeSession->ql_parse (_cond_spec); 346 if (cond == NULL) 347 { 348 fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _cond_spec); 349 abort (); 350 } 351 cond_spec = dbe_strdup (_cond_spec); 352 } 353} 354 355void 356BaseMetric::set_val_spec (char *_val_spec) 357{ 358 if (val_spec) 359 { 360 free (val_spec); 361 delete val; 362 val_spec = NULL; 363 val = NULL; 364 } 365 if (_val_spec) 366 { 367 val = dbeSession->ql_parse (_val_spec); 368 if (val == NULL) 369 { 370 fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _val_spec); 371 abort (); 372 } 373 val_spec = dbe_strdup (_val_spec); 374 } 375} 376 377void 378BaseMetric::set_expr_spec (char *_expr_spec) 379{ 380 id = last_id++; 381 if (expr_spec) 382 { 383 free (expr_spec); 384 delete expr; 385 expr_spec = NULL; 386 expr = NULL; 387 } 388 if (_expr_spec) 389 { 390 expr = dbeSession->ql_parse (_expr_spec); 391 if (expr == NULL) 392 { 393 fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _expr_spec); 394 return; 395 } 396 expr_spec = dbe_strdup (_expr_spec); 397 } 398} 399 400void 401BaseMetric::specify_mstate_metric (int st) 402{ 403 char buf[128]; 404 snprintf (buf, sizeof (buf), NTXT ("MSTATE==%d"), st); 405 specify_prof_metric (buf); 406} 407 408void 409BaseMetric::specify_ompstate_metric (int st) 410{ 411 char buf[128]; 412 snprintf (buf, sizeof (buf), NTXT ("OMPSTATE==%d"), st); 413 specify_prof_metric (buf); 414} 415 416void 417BaseMetric::specify_prof_metric (char *_cond_spec) 418{ 419 packet_type = DATA_CLOCK; 420 specify_metric (_cond_spec, NTXT ("NTICK_USEC")); // microseconds 421} 422 423void 424BaseMetric::specify_metric (char *_cond_spec, char *_val_spec) 425{ 426 set_cond_spec (_cond_spec); 427 set_val_spec (_val_spec); 428} 429 430void 431BaseMetric::specify () 432{ 433 enum 434 { 435 IDLE_STATE_BITS = 436 (1 << OMP_IDLE_STATE) | (1 << OMP_IBAR_STATE) | (1 << OMP_EBAR_STATE) | 437 (1 << OMP_LKWT_STATE) | (1 << OMP_CTWT_STATE) | (1 << OMP_ODWT_STATE) | 438 (1 << OMP_ATWT_STATE) | (1 << OMP_TSKWT_STATE), 439 LMS_USER_BITS = 440 (1 << OMP_NO_STATE) | (1 << OMP_WORK_STATE) | (1 << OMP_SERL_STATE) | 441 (1 << OMP_RDUC_STATE) 442 }; 443 444 char buf[256]; 445 char buf2[256]; 446 packet_type = (ProfData_type) - 1; // illegal value 447 clock_unit = CUNIT_TIME; 448 switch (type) 449 { 450 case SIZES: 451 username = dbe_strdup (GTXT ("Size")); 452 clock_unit = CUNIT_BYTES; 453 cmd = dbe_strdup (NTXT ("size")); 454 break; 455 case ADDRESS: 456 username = dbe_strdup (GTXT ("PC Address")); 457 cmd = dbe_strdup (NTXT ("address")); 458 break; 459 case ONAME: 460 username = dbe_strdup (GTXT ("Name")); 461 cmd = dbe_strdup (NTXT ("name")); 462 break; 463 case CP_LMS_SYSTEM: 464 username = dbe_strdup (GTXT ("System CPU Time")); 465 specify_mstate_metric (LMS_SYSTEM); 466 cmd = dbe_strdup (NTXT ("system")); 467 break; 468 case CP_TOTAL_CPU: 469 username = dbe_strdup (GTXT ("Total CPU Time")); 470 snprintf (buf, sizeof (buf), 471 "(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)", 472 LMS_USER, LMS_SYSTEM, LMS_TRAP, LMS_LINUX_CPU); 473 specify_prof_metric (buf); 474 cmd = dbe_strdup (NTXT ("totalcpu")); 475 break; 476 case CP_TOTAL: 477 username = dbe_strdup (GTXT ("Total Thread Time")); 478 snprintf (buf, sizeof (buf), NTXT ("(MSTATE!=%d)&&(MSTATE!=%d)"), 479 LMS_KERNEL_CPU, LMS_LINUX_CPU); 480 specify_prof_metric (buf); 481 cmd = dbe_strdup (NTXT ("total")); 482 break; 483 case CP_KERNEL_CPU: 484 username = dbe_strdup (GTXT ("Kernel CPU Time")); 485 specify_mstate_metric (LMS_KERNEL_CPU); 486 cmd = dbe_strdup (NTXT ("kcpu")); 487 break; 488 case OMP_MASTER_THREAD: 489 username = dbe_strdup (GTXT ("Master Thread Time")); 490 specify_prof_metric (NTXT ("LWPID==1")); 491 cmd = dbe_strdup (NTXT ("masterthread")); 492 break; 493 case CP_LMS_USER: 494 username = dbe_strdup (GTXT ("User CPU Time")); 495 specify_mstate_metric (LMS_USER); 496 cmd = dbe_strdup (NTXT ("user")); 497 break; 498 case CP_LMS_WAIT_CPU: 499 username = dbe_strdup (GTXT ("Wait CPU Time")); 500 specify_mstate_metric (LMS_WAIT_CPU); 501 cmd = dbe_strdup (NTXT ("wait")); 502 break; 503 case CP_LMS_USER_LOCK: 504 username = dbe_strdup (GTXT ("User Lock Time")); 505 specify_mstate_metric (LMS_USER_LOCK); 506 cmd = dbe_strdup (NTXT ("lock")); 507 break; 508 case CP_LMS_TFAULT: 509 username = dbe_strdup (GTXT ("Text Page Fault Time")); 510 specify_mstate_metric (LMS_TFAULT); 511 cmd = dbe_strdup (NTXT ("textpfault")); 512 break; 513 case CP_LMS_DFAULT: 514 username = dbe_strdup (GTXT ("Data Page Fault Time")); 515 specify_mstate_metric (LMS_DFAULT); 516 cmd = dbe_strdup (NTXT ("datapfault")); 517 break; 518 case CP_LMS_TRAP: 519 username = dbe_strdup (GTXT ("Trap CPU Time")); 520 specify_mstate_metric (LMS_TRAP); 521 cmd = dbe_strdup (NTXT ("trap")); 522 break; 523 case CP_LMS_KFAULT: 524 username = dbe_strdup (GTXT ("Kernel Page Fault Time")); 525 specify_mstate_metric (LMS_KFAULT); 526 cmd = dbe_strdup (NTXT ("kernelpfault")); 527 break; 528 case CP_LMS_SLEEP: 529 username = dbe_strdup (GTXT ("Sleep Time")); 530 specify_mstate_metric (LMS_SLEEP); 531 cmd = dbe_strdup (NTXT ("sleep")); 532 break; 533 case CP_LMS_STOPPED: 534 username = dbe_strdup (GTXT ("Stopped Time")); 535 specify_mstate_metric (LMS_STOPPED); 536 cmd = dbe_strdup (NTXT ("stop")); 537 break; 538 case OMP_OVHD: 539 username = dbe_strdup (GTXT ("OpenMP Overhead Time")); 540 specify_ompstate_metric (OMP_OVHD_STATE); 541 cmd = dbe_strdup (NTXT ("ompovhd")); 542 break; 543 case OMP_WORK: 544 username = dbe_strdup (GTXT ("OpenMP Work Time")); 545 snprintf (buf, sizeof (buf), 546 NTXT ("(OMPSTATE>=0) && (MSTATE==%d) && ((1<<OMPSTATE) & %d)"), 547 LMS_USER, LMS_USER_BITS); 548 specify_prof_metric (buf); 549 cmd = dbe_strdup (NTXT ("ompwork")); 550 break; 551 case OMP_WAIT: 552 username = dbe_strdup (GTXT ("OpenMP Wait Time")); 553 snprintf (buf, sizeof (buf), 554 "OMPSTATE>=0 && ((1<<OMPSTATE) & ((MSTATE!=%d) ? %d : %d))", 555 LMS_USER, (LMS_USER_BITS | IDLE_STATE_BITS), IDLE_STATE_BITS); 556 specify_prof_metric (buf); 557 cmd = dbe_strdup (NTXT ("ompwait")); 558 break; 559 case OMP_IBAR: 560 username = dbe_strdup (GTXT ("OpenMP Implicit Barrier Time")); 561 specify_ompstate_metric (OMP_IBAR_STATE); 562 cmd = dbe_strdup (NTXT ("ompibar")); 563 break; 564 case OMP_EBAR: 565 username = dbe_strdup (GTXT ("OpenMP Explicit Barrier Time")); 566 specify_ompstate_metric (OMP_EBAR_STATE); 567 cmd = dbe_strdup (NTXT ("ompebar")); 568 break; 569 case OMP_SERL: 570 username = dbe_strdup (GTXT ("OpenMP Serial Time")); 571 specify_ompstate_metric (OMP_SERL_STATE); 572 cmd = dbe_strdup (NTXT ("ompserl")); 573 break; 574 case OMP_RDUC: 575 username = dbe_strdup (GTXT ("OpenMP Reduction Time")); 576 specify_ompstate_metric (OMP_RDUC_STATE); 577 cmd = dbe_strdup (NTXT ("omprduc")); 578 break; 579 case OMP_LKWT: 580 username = dbe_strdup (GTXT ("OpenMP Lock Wait Time")); 581 specify_ompstate_metric (OMP_LKWT_STATE); 582 cmd = dbe_strdup (NTXT ("omplkwt")); 583 break; 584 case OMP_CTWT: 585 username = dbe_strdup (GTXT ("OpenMP Critical Section Wait Time")); 586 specify_ompstate_metric (OMP_CTWT_STATE); 587 cmd = dbe_strdup (NTXT ("ompctwt")); 588 break; 589 case OMP_ODWT: 590 username = dbe_strdup (GTXT ("OpenMP Ordered Section Wait Time")); 591 specify_ompstate_metric (OMP_ODWT_STATE); 592 cmd = dbe_strdup (NTXT ("ompodwt")); 593 break; 594 case SYNC_WAIT_TIME: 595 packet_type = DATA_SYNCH; 596 username = dbe_strdup (GTXT ("Sync Wait Time")); 597 snprintf (buf, sizeof (buf), NTXT ("(EVT_TIME)/%lld"), 598 (long long) (NANOSEC / METRIC_HR_PRECISION)); 599 specify_metric (NULL, buf); 600 cmd = dbe_strdup (NTXT ("sync")); 601 break; 602 case SYNC_WAIT_COUNT: 603 packet_type = DATA_SYNCH; 604 username = dbe_strdup (GTXT ("Sync Wait Count")); 605 specify_metric (NULL, NTXT ("1")); 606 cmd = dbe_strdup (NTXT ("syncn")); 607 break; 608 case HEAP_ALLOC_CNT: 609 packet_type = DATA_HEAP; 610 username = dbe_strdup (GTXT ("Allocations")); 611 snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"), 612 FREE_TRACE, MUNMAP_TRACE); 613 specify_metric (buf, NTXT ("1")); 614 cmd = dbe_strdup (NTXT ("heapalloccnt")); 615 break; 616 case HEAP_ALLOC_BYTES: 617 packet_type = DATA_HEAP; 618 username = dbe_strdup (GTXT ("Bytes Allocated")); 619 snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"), 620 FREE_TRACE, MUNMAP_TRACE); 621 specify_metric (buf, NTXT ("HSIZE")); 622 cmd = dbe_strdup (NTXT ("heapallocbytes")); 623 break; 624 case HEAP_LEAK_CNT: 625 packet_type = DATA_HEAP; 626 username = dbe_strdup (GTXT ("Leaks")); 627 snprintf (buf, sizeof (buf), "(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR&&HLEAKED", 628 FREE_TRACE, MUNMAP_TRACE); 629 specify_metric (buf, NTXT ("1")); 630 cmd = dbe_strdup (NTXT ("heapleakcnt")); 631 break; 632 case HEAP_LEAK_BYTES: 633 packet_type = DATA_HEAP; 634 username = dbe_strdup (GTXT ("Bytes Leaked")); 635 snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"), 636 FREE_TRACE, MUNMAP_TRACE); 637 specify_metric (buf, NTXT ("HLEAKED")); 638 cmd = dbe_strdup (NTXT ("heapleakbytes")); 639 break; 640 641 case IO_READ_CNT: 642 packet_type = DATA_IOTRACE; 643 username = dbe_strdup (GTXT ("Read Count")); 644 snprintf (buf, sizeof (buf), "(IOTYPE==%d)", READ_TRACE); 645 specify_metric (buf, NTXT ("1")); 646 cmd = dbe_strdup (NTXT ("ioreadcnt")); 647 break; 648 case IO_WRITE_CNT: 649 packet_type = DATA_IOTRACE; 650 username = dbe_strdup (GTXT ("Write Count")); 651 snprintf (buf, sizeof (buf), "(IOTYPE==%d)", WRITE_TRACE); 652 specify_metric (buf, NTXT ("1")); 653 cmd = dbe_strdup (NTXT ("iowritecnt")); 654 break; 655 case IO_OTHER_CNT: 656 packet_type = DATA_IOTRACE; 657 username = dbe_strdup (GTXT ("Other I/O Count")); 658 snprintf (buf, sizeof (buf), "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)", 659 OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE); 660 specify_metric (buf, NTXT ("1")); 661 cmd = dbe_strdup (NTXT ("ioothercnt")); 662 break; 663 case IO_ERROR_CNT: 664 packet_type = DATA_IOTRACE; 665 username = dbe_strdup (GTXT ("I/O Error Count")); 666 snprintf (buf, sizeof (buf), 667 "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)", 668 READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR, 669 CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR); 670 specify_metric (buf, NTXT ("1")); 671 cmd = dbe_strdup (NTXT ("ioerrorcnt")); 672 break; 673 case IO_READ_BYTES: 674 packet_type = DATA_IOTRACE; 675 username = dbe_strdup (GTXT ("Read Bytes")); 676 snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&IONBYTE"), 677 READ_TRACE); 678 specify_metric (buf, NTXT ("IONBYTE")); 679 cmd = dbe_strdup (NTXT ("ioreadbytes")); 680 break; 681 case IO_WRITE_BYTES: 682 packet_type = DATA_IOTRACE; 683 username = dbe_strdup (GTXT ("Write Bytes")); 684 snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&IONBYTE", WRITE_TRACE); 685 specify_metric (buf, NTXT ("IONBYTE")); 686 cmd = dbe_strdup (NTXT ("iowritebytes")); 687 break; 688 case IO_READ_TIME: 689 packet_type = DATA_IOTRACE; 690 username = dbe_strdup (GTXT ("Read Time")); 691 snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&EVT_TIME", READ_TRACE); 692 snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), 693 (long long) (NANOSEC / METRIC_HR_PRECISION)); 694 specify_metric (buf, buf2); 695 cmd = dbe_strdup (NTXT ("ioreadtime")); 696 break; 697 case IO_WRITE_TIME: 698 packet_type = DATA_IOTRACE; 699 username = dbe_strdup (GTXT ("Write Time")); 700 snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&EVT_TIME"), 701 WRITE_TRACE); 702 snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), 703 (long long) (NANOSEC / METRIC_HR_PRECISION)); 704 specify_metric (buf, buf2); 705 cmd = dbe_strdup (NTXT ("iowritetime")); 706 break; 707 case IO_OTHER_TIME: 708 packet_type = DATA_IOTRACE; 709 username = dbe_strdup (GTXT ("Other I/O Time")); 710 snprintf (buf, sizeof (buf), 711 "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME", 712 OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE); 713 snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), 714 (long long) (NANOSEC / METRIC_HR_PRECISION)); 715 specify_metric (buf, buf2); 716 cmd = dbe_strdup (NTXT ("ioothertime")); 717 break; 718 case IO_ERROR_TIME: 719 packet_type = DATA_IOTRACE; 720 username = dbe_strdup (GTXT ("I/O Error Time")); 721 snprintf (buf, sizeof (buf), 722 "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME", 723 READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR, 724 CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR); 725 snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), 726 (long long) (NANOSEC / METRIC_HR_PRECISION)); 727 specify_metric (buf, buf2); 728 cmd = dbe_strdup (NTXT ("ioerrortime")); 729 break; 730 case RACCESS: 731 packet_type = DATA_RACE; 732 username = dbe_strdup (GTXT ("Race Accesses")); 733 specify_metric (NULL, NTXT ("RCNT")); 734 cmd = dbe_strdup (NTXT ("raccess")); 735 break; 736 case DEADLOCKS: 737 packet_type = DATA_DLCK; 738 username = dbe_strdup (GTXT ("Deadlocks")); 739 specify_metric (NULL, NTXT ("1")); 740 cmd = dbe_strdup (NTXT ("deadlocks")); 741 break; 742 case HWCNTR: 743 packet_type = DATA_HWC; 744 // username, cmd, and aux set by hwc constructor 745 if (valtype == VT_DOUBLE) 746 { 747 if (hw_ctr->timecvt > 0) // CPU cycles 748 specify_metric (NULL, NTXT ("((HWCINT*1000000)/FREQ_MHZ)")); 749 else if (hw_ctr->timecvt < 0) 750 { // reference clock (frequency is -timecvt MHz) 751 snprintf (buf, sizeof (buf), NTXT ("((HWCINT*1000000)/%d)"), -hw_ctr->timecvt); 752 specify_metric (NULL, buf); 753 } 754 else // shouldn't happen 755 specify_metric (NULL, NTXT ("0")); 756 // resulting unit: seconds * 1e12 757 precision = 1000000LL * 1000000LL; // Seconds * 1e12 758 } 759 else 760 { 761 specify_metric (NULL, NTXT ("HWCINT")); 762 precision = 1; 763 } 764 break; 765 case OMP_MSTR: 766 case OMP_SNGL: 767 case OMP_ORDD: 768 case OMP_NONE: 769 default: 770 username = dbe_strdup (GTXT ("****")); 771 fprintf (stderr, "BaseMetric::init Undefined basemetric %s\n", 772 get_basetype_name ()); 773 } 774} 775 776#define CASE_S(x) case x: s = (char *) #x; break 777char * 778BaseMetric::get_basetype_name () 779{ 780 static char buf[128]; 781 char *s; 782 switch (type) 783 { 784 CASE_S (CP_LMS_SYSTEM); 785 CASE_S (CP_TOTAL_CPU); 786 CASE_S (CP_TOTAL); 787 CASE_S (OMP_MASTER_THREAD); 788 CASE_S (CP_LMS_USER); 789 CASE_S (CP_LMS_WAIT_CPU); 790 CASE_S (CP_LMS_USER_LOCK); 791 CASE_S (CP_LMS_TFAULT); 792 CASE_S (CP_LMS_DFAULT); 793 CASE_S (CP_LMS_TRAP); 794 CASE_S (CP_LMS_KFAULT); 795 CASE_S (CP_LMS_SLEEP); 796 CASE_S (CP_LMS_STOPPED); 797 CASE_S (OMP_NONE); 798 CASE_S (OMP_OVHD); 799 CASE_S (OMP_WORK); 800 CASE_S (OMP_IBAR); 801 CASE_S (OMP_EBAR); 802 CASE_S (OMP_WAIT); 803 CASE_S (OMP_SERL); 804 CASE_S (OMP_RDUC); 805 CASE_S (OMP_LKWT); 806 CASE_S (OMP_CTWT); 807 CASE_S (OMP_ODWT); 808 CASE_S (OMP_MSTR); 809 CASE_S (OMP_SNGL); 810 CASE_S (OMP_ORDD); 811 CASE_S (CP_KERNEL_CPU); 812 CASE_S (SYNC_WAIT_TIME); 813 CASE_S (IO_READ_TIME); 814 CASE_S (IO_WRITE_TIME); 815 CASE_S (IO_OTHER_TIME); 816 CASE_S (IO_ERROR_TIME); 817 CASE_S (HWCNTR); 818 CASE_S (SYNC_WAIT_COUNT); 819 CASE_S (HEAP_ALLOC_CNT); 820 CASE_S (HEAP_LEAK_CNT); 821 CASE_S (IO_READ_CNT); 822 CASE_S (IO_WRITE_CNT); 823 CASE_S (IO_OTHER_CNT); 824 CASE_S (IO_ERROR_CNT); 825 CASE_S (RACCESS); 826 CASE_S (DEADLOCKS); 827 CASE_S (HEAP_ALLOC_BYTES); 828 CASE_S (HEAP_LEAK_BYTES); 829 CASE_S (IO_READ_BYTES); 830 CASE_S (IO_WRITE_BYTES); 831 CASE_S (SIZES); 832 CASE_S (ADDRESS); 833 CASE_S (ONAME); 834 CASE_S (DERIVED); 835 default: 836 s = NTXT ("???"); 837 break; 838 } 839 snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type); 840 buf[sizeof (buf) - 1] = 0; 841 return buf; 842} 843 844char * 845BaseMetric::dump () 846{ 847 int len = 4; 848 char *msg = dbe_sprintf (NTXT ("id=%d %s aux='%s' cmd='%s' user_name='%s' expr_spec='%s'\n" 849 "%*c cond_spec='%s' val_spec='%s'"), 850 id, get_basetype_name (), STR (aux), STR (cmd), 851 STR (username), STR (expr_spec), 852 len, ' ', STR (cond_spec), STR (val_spec)); 853 return msg; 854} 855 856Histable * 857BaseMetric::get_comparable_obj (Histable *obj) 858{ 859 if (obj == NULL || expr == NULL) 860 return obj; 861 if (strncmp (expr_spec, NTXT ("EXPGRID=="), 9) == 0) 862 { 863 int n = atoi (expr_spec + 9); 864 Vector<Histable *> *cmpObjs = obj->get_comparable_objs (); 865 if (cmpObjs && cmpObjs->size () >= n) 866 return cmpObjs->get (n - 1); 867 return NULL; 868 } 869 return obj; 870} 871 872Definition::Definition (opType _op) 873{ 874 op = _op; 875 bm = NULL; 876 arg1 = NULL; 877 arg2 = NULL; 878 def = NULL; 879 dependencies = NULL; 880 map = NULL; 881 index = 0; 882} 883 884Definition::~Definition () 885{ 886 delete arg1; 887 delete arg2; 888 delete dependencies; 889 delete[] map; 890} 891 892Vector<BaseMetric *> * 893Definition::get_dependencies () 894{ 895 if (dependencies == NULL) 896 { 897 if (arg1 && arg1->bm && arg2 && arg2->bm) 898 { 899 dependencies = new Vector<BaseMetric *>(2); 900 arg1->index = dependencies->size (); 901 dependencies->append (arg1->bm); 902 arg2->index = dependencies->size (); 903 dependencies->append (arg2->bm); 904 map = new long[2]; 905 } 906 } 907 return dependencies; 908} 909 910long * 911Definition::get_map () 912{ 913 get_dependencies (); 914 return map; 915} 916 917Definition * 918Definition::add_definition (char *_def) 919{ 920 // parse the definition 921 char *op_ptr = strchr (_def, '/'); 922 if (op_ptr == NULL) 923 { 924 // it's a primitive metric 925 BaseMetric *bm = dbeSession->find_base_reg_metric (_def); 926 if (bm) 927 { 928 Definition *p = new Definition (opPrimitive); 929 p->bm = bm; 930 return p; 931 } 932 return NULL; // BaseMetric is not yet specified 933 } 934 Definition *p2 = add_definition (op_ptr + 1); 935 if (p2 == NULL) 936 return NULL; 937 _def = dbe_strdup (_def); 938 op_ptr = strchr (_def, '/'); 939 *op_ptr = 0; 940 Definition *p1 = add_definition (_def); 941 if (p1) 942 { 943 *op_ptr = '/'; 944 Definition *p = new Definition (opDivide); 945 p->arg1 = p1; 946 p->arg2 = p2; 947 p->def = _def; 948 return p; 949 } 950 free (_def); 951 delete p1; 952 delete p2; 953 return NULL; 954} 955 956double 957Definition::eval (long *indexes, TValue *values) 958{ 959 switch (op) 960 { 961 case opPrimitive: 962 return values[indexes[index]].to_double (); 963 case opDivide: 964 { 965 double x2 = arg2->eval (indexes, values); 966 if (x2 == 0) 967 return 0.; 968 double x1 = arg1->eval (indexes, values); 969 return x1 / x2; 970 } 971 default: 972 fprintf (stderr, GTXT ("unknown expression\n")); 973 return 0.; 974 } 975} 976