| /* Copyright (C) 2021-2024 Free Software Foundation, Inc. |
| Contributed by Oracle. |
| |
| This file is part of GNU Binutils. |
| |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| This program is distributed in the hope that 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, write to the Free Software |
| Foundation, 51 Franklin Street - Fifth Floor, Boston, |
| MA 02110-1301, USA. */ |
| |
| #include "config.h" |
| #include <strings.h> |
| #include <stdlib.h> |
| |
| #include "util.h" |
| #include "BaseMetric.h" |
| #include "DbeSession.h" |
| #include "Expression.h" |
| |
| int BaseMetric::last_id = 0; |
| |
| void |
| BaseMetric::init (Type t) |
| { |
| id = last_id++; |
| type = t; |
| aux = NULL; |
| cmd = NULL; |
| username = NULL; |
| hw_ctr = NULL; |
| cond = NULL; |
| val = NULL; |
| expr = NULL; |
| cond_spec = NULL; |
| val_spec = NULL; |
| expr_spec = NULL; |
| legend = NULL; |
| definition = NULL; |
| dependent_bm = NULL; |
| zeroThreshold = 0; |
| clock_unit = (Presentation_clock_unit) 0; |
| for (int ii = 0; ii < NSUBTYPES; ii++) |
| default_visbits[ii] = VAL_NA; |
| valtype = VT_DOUBLE; |
| precision = METRIC_HR_PRECISION; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = VAL_TIMEVAL | VAL_PERCENT; |
| } |
| |
| BaseMetric::BaseMetric (Type t) |
| { |
| init (t); |
| switch (t) |
| { |
| case CP_LMS_USER: |
| case CP_LMS_SYSTEM: |
| case CP_LMS_WAIT_CPU: |
| case CP_LMS_USER_LOCK: |
| case CP_LMS_TFAULT: |
| case CP_LMS_DFAULT: |
| case OMP_MASTER_THREAD: |
| case CP_TOTAL: |
| case CP_TOTAL_CPU: |
| case CP_LMS_TRAP: |
| case CP_LMS_KFAULT: |
| case CP_LMS_SLEEP: |
| case CP_LMS_STOPPED: |
| case OMP_NONE: |
| case OMP_OVHD: |
| case OMP_WORK: |
| case OMP_IBAR: |
| case OMP_EBAR: |
| case OMP_WAIT: |
| case OMP_SERL: |
| case OMP_RDUC: |
| case OMP_LKWT: |
| case OMP_CTWT: |
| case OMP_ODWT: |
| case OMP_MSTR: |
| case OMP_SNGL: |
| case OMP_ORDD: |
| case CP_KERNEL_CPU: |
| // all of these are floating point, precision = clock profile tick |
| valtype = VT_DOUBLE; |
| precision = METRIC_SIG_PRECISION; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = VAL_TIMEVAL | VAL_PERCENT; |
| break; |
| case SYNC_WAIT_TIME: |
| case IO_READ_TIME: |
| case IO_WRITE_TIME: |
| case IO_OTHER_TIME: |
| case IO_ERROR_TIME: |
| // all of these are floating point, precision = hrtime tick |
| valtype = VT_DOUBLE; |
| precision = METRIC_HR_PRECISION; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = VAL_TIMEVAL | VAL_PERCENT; |
| break; |
| case SYNC_WAIT_COUNT: |
| case HEAP_ALLOC_CNT: |
| case HEAP_LEAK_CNT: |
| case IO_READ_CNT: |
| case IO_WRITE_CNT: |
| case IO_OTHER_CNT: |
| case IO_ERROR_CNT: |
| valtype = VT_LLONG; |
| precision = 1; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = VAL_VALUE | VAL_PERCENT; |
| break; |
| case RACCESS: |
| case DEADLOCKS: |
| // all of these are integer |
| valtype = VT_LLONG; |
| precision = 1; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = VAL_VALUE | VAL_PERCENT; |
| zeroThreshold = 1; |
| break; |
| case HEAP_ALLOC_BYTES: |
| case HEAP_LEAK_BYTES: |
| case IO_READ_BYTES: |
| case IO_WRITE_BYTES: |
| // all of these are longlong |
| valtype = VT_ULLONG; |
| precision = 1; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = VAL_VALUE | VAL_PERCENT; |
| break; |
| case SIZES: |
| valtype = VT_LLONG; |
| precision = 1; |
| flavors = STATIC; |
| value_styles = VAL_VALUE; |
| break; |
| case ADDRESS: |
| valtype = VT_ADDRESS; |
| precision = 1; |
| flavors = STATIC; |
| value_styles = VAL_VALUE; |
| break; |
| case ONAME: |
| valtype = VT_LABEL; |
| precision = 0; |
| flavors = STATIC; |
| value_styles = VAL_VALUE; |
| break; |
| case HWCNTR: // We should call the other constructor for hwc metric |
| default: |
| abort (); |
| } |
| specify (); |
| } |
| |
| // Constructor for linked HW counters (base counter) |
| BaseMetric::BaseMetric (Hwcentry *ctr, const char* _aux, const char* _username, |
| int v_styles, BaseMetric* _dependent_bm) |
| { |
| hwc_init (ctr, _aux, _aux, _username, v_styles); |
| dependent_bm = _dependent_bm; |
| } |
| |
| // Constructor for linked HW counters (derived counter) |
| |
| BaseMetric::BaseMetric (Hwcentry *ctr, const char *_aux, const char *_cmdname, |
| const char *_username, int v_styles) |
| { |
| hwc_init (ctr, _aux, _cmdname, _username, v_styles); |
| } |
| |
| void |
| BaseMetric::hwc_init (Hwcentry *ctr, const char* _aux, const char* _cmdname, |
| const char* _username, int v_styles) |
| { |
| init (HWCNTR); |
| aux = dbe_strdup (_aux); // HWC identifier |
| cmd = dbe_strdup (_cmdname); // may differ from _aux for cycles->time hwcs |
| username = dbe_strdup (_username); |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| value_styles = v_styles | VAL_PERCENT; |
| if ((value_styles & (VAL_TIMEVAL | VAL_VALUE)) == VAL_TIMEVAL) |
| valtype = VT_DOUBLE; |
| else |
| valtype = VT_ULLONG; |
| if (ABST_MEMSPACE_ENABLED (ctr->memop)) |
| flavors |= DATASPACE; // only for ctrs with memop definitions |
| hw_ctr = ctr; |
| specify (); |
| } |
| |
| // Constructor for derived metrics |
| BaseMetric::BaseMetric (const char *_cmd, const char *_username, |
| Definition *def) |
| { |
| init (DERIVED); |
| cmd = dbe_strdup (_cmd); |
| username = dbe_strdup (_username); |
| aux = dbe_strdup (_cmd); |
| definition = def; |
| flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED; |
| clock_unit = CUNIT_NULL; // should it be CUNIT_TIME or 0 or something? |
| |
| /* we're not going to process packets for derived metrics */ |
| packet_type = (ProfData_type) (-1); |
| value_styles = VAL_VALUE; |
| valtype = VT_DOUBLE; |
| precision = 1000; |
| } |
| |
| // Copy constructor |
| BaseMetric::BaseMetric (const BaseMetric& m) |
| { |
| id = m.id; |
| type = m.type; |
| aux = dbe_strdup (m.aux); |
| cmd = dbe_strdup (m.cmd); |
| username = dbe_strdup (m.username); |
| flavors = m.flavors; |
| value_styles = m.value_styles; |
| valtype = m.valtype; |
| precision = m.precision; |
| hw_ctr = m.hw_ctr; |
| packet_type = m.packet_type; |
| zeroThreshold = m.zeroThreshold; |
| clock_unit = m.clock_unit; |
| for (int ii = 0; ii < NSUBTYPES; ii++) |
| default_visbits[ii] = m.default_visbits[ii]; |
| if (m.cond_spec) |
| { |
| cond_spec = strdup (m.cond_spec); |
| cond = m.cond->copy (); |
| } |
| else |
| { |
| cond = NULL; |
| cond_spec = NULL; |
| } |
| if (m.val_spec) |
| { |
| val_spec = strdup (m.val_spec); |
| val = m.val->copy (); |
| } |
| else |
| { |
| val = NULL; |
| val_spec = NULL; |
| } |
| if (m.expr_spec) |
| { |
| expr_spec = strdup (m.expr_spec); |
| expr = m.expr->copy (); |
| } |
| else |
| { |
| expr = NULL; |
| expr_spec = NULL; |
| } |
| legend = dbe_strdup (m.legend); |
| definition = NULL; |
| if (m.definition) |
| definition = Definition::add_definition (m.definition->def); |
| dependent_bm = m.dependent_bm; |
| } |
| |
| BaseMetric::~BaseMetric () |
| { |
| free (aux); |
| free (cmd); |
| free (cond_spec); |
| free (val_spec); |
| free (expr_spec); |
| free (legend); |
| free (username); |
| delete cond; |
| delete val; |
| delete expr; |
| delete definition; |
| } |
| |
| bool |
| BaseMetric::is_internal () |
| { |
| return (get_value_styles () & VAL_INTERNAL) != 0; |
| } |
| |
| int |
| BaseMetric::get_default_visbits (SubType subtype) |
| { |
| int rc = VAL_NA; |
| switch (subtype) |
| { |
| case STATIC: |
| case EXCLUSIVE: |
| rc = default_visbits[0]; |
| break; |
| case INCLUSIVE: |
| rc = default_visbits[1]; |
| break; |
| default: |
| break; |
| } |
| return rc; |
| } |
| |
| void |
| BaseMetric::set_default_visbits (SubType subtype, int _visbits) |
| { |
| switch (subtype) |
| { |
| case STATIC: |
| case EXCLUSIVE: |
| default_visbits[0] = _visbits; |
| break; |
| case INCLUSIVE: |
| default_visbits[1] = _visbits; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| void |
| BaseMetric::set_cond_spec (char *_cond_spec) |
| { |
| if (cond_spec) |
| { |
| free (cond_spec); |
| delete cond; |
| cond_spec = NULL; |
| cond = NULL; |
| } |
| if (_cond_spec) |
| { |
| cond = dbeSession->ql_parse (_cond_spec); |
| if (cond == NULL) |
| { |
| fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _cond_spec); |
| abort (); |
| } |
| cond_spec = dbe_strdup (_cond_spec); |
| } |
| } |
| |
| void |
| BaseMetric::set_val_spec (char *_val_spec) |
| { |
| if (val_spec) |
| { |
| free (val_spec); |
| delete val; |
| val_spec = NULL; |
| val = NULL; |
| } |
| if (_val_spec) |
| { |
| val = dbeSession->ql_parse (_val_spec); |
| if (val == NULL) |
| { |
| fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _val_spec); |
| abort (); |
| } |
| val_spec = dbe_strdup (_val_spec); |
| } |
| } |
| |
| void |
| BaseMetric::set_expr_spec (char *_expr_spec) |
| { |
| id = last_id++; |
| if (expr_spec) |
| { |
| free (expr_spec); |
| delete expr; |
| expr_spec = NULL; |
| expr = NULL; |
| } |
| if (_expr_spec) |
| { |
| expr = dbeSession->ql_parse (_expr_spec); |
| if (expr == NULL) |
| { |
| fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _expr_spec); |
| return; |
| } |
| expr_spec = dbe_strdup (_expr_spec); |
| } |
| } |
| |
| void |
| BaseMetric::specify_mstate_metric (int st) |
| { |
| char buf[128]; |
| snprintf (buf, sizeof (buf), NTXT ("MSTATE==%d"), st); |
| specify_prof_metric (buf); |
| } |
| |
| void |
| BaseMetric::specify_ompstate_metric (int st) |
| { |
| char buf[128]; |
| snprintf (buf, sizeof (buf), NTXT ("OMPSTATE==%d"), st); |
| specify_prof_metric (buf); |
| } |
| |
| void |
| BaseMetric::specify_prof_metric (char *_cond_spec) |
| { |
| packet_type = DATA_CLOCK; |
| specify_metric (_cond_spec, NTXT ("NTICK_USEC")); // microseconds |
| } |
| |
| void |
| BaseMetric::specify_metric (char *_cond_spec, char *_val_spec) |
| { |
| set_cond_spec (_cond_spec); |
| set_val_spec (_val_spec); |
| } |
| |
| void |
| BaseMetric::specify () |
| { |
| enum |
| { |
| IDLE_STATE_BITS = |
| (1 << OMP_IDLE_STATE) | (1 << OMP_IBAR_STATE) | (1 << OMP_EBAR_STATE) | |
| (1 << OMP_LKWT_STATE) | (1 << OMP_CTWT_STATE) | (1 << OMP_ODWT_STATE) | |
| (1 << OMP_ATWT_STATE) | (1 << OMP_TSKWT_STATE), |
| LMS_USER_BITS = |
| (1 << OMP_NO_STATE) | (1 << OMP_WORK_STATE) | (1 << OMP_SERL_STATE) | |
| (1 << OMP_RDUC_STATE) |
| }; |
| |
| char buf[256]; |
| char buf2[256]; |
| packet_type = (ProfData_type) - 1; // illegal value |
| clock_unit = CUNIT_TIME; |
| switch (type) |
| { |
| case SIZES: |
| username = dbe_strdup (GTXT ("Size")); |
| clock_unit = CUNIT_BYTES; |
| cmd = dbe_strdup (NTXT ("size")); |
| break; |
| case ADDRESS: |
| username = dbe_strdup (GTXT ("PC Address")); |
| cmd = dbe_strdup (NTXT ("address")); |
| break; |
| case ONAME: |
| username = dbe_strdup (GTXT ("Name")); |
| cmd = dbe_strdup (NTXT ("name")); |
| break; |
| case CP_LMS_SYSTEM: |
| username = dbe_strdup (GTXT ("System CPU Time")); |
| specify_mstate_metric (LMS_SYSTEM); |
| cmd = dbe_strdup (NTXT ("system")); |
| break; |
| case CP_TOTAL_CPU: |
| username = dbe_strdup (GTXT ("Total CPU Time")); |
| snprintf (buf, sizeof (buf), |
| "(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)", |
| LMS_USER, LMS_SYSTEM, LMS_TRAP, LMS_LINUX_CPU); |
| specify_prof_metric (buf); |
| cmd = dbe_strdup (NTXT ("totalcpu")); |
| break; |
| case CP_TOTAL: |
| username = dbe_strdup (GTXT ("Total Thread Time")); |
| snprintf (buf, sizeof (buf), NTXT ("(MSTATE!=%d)&&(MSTATE!=%d)"), |
| LMS_KERNEL_CPU, LMS_LINUX_CPU); |
| specify_prof_metric (buf); |
| cmd = dbe_strdup (NTXT ("total")); |
| break; |
| case CP_KERNEL_CPU: |
| username = dbe_strdup (GTXT ("Kernel CPU Time")); |
| specify_mstate_metric (LMS_KERNEL_CPU); |
| cmd = dbe_strdup (NTXT ("kcpu")); |
| break; |
| case OMP_MASTER_THREAD: |
| username = dbe_strdup (GTXT ("Master Thread Time")); |
| specify_prof_metric (NTXT ("LWPID==1")); |
| cmd = dbe_strdup (NTXT ("masterthread")); |
| break; |
| case CP_LMS_USER: |
| username = dbe_strdup (GTXT ("User CPU Time")); |
| specify_mstate_metric (LMS_USER); |
| cmd = dbe_strdup (NTXT ("user")); |
| break; |
| case CP_LMS_WAIT_CPU: |
| username = dbe_strdup (GTXT ("Wait CPU Time")); |
| specify_mstate_metric (LMS_WAIT_CPU); |
| cmd = dbe_strdup (NTXT ("wait")); |
| break; |
| case CP_LMS_USER_LOCK: |
| username = dbe_strdup (GTXT ("User Lock Time")); |
| specify_mstate_metric (LMS_USER_LOCK); |
| cmd = dbe_strdup (NTXT ("lock")); |
| break; |
| case CP_LMS_TFAULT: |
| username = dbe_strdup (GTXT ("Text Page Fault Time")); |
| specify_mstate_metric (LMS_TFAULT); |
| cmd = dbe_strdup (NTXT ("textpfault")); |
| break; |
| case CP_LMS_DFAULT: |
| username = dbe_strdup (GTXT ("Data Page Fault Time")); |
| specify_mstate_metric (LMS_DFAULT); |
| cmd = dbe_strdup (NTXT ("datapfault")); |
| break; |
| case CP_LMS_TRAP: |
| username = dbe_strdup (GTXT ("Trap CPU Time")); |
| specify_mstate_metric (LMS_TRAP); |
| cmd = dbe_strdup (NTXT ("trap")); |
| break; |
| case CP_LMS_KFAULT: |
| username = dbe_strdup (GTXT ("Kernel Page Fault Time")); |
| specify_mstate_metric (LMS_KFAULT); |
| cmd = dbe_strdup (NTXT ("kernelpfault")); |
| break; |
| case CP_LMS_SLEEP: |
| username = dbe_strdup (GTXT ("Sleep Time")); |
| specify_mstate_metric (LMS_SLEEP); |
| cmd = dbe_strdup (NTXT ("sleep")); |
| break; |
| case CP_LMS_STOPPED: |
| username = dbe_strdup (GTXT ("Stopped Time")); |
| specify_mstate_metric (LMS_STOPPED); |
| cmd = dbe_strdup (NTXT ("stop")); |
| break; |
| case OMP_OVHD: |
| username = dbe_strdup (GTXT ("OpenMP Overhead Time")); |
| specify_ompstate_metric (OMP_OVHD_STATE); |
| cmd = dbe_strdup (NTXT ("ompovhd")); |
| break; |
| case OMP_WORK: |
| username = dbe_strdup (GTXT ("OpenMP Work Time")); |
| snprintf (buf, sizeof (buf), |
| NTXT ("(OMPSTATE>=0) && (MSTATE==%d) && ((1<<OMPSTATE) & %d)"), |
| LMS_USER, LMS_USER_BITS); |
| specify_prof_metric (buf); |
| cmd = dbe_strdup (NTXT ("ompwork")); |
| break; |
| case OMP_WAIT: |
| username = dbe_strdup (GTXT ("OpenMP Wait Time")); |
| snprintf (buf, sizeof (buf), |
| "OMPSTATE>=0 && ((1<<OMPSTATE) & ((MSTATE!=%d) ? %d : %d))", |
| LMS_USER, (LMS_USER_BITS | IDLE_STATE_BITS), IDLE_STATE_BITS); |
| specify_prof_metric (buf); |
| cmd = dbe_strdup (NTXT ("ompwait")); |
| break; |
| case OMP_IBAR: |
| username = dbe_strdup (GTXT ("OpenMP Implicit Barrier Time")); |
| specify_ompstate_metric (OMP_IBAR_STATE); |
| cmd = dbe_strdup (NTXT ("ompibar")); |
| break; |
| case OMP_EBAR: |
| username = dbe_strdup (GTXT ("OpenMP Explicit Barrier Time")); |
| specify_ompstate_metric (OMP_EBAR_STATE); |
| cmd = dbe_strdup (NTXT ("ompebar")); |
| break; |
| case OMP_SERL: |
| username = dbe_strdup (GTXT ("OpenMP Serial Time")); |
| specify_ompstate_metric (OMP_SERL_STATE); |
| cmd = dbe_strdup (NTXT ("ompserl")); |
| break; |
| case OMP_RDUC: |
| username = dbe_strdup (GTXT ("OpenMP Reduction Time")); |
| specify_ompstate_metric (OMP_RDUC_STATE); |
| cmd = dbe_strdup (NTXT ("omprduc")); |
| break; |
| case OMP_LKWT: |
| username = dbe_strdup (GTXT ("OpenMP Lock Wait Time")); |
| specify_ompstate_metric (OMP_LKWT_STATE); |
| cmd = dbe_strdup (NTXT ("omplkwt")); |
| break; |
| case OMP_CTWT: |
| username = dbe_strdup (GTXT ("OpenMP Critical Section Wait Time")); |
| specify_ompstate_metric (OMP_CTWT_STATE); |
| cmd = dbe_strdup (NTXT ("ompctwt")); |
| break; |
| case OMP_ODWT: |
| username = dbe_strdup (GTXT ("OpenMP Ordered Section Wait Time")); |
| specify_ompstate_metric (OMP_ODWT_STATE); |
| cmd = dbe_strdup (NTXT ("ompodwt")); |
| break; |
| case SYNC_WAIT_TIME: |
| packet_type = DATA_SYNCH; |
| username = dbe_strdup (GTXT ("Sync Wait Time")); |
| snprintf (buf, sizeof (buf), NTXT ("(EVT_TIME)/%lld"), |
| (long long) (NANOSEC / METRIC_HR_PRECISION)); |
| specify_metric (NULL, buf); |
| cmd = dbe_strdup (NTXT ("sync")); |
| break; |
| case SYNC_WAIT_COUNT: |
| packet_type = DATA_SYNCH; |
| username = dbe_strdup (GTXT ("Sync Wait Count")); |
| specify_metric (NULL, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("syncn")); |
| break; |
| case HEAP_ALLOC_CNT: |
| packet_type = DATA_HEAP; |
| username = dbe_strdup (GTXT ("Allocations")); |
| snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"), |
| FREE_TRACE, MUNMAP_TRACE); |
| specify_metric (buf, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("heapalloccnt")); |
| break; |
| case HEAP_ALLOC_BYTES: |
| packet_type = DATA_HEAP; |
| username = dbe_strdup (GTXT ("Bytes Allocated")); |
| snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"), |
| FREE_TRACE, MUNMAP_TRACE); |
| specify_metric (buf, NTXT ("HSIZE")); |
| cmd = dbe_strdup (NTXT ("heapallocbytes")); |
| break; |
| case HEAP_LEAK_CNT: |
| packet_type = DATA_HEAP; |
| username = dbe_strdup (GTXT ("Leaks")); |
| snprintf (buf, sizeof (buf), "(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR&&HLEAKED", |
| FREE_TRACE, MUNMAP_TRACE); |
| specify_metric (buf, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("heapleakcnt")); |
| break; |
| case HEAP_LEAK_BYTES: |
| packet_type = DATA_HEAP; |
| username = dbe_strdup (GTXT ("Bytes Leaked")); |
| snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"), |
| FREE_TRACE, MUNMAP_TRACE); |
| specify_metric (buf, NTXT ("HLEAKED")); |
| cmd = dbe_strdup (NTXT ("heapleakbytes")); |
| break; |
| |
| case IO_READ_CNT: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Read Count")); |
| snprintf (buf, sizeof (buf), "(IOTYPE==%d)", READ_TRACE); |
| specify_metric (buf, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("ioreadcnt")); |
| break; |
| case IO_WRITE_CNT: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Write Count")); |
| snprintf (buf, sizeof (buf), "(IOTYPE==%d)", WRITE_TRACE); |
| specify_metric (buf, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("iowritecnt")); |
| break; |
| case IO_OTHER_CNT: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Other I/O Count")); |
| snprintf (buf, sizeof (buf), "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)", |
| OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE); |
| specify_metric (buf, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("ioothercnt")); |
| break; |
| case IO_ERROR_CNT: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("I/O Error Count")); |
| snprintf (buf, sizeof (buf), |
| "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)", |
| READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR, |
| CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR); |
| specify_metric (buf, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("ioerrorcnt")); |
| break; |
| case IO_READ_BYTES: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Read Bytes")); |
| snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&IONBYTE"), |
| READ_TRACE); |
| specify_metric (buf, NTXT ("IONBYTE")); |
| cmd = dbe_strdup (NTXT ("ioreadbytes")); |
| break; |
| case IO_WRITE_BYTES: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Write Bytes")); |
| snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&IONBYTE", WRITE_TRACE); |
| specify_metric (buf, NTXT ("IONBYTE")); |
| cmd = dbe_strdup (NTXT ("iowritebytes")); |
| break; |
| case IO_READ_TIME: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Read Time")); |
| snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&EVT_TIME", READ_TRACE); |
| snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), |
| (long long) (NANOSEC / METRIC_HR_PRECISION)); |
| specify_metric (buf, buf2); |
| cmd = dbe_strdup (NTXT ("ioreadtime")); |
| break; |
| case IO_WRITE_TIME: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Write Time")); |
| snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&EVT_TIME"), |
| WRITE_TRACE); |
| snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), |
| (long long) (NANOSEC / METRIC_HR_PRECISION)); |
| specify_metric (buf, buf2); |
| cmd = dbe_strdup (NTXT ("iowritetime")); |
| break; |
| case IO_OTHER_TIME: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("Other I/O Time")); |
| snprintf (buf, sizeof (buf), |
| "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME", |
| OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE); |
| snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), |
| (long long) (NANOSEC / METRIC_HR_PRECISION)); |
| specify_metric (buf, buf2); |
| cmd = dbe_strdup (NTXT ("ioothertime")); |
| break; |
| case IO_ERROR_TIME: |
| packet_type = DATA_IOTRACE; |
| username = dbe_strdup (GTXT ("I/O Error Time")); |
| snprintf (buf, sizeof (buf), |
| "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME", |
| READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR, |
| CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR); |
| snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"), |
| (long long) (NANOSEC / METRIC_HR_PRECISION)); |
| specify_metric (buf, buf2); |
| cmd = dbe_strdup (NTXT ("ioerrortime")); |
| break; |
| case RACCESS: |
| packet_type = DATA_RACE; |
| username = dbe_strdup (GTXT ("Race Accesses")); |
| specify_metric (NULL, NTXT ("RCNT")); |
| cmd = dbe_strdup (NTXT ("raccess")); |
| break; |
| case DEADLOCKS: |
| packet_type = DATA_DLCK; |
| username = dbe_strdup (GTXT ("Deadlocks")); |
| specify_metric (NULL, NTXT ("1")); |
| cmd = dbe_strdup (NTXT ("deadlocks")); |
| break; |
| case HWCNTR: |
| packet_type = DATA_HWC; |
| // username, cmd, and aux set by hwc constructor |
| if (valtype == VT_DOUBLE) |
| { |
| if (hw_ctr->timecvt > 0) // CPU cycles |
| specify_metric (NULL, NTXT ("((HWCINT*1000000)/FREQ_MHZ)")); |
| else if (hw_ctr->timecvt < 0) |
| { // reference clock (frequency is -timecvt MHz) |
| snprintf (buf, sizeof (buf), NTXT ("((HWCINT*1000000)/%d)"), -hw_ctr->timecvt); |
| specify_metric (NULL, buf); |
| } |
| else // shouldn't happen |
| specify_metric (NULL, NTXT ("0")); |
| // resulting unit: seconds * 1e12 |
| precision = 1000000LL * 1000000LL; // Seconds * 1e12 |
| } |
| else |
| { |
| specify_metric (NULL, NTXT ("HWCINT")); |
| precision = 1; |
| } |
| break; |
| case OMP_MSTR: |
| case OMP_SNGL: |
| case OMP_ORDD: |
| case OMP_NONE: |
| default: |
| username = dbe_strdup (GTXT ("****")); |
| fprintf (stderr, "BaseMetric::init Undefined basemetric %s\n", |
| get_basetype_name ()); |
| } |
| } |
| |
| #define CASE_S(x) case x: s = (char *) #x; break |
| char * |
| BaseMetric::get_basetype_name () |
| { |
| static char buf[128]; |
| char *s; |
| switch (type) |
| { |
| CASE_S (CP_LMS_SYSTEM); |
| CASE_S (CP_TOTAL_CPU); |
| CASE_S (CP_TOTAL); |
| CASE_S (OMP_MASTER_THREAD); |
| CASE_S (CP_LMS_USER); |
| CASE_S (CP_LMS_WAIT_CPU); |
| CASE_S (CP_LMS_USER_LOCK); |
| CASE_S (CP_LMS_TFAULT); |
| CASE_S (CP_LMS_DFAULT); |
| CASE_S (CP_LMS_TRAP); |
| CASE_S (CP_LMS_KFAULT); |
| CASE_S (CP_LMS_SLEEP); |
| CASE_S (CP_LMS_STOPPED); |
| CASE_S (OMP_NONE); |
| CASE_S (OMP_OVHD); |
| CASE_S (OMP_WORK); |
| CASE_S (OMP_IBAR); |
| CASE_S (OMP_EBAR); |
| CASE_S (OMP_WAIT); |
| CASE_S (OMP_SERL); |
| CASE_S (OMP_RDUC); |
| CASE_S (OMP_LKWT); |
| CASE_S (OMP_CTWT); |
| CASE_S (OMP_ODWT); |
| CASE_S (OMP_MSTR); |
| CASE_S (OMP_SNGL); |
| CASE_S (OMP_ORDD); |
| CASE_S (CP_KERNEL_CPU); |
| CASE_S (SYNC_WAIT_TIME); |
| CASE_S (IO_READ_TIME); |
| CASE_S (IO_WRITE_TIME); |
| CASE_S (IO_OTHER_TIME); |
| CASE_S (IO_ERROR_TIME); |
| CASE_S (HWCNTR); |
| CASE_S (SYNC_WAIT_COUNT); |
| CASE_S (HEAP_ALLOC_CNT); |
| CASE_S (HEAP_LEAK_CNT); |
| CASE_S (IO_READ_CNT); |
| CASE_S (IO_WRITE_CNT); |
| CASE_S (IO_OTHER_CNT); |
| CASE_S (IO_ERROR_CNT); |
| CASE_S (RACCESS); |
| CASE_S (DEADLOCKS); |
| CASE_S (HEAP_ALLOC_BYTES); |
| CASE_S (HEAP_LEAK_BYTES); |
| CASE_S (IO_READ_BYTES); |
| CASE_S (IO_WRITE_BYTES); |
| CASE_S (SIZES); |
| CASE_S (ADDRESS); |
| CASE_S (ONAME); |
| CASE_S (DERIVED); |
| default: |
| s = NTXT ("???"); |
| break; |
| } |
| snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type); |
| buf[sizeof (buf) - 1] = 0; |
| return buf; |
| } |
| |
| char * |
| BaseMetric::dump () |
| { |
| int len = 4; |
| char *msg = dbe_sprintf (NTXT ("id=%d %s aux='%s' cmd='%s' user_name='%s' expr_spec='%s'\n" |
| "%*c cond_spec='%s' val_spec='%s'"), |
| id, get_basetype_name (), STR (aux), STR (cmd), |
| STR (username), STR (expr_spec), |
| len, ' ', STR (cond_spec), STR (val_spec)); |
| return msg; |
| } |
| |
| Histable * |
| BaseMetric::get_comparable_obj (Histable *obj) |
| { |
| if (obj == NULL || expr == NULL) |
| return obj; |
| if (strncmp (expr_spec, NTXT ("EXPGRID=="), 9) == 0) |
| { |
| int n = atoi (expr_spec + 9); |
| Vector<Histable *> *cmpObjs = obj->get_comparable_objs (); |
| if (cmpObjs && cmpObjs->size () >= n) |
| return cmpObjs->get (n - 1); |
| return NULL; |
| } |
| return obj; |
| } |
| |
| Definition::Definition (opType _op) |
| { |
| op = _op; |
| bm = NULL; |
| arg1 = NULL; |
| arg2 = NULL; |
| def = NULL; |
| dependencies = NULL; |
| map = NULL; |
| index = 0; |
| } |
| |
| Definition::~Definition () |
| { |
| delete arg1; |
| delete arg2; |
| delete dependencies; |
| delete[] map; |
| } |
| |
| Vector<BaseMetric *> * |
| Definition::get_dependencies () |
| { |
| if (dependencies == NULL) |
| { |
| if (arg1 && arg1->bm && arg2 && arg2->bm) |
| { |
| dependencies = new Vector<BaseMetric *>(2); |
| arg1->index = dependencies->size (); |
| dependencies->append (arg1->bm); |
| arg2->index = dependencies->size (); |
| dependencies->append (arg2->bm); |
| map = new long[2]; |
| } |
| } |
| return dependencies; |
| } |
| |
| long * |
| Definition::get_map () |
| { |
| get_dependencies (); |
| return map; |
| } |
| |
| Definition * |
| Definition::add_definition (char *_def) |
| { |
| // parse the definition |
| char *op_ptr = strchr (_def, '/'); |
| if (op_ptr == NULL) |
| { |
| // it's a primitive metric |
| BaseMetric *bm = dbeSession->find_base_reg_metric (_def); |
| if (bm) |
| { |
| Definition *p = new Definition (opPrimitive); |
| p->bm = bm; |
| return p; |
| } |
| return NULL; // BaseMetric is not yet specified |
| } |
| Definition *p2 = add_definition (op_ptr + 1); |
| if (p2 == NULL) |
| return NULL; |
| _def = dbe_strdup (_def); |
| op_ptr = strchr (_def, '/'); |
| *op_ptr = 0; |
| Definition *p1 = add_definition (_def); |
| if (p1) |
| { |
| *op_ptr = '/'; |
| Definition *p = new Definition (opDivide); |
| p->arg1 = p1; |
| p->arg2 = p2; |
| p->def = _def; |
| return p; |
| } |
| free (_def); |
| delete p1; |
| delete p2; |
| return NULL; |
| } |
| |
| double |
| Definition::eval (long *indexes, TValue *values) |
| { |
| switch (op) |
| { |
| case opPrimitive: |
| return values[indexes[index]].to_double (); |
| case opDivide: |
| { |
| double x2 = arg2->eval (indexes, values); |
| if (x2 == 0) |
| return 0.; |
| double x1 = arg1->eval (indexes, values); |
| return x1 / x2; |
| } |
| default: |
| fprintf (stderr, GTXT ("unknown expression\n")); |
| return 0.; |
| } |
| } |