Retro68/binutils/gprofng/src/BaseMetric.cc
Wolfgang Thaller f485e125c4 binutils 2.39
2022-10-27 20:45:45 +02:00

976 lines
26 KiB
C++

/* Copyright (C) 2021 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.;
}
}