mirror of
https://github.com/autc04/Retro68.git
synced 2024-06-15 07:29:41 +00:00
330 lines
8.5 KiB
C++
330 lines
8.5 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 <stdio.h>
|
|
#include <strings.h>
|
|
#include <limits.h>
|
|
#include <sys/param.h>
|
|
|
|
#include "hwcentry.h"
|
|
#include "DbeSession.h"
|
|
#include "Experiment.h"
|
|
#include "Expression.h"
|
|
#include "Metric.h"
|
|
#include "Table.h"
|
|
#include "i18n.h"
|
|
#include "debug.h"
|
|
|
|
BaseMetricTreeNode::BaseMetricTreeNode ()
|
|
{
|
|
init_vars ();
|
|
build_basic_tree ();
|
|
}
|
|
|
|
BaseMetricTreeNode::BaseMetricTreeNode (BaseMetric *item)
|
|
{
|
|
init_vars ();
|
|
bm = item;
|
|
name = dbe_strdup (bm->get_cmd ());
|
|
uname = dbe_strdup (bm->get_username ());
|
|
unit = NULL; //YXXX populate from base_metric (requires updating base_metric)
|
|
unit_uname = NULL;
|
|
}
|
|
|
|
BaseMetricTreeNode::BaseMetricTreeNode (const char *_name, const char *_uname,
|
|
const char *_unit, const char *_unit_uname)
|
|
{
|
|
init_vars ();
|
|
name = dbe_strdup (_name);
|
|
uname = dbe_strdup (_uname);
|
|
unit = dbe_strdup (_unit);
|
|
unit_uname = dbe_strdup (_unit_uname);
|
|
}
|
|
|
|
void
|
|
BaseMetricTreeNode::init_vars ()
|
|
{
|
|
name = NULL;
|
|
uname = NULL;
|
|
unit = NULL;
|
|
unit_uname = NULL;
|
|
root = this;
|
|
parent = NULL;
|
|
children = new Vector<BaseMetricTreeNode*>;
|
|
isCompositeMetric = false;
|
|
bm = NULL;
|
|
registered = false;
|
|
num_registered_descendents = 0;
|
|
}
|
|
|
|
BaseMetricTreeNode::~BaseMetricTreeNode ()
|
|
{
|
|
children->destroy ();
|
|
delete children;
|
|
free (name);
|
|
free (uname);
|
|
free (unit);
|
|
free (unit_uname);
|
|
}
|
|
|
|
BaseMetricTreeNode *
|
|
BaseMetricTreeNode::register_metric (BaseMetric *item)
|
|
{
|
|
BaseMetricTreeNode *found = root->find (item->get_cmd ());
|
|
if (!found)
|
|
{
|
|
switch (item->get_type ())
|
|
{
|
|
case BaseMetric::CP_TOTAL:
|
|
found = root->find (L_CP_TOTAL);
|
|
break;
|
|
case BaseMetric::CP_TOTAL_CPU:
|
|
found = root->find (L_CP_TOTAL_CPU);
|
|
break;
|
|
}
|
|
if (found && found->bm == NULL)
|
|
found->bm = item;
|
|
}
|
|
if (!found)
|
|
{
|
|
switch (item->get_type ())
|
|
{
|
|
case BaseMetric::HEAP_ALLOC_BYTES:
|
|
case BaseMetric::HEAP_ALLOC_CNT:
|
|
case BaseMetric::HEAP_LEAK_BYTES:
|
|
case BaseMetric::HEAP_LEAK_CNT:
|
|
found = root->find (get_prof_data_type_name (DATA_HEAP));
|
|
break;
|
|
case BaseMetric::CP_KERNEL_CPU:
|
|
case BaseMetric::CP_TOTAL:
|
|
found = root->find (get_prof_data_type_name (DATA_CLOCK));
|
|
break;
|
|
case BaseMetric::CP_LMS_DFAULT:
|
|
case BaseMetric::CP_LMS_TFAULT:
|
|
case BaseMetric::CP_LMS_KFAULT:
|
|
case BaseMetric::CP_LMS_STOPPED:
|
|
case BaseMetric::CP_LMS_WAIT_CPU:
|
|
case BaseMetric::CP_LMS_SLEEP:
|
|
case BaseMetric::CP_LMS_USER_LOCK:
|
|
case BaseMetric::CP_TOTAL_CPU:
|
|
found = root->find (L_CP_TOTAL);
|
|
break;
|
|
case BaseMetric::CP_LMS_USER:
|
|
case BaseMetric::CP_LMS_SYSTEM:
|
|
case BaseMetric::CP_LMS_TRAP:
|
|
found = root->find (L_CP_TOTAL_CPU);
|
|
break;
|
|
case BaseMetric::HWCNTR:
|
|
found = root->find ((item->get_flavors () & BaseMetric::DATASPACE) != 0 ?
|
|
L2_HWC_DSPACE : L2_HWC_GENERAL);
|
|
break;
|
|
case BaseMetric::SYNC_WAIT_TIME:
|
|
case BaseMetric::SYNC_WAIT_COUNT:
|
|
found = root->find (get_prof_data_type_name (DATA_SYNCH));
|
|
break;
|
|
case BaseMetric::OMP_WORK:
|
|
case BaseMetric::OMP_WAIT:
|
|
case BaseMetric::OMP_OVHD:
|
|
found = root->find (get_prof_data_type_name (DATA_OMP));
|
|
break;
|
|
case BaseMetric::IO_READ_TIME:
|
|
case BaseMetric::IO_READ_BYTES:
|
|
case BaseMetric::IO_READ_CNT:
|
|
case BaseMetric::IO_WRITE_TIME:
|
|
case BaseMetric::IO_WRITE_BYTES:
|
|
case BaseMetric::IO_WRITE_CNT:
|
|
case BaseMetric::IO_OTHER_TIME:
|
|
case BaseMetric::IO_OTHER_CNT:
|
|
case BaseMetric::IO_ERROR_TIME:
|
|
case BaseMetric::IO_ERROR_CNT:
|
|
found = root->find (get_prof_data_type_name (DATA_IOTRACE));
|
|
break;
|
|
case BaseMetric::ONAME:
|
|
case BaseMetric::SIZES:
|
|
case BaseMetric::ADDRESS:
|
|
found = root->find (L1_STATIC);
|
|
break;
|
|
default:
|
|
found = root->find (L1_OTHER);
|
|
break;
|
|
}
|
|
assert (found != NULL);
|
|
switch (item->get_type ())
|
|
{
|
|
case BaseMetric::CP_TOTAL:
|
|
case BaseMetric::CP_TOTAL_CPU:
|
|
found->isCompositeMetric = true;
|
|
break;
|
|
}
|
|
found = found->add_child (item);
|
|
}
|
|
register_node (found);
|
|
return found;
|
|
}
|
|
|
|
void
|
|
BaseMetricTreeNode::register_node (BaseMetricTreeNode *node)
|
|
{
|
|
if (!node->registered)
|
|
{
|
|
node->registered = true;
|
|
BaseMetricTreeNode *tmp = node->parent;
|
|
while (tmp)
|
|
{
|
|
tmp->num_registered_descendents++;
|
|
tmp = tmp->parent;
|
|
}
|
|
}
|
|
}
|
|
|
|
BaseMetricTreeNode *
|
|
BaseMetricTreeNode::find (const char *_name)
|
|
{
|
|
BaseMetricTreeNode *found = NULL;
|
|
if (dbe_strcmp (get_name (), _name) == 0)
|
|
return this;
|
|
if (bm && dbe_strcmp (bm->get_cmd (), _name) == 0)
|
|
return this;
|
|
BaseMetricTreeNode *child;
|
|
int index;
|
|
|
|
Vec_loop (BaseMetricTreeNode*, children, index, child)
|
|
{
|
|
found = child->find (_name);
|
|
if (found)
|
|
return found;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
int_get_registered_descendents (BaseMetricTreeNode* curr,
|
|
Vector<BaseMetricTreeNode*> *dest, bool nearest_only)
|
|
{
|
|
if (!curr)
|
|
return;
|
|
if (curr->is_registered ())
|
|
{
|
|
dest->append (curr);
|
|
if (nearest_only)
|
|
return; // soon as we hit a live node, stop following branch
|
|
}
|
|
int index;
|
|
BaseMetricTreeNode *child;
|
|
|
|
Vec_loop (BaseMetricTreeNode*, curr->get_children (), index, child)
|
|
{
|
|
int_get_registered_descendents (child, dest, nearest_only);
|
|
}
|
|
}
|
|
|
|
void
|
|
BaseMetricTreeNode::get_nearest_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
|
|
{
|
|
if (!dest || dest->size () != 0)
|
|
abort ();
|
|
bool nearest_only = true;
|
|
int_get_registered_descendents (this, dest, nearest_only);
|
|
}
|
|
|
|
void
|
|
BaseMetricTreeNode::get_all_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
|
|
{
|
|
if (!dest || dest->size () != 0)
|
|
abort ();
|
|
bool nearest_only = false;
|
|
int_get_registered_descendents (this, dest, nearest_only);
|
|
}
|
|
|
|
char *
|
|
BaseMetricTreeNode::get_description ()
|
|
{
|
|
if (bm)
|
|
{
|
|
Hwcentry* hw_ctr = bm->get_hw_ctr ();
|
|
if (hw_ctr)
|
|
return hw_ctr->short_desc;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
BaseMetricTreeNode::build_basic_tree ()
|
|
{
|
|
#define TREE_INSERT_DATA_TYPE(t) add_child(get_prof_data_type_name (t), get_prof_data_type_uname (t))
|
|
BaseMetricTreeNode *level1, *level2;
|
|
// register L1_DURATION here because it has a value but is not a true metric
|
|
register_node (add_child (L1_DURATION, L1_DURATION_UNAME, UNIT_SECONDS,
|
|
UNIT_SECONDS_UNAME));
|
|
register_node (add_child (L1_GCDURATION, L1_GCDURATION_UNAME, UNIT_SECONDS,
|
|
UNIT_SECONDS_UNAME));
|
|
TREE_INSERT_DATA_TYPE (DATA_HEAP);
|
|
level1 = TREE_INSERT_DATA_TYPE (DATA_CLOCK);
|
|
level1 = level1->add_child (L_CP_TOTAL, GTXT ("XXX Total Thread Time"));
|
|
level1->isCompositeMetric = true;
|
|
level2 = level1->add_child (L_CP_TOTAL_CPU, GTXT ("XXX Total CPU Time"));
|
|
level2->isCompositeMetric = true;
|
|
|
|
add_child (L1_OTHER, L1_OTHER_UNAME);
|
|
level1 = TREE_INSERT_DATA_TYPE (DATA_HWC);
|
|
level1->add_child (L2_HWC_DSPACE, L2_HWC_DSPACE_UNAME);
|
|
level1->add_child (L2_HWC_GENERAL, L2_HWC_GENERAL_UNAME);
|
|
TREE_INSERT_DATA_TYPE (DATA_SYNCH);
|
|
TREE_INSERT_DATA_TYPE (DATA_OMP);
|
|
TREE_INSERT_DATA_TYPE (DATA_IOTRACE);
|
|
add_child (L1_STATIC, L1_STATIC_UNAME);
|
|
}
|
|
|
|
BaseMetricTreeNode *
|
|
BaseMetricTreeNode::add_child (BaseMetric *item)
|
|
{
|
|
return add_child (new BaseMetricTreeNode (item));
|
|
}
|
|
|
|
BaseMetricTreeNode *
|
|
BaseMetricTreeNode::add_child (const char * _name, const char *_uname,
|
|
const char * _unit, const char * _unit_uname)
|
|
{
|
|
return add_child (new BaseMetricTreeNode (_name, _uname, _unit, _unit_uname));
|
|
}
|
|
|
|
BaseMetricTreeNode *
|
|
BaseMetricTreeNode::add_child (BaseMetricTreeNode *new_node)
|
|
{
|
|
new_node->parent = this;
|
|
new_node->root = root;
|
|
children->append (new_node);
|
|
return new_node;
|
|
}
|
|
|
|
char *
|
|
BaseMetricTreeNode::dump ()
|
|
{
|
|
int len = 4;
|
|
char *s = bm ? bm->dump () : dbe_strdup ("<no base metric>");
|
|
char *msg = dbe_sprintf ("%s\n%*c %*c unit='%s' unit_uname='%s' uname='%s' name='%s'\n",
|
|
STR (s), len, ' ', len, ' ',
|
|
STR (get_unit_uname ()), STR (get_unit ()),
|
|
STR (get_user_name ()), STR (get_name ()));
|
|
free (s);
|
|
return msg;
|
|
}
|