1*f22f0ef4Schristos /* Copyright (C) 2021 Free Software Foundation, Inc.
2*f22f0ef4Schristos    Contributed by Oracle.
3*f22f0ef4Schristos 
4*f22f0ef4Schristos    This file is part of GNU Binutils.
5*f22f0ef4Schristos 
6*f22f0ef4Schristos    This program is free software; you can redistribute it and/or modify
7*f22f0ef4Schristos    it under the terms of the GNU General Public License as published by
8*f22f0ef4Schristos    the Free Software Foundation; either version 3, or (at your option)
9*f22f0ef4Schristos    any later version.
10*f22f0ef4Schristos 
11*f22f0ef4Schristos    This program is distributed in the hope that it will be useful,
12*f22f0ef4Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*f22f0ef4Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*f22f0ef4Schristos    GNU General Public License for more details.
15*f22f0ef4Schristos 
16*f22f0ef4Schristos    You should have received a copy of the GNU General Public License
17*f22f0ef4Schristos    along with this program; if not, write to the Free Software
18*f22f0ef4Schristos    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19*f22f0ef4Schristos    MA 02110-1301, USA.  */
20*f22f0ef4Schristos 
21*f22f0ef4Schristos #include "config.h"
22*f22f0ef4Schristos #include <stdio.h>
23*f22f0ef4Schristos #include <strings.h>
24*f22f0ef4Schristos #include <limits.h>
25*f22f0ef4Schristos #include <sys/param.h>
26*f22f0ef4Schristos 
27*f22f0ef4Schristos #include "hwcentry.h"
28*f22f0ef4Schristos #include "DbeSession.h"
29*f22f0ef4Schristos #include "Experiment.h"
30*f22f0ef4Schristos #include "Expression.h"
31*f22f0ef4Schristos #include "Metric.h"
32*f22f0ef4Schristos #include "Table.h"
33*f22f0ef4Schristos #include "i18n.h"
34*f22f0ef4Schristos #include "debug.h"
35*f22f0ef4Schristos 
BaseMetricTreeNode()36*f22f0ef4Schristos BaseMetricTreeNode::BaseMetricTreeNode ()
37*f22f0ef4Schristos {
38*f22f0ef4Schristos   init_vars ();
39*f22f0ef4Schristos   build_basic_tree ();
40*f22f0ef4Schristos }
41*f22f0ef4Schristos 
BaseMetricTreeNode(BaseMetric * item)42*f22f0ef4Schristos BaseMetricTreeNode::BaseMetricTreeNode (BaseMetric *item)
43*f22f0ef4Schristos {
44*f22f0ef4Schristos   init_vars ();
45*f22f0ef4Schristos   bm = item;
46*f22f0ef4Schristos   name = dbe_strdup (bm->get_cmd ());
47*f22f0ef4Schristos   uname = dbe_strdup (bm->get_username ());
48*f22f0ef4Schristos   unit = NULL; //YXXX populate from base_metric (requires updating base_metric)
49*f22f0ef4Schristos   unit_uname = NULL;
50*f22f0ef4Schristos }
51*f22f0ef4Schristos 
BaseMetricTreeNode(const char * _name,const char * _uname,const char * _unit,const char * _unit_uname)52*f22f0ef4Schristos BaseMetricTreeNode::BaseMetricTreeNode (const char *_name, const char *_uname,
53*f22f0ef4Schristos 				    const char *_unit, const char *_unit_uname)
54*f22f0ef4Schristos {
55*f22f0ef4Schristos   init_vars ();
56*f22f0ef4Schristos   name = dbe_strdup (_name);
57*f22f0ef4Schristos   uname = dbe_strdup (_uname);
58*f22f0ef4Schristos   unit = dbe_strdup (_unit);
59*f22f0ef4Schristos   unit_uname = dbe_strdup (_unit_uname);
60*f22f0ef4Schristos }
61*f22f0ef4Schristos 
62*f22f0ef4Schristos void
init_vars()63*f22f0ef4Schristos BaseMetricTreeNode::init_vars ()
64*f22f0ef4Schristos {
65*f22f0ef4Schristos   name = NULL;
66*f22f0ef4Schristos   uname = NULL;
67*f22f0ef4Schristos   unit = NULL;
68*f22f0ef4Schristos   unit_uname = NULL;
69*f22f0ef4Schristos   root = this;
70*f22f0ef4Schristos   parent = NULL;
71*f22f0ef4Schristos   children = new Vector<BaseMetricTreeNode*>;
72*f22f0ef4Schristos   isCompositeMetric = false;
73*f22f0ef4Schristos   bm = NULL;
74*f22f0ef4Schristos   registered = false;
75*f22f0ef4Schristos   num_registered_descendents = 0;
76*f22f0ef4Schristos }
77*f22f0ef4Schristos 
~BaseMetricTreeNode()78*f22f0ef4Schristos BaseMetricTreeNode::~BaseMetricTreeNode ()
79*f22f0ef4Schristos {
80*f22f0ef4Schristos   children->destroy ();
81*f22f0ef4Schristos   delete children;
82*f22f0ef4Schristos   free (name);
83*f22f0ef4Schristos   free (uname);
84*f22f0ef4Schristos   free (unit);
85*f22f0ef4Schristos   free (unit_uname);
86*f22f0ef4Schristos }
87*f22f0ef4Schristos 
88*f22f0ef4Schristos BaseMetricTreeNode *
register_metric(BaseMetric * item)89*f22f0ef4Schristos BaseMetricTreeNode::register_metric (BaseMetric *item)
90*f22f0ef4Schristos {
91*f22f0ef4Schristos   BaseMetricTreeNode *found = root->find (item->get_cmd ());
92*f22f0ef4Schristos   if (!found)
93*f22f0ef4Schristos     {
94*f22f0ef4Schristos       switch (item->get_type ())
95*f22f0ef4Schristos 	{
96*f22f0ef4Schristos 	case BaseMetric::CP_TOTAL:
97*f22f0ef4Schristos 	  found = root->find (L_CP_TOTAL);
98*f22f0ef4Schristos 	  break;
99*f22f0ef4Schristos 	case BaseMetric::CP_TOTAL_CPU:
100*f22f0ef4Schristos 	  found = root->find (L_CP_TOTAL_CPU);
101*f22f0ef4Schristos 	  break;
102*f22f0ef4Schristos 	}
103*f22f0ef4Schristos       if (found && found->bm == NULL)
104*f22f0ef4Schristos 	found->bm = item;
105*f22f0ef4Schristos     }
106*f22f0ef4Schristos   if (!found)
107*f22f0ef4Schristos     {
108*f22f0ef4Schristos       switch (item->get_type ())
109*f22f0ef4Schristos 	{
110*f22f0ef4Schristos 	case BaseMetric::HEAP_ALLOC_BYTES:
111*f22f0ef4Schristos 	case BaseMetric::HEAP_ALLOC_CNT:
112*f22f0ef4Schristos 	case BaseMetric::HEAP_LEAK_BYTES:
113*f22f0ef4Schristos 	case BaseMetric::HEAP_LEAK_CNT:
114*f22f0ef4Schristos 	  found = root->find (get_prof_data_type_name (DATA_HEAP));
115*f22f0ef4Schristos 	  break;
116*f22f0ef4Schristos 	case BaseMetric::CP_KERNEL_CPU:
117*f22f0ef4Schristos 	case BaseMetric::CP_TOTAL:
118*f22f0ef4Schristos 	  found = root->find (get_prof_data_type_name (DATA_CLOCK));
119*f22f0ef4Schristos 	  break;
120*f22f0ef4Schristos 	case BaseMetric::CP_LMS_DFAULT:
121*f22f0ef4Schristos 	case BaseMetric::CP_LMS_TFAULT:
122*f22f0ef4Schristos 	case BaseMetric::CP_LMS_KFAULT:
123*f22f0ef4Schristos 	case BaseMetric::CP_LMS_STOPPED:
124*f22f0ef4Schristos 	case BaseMetric::CP_LMS_WAIT_CPU:
125*f22f0ef4Schristos 	case BaseMetric::CP_LMS_SLEEP:
126*f22f0ef4Schristos 	case BaseMetric::CP_LMS_USER_LOCK:
127*f22f0ef4Schristos 	case BaseMetric::CP_TOTAL_CPU:
128*f22f0ef4Schristos 	  found = root->find (L_CP_TOTAL);
129*f22f0ef4Schristos 	  break;
130*f22f0ef4Schristos 	case BaseMetric::CP_LMS_USER:
131*f22f0ef4Schristos 	case BaseMetric::CP_LMS_SYSTEM:
132*f22f0ef4Schristos 	case BaseMetric::CP_LMS_TRAP:
133*f22f0ef4Schristos 	  found = root->find (L_CP_TOTAL_CPU);
134*f22f0ef4Schristos 	  break;
135*f22f0ef4Schristos 	case BaseMetric::HWCNTR:
136*f22f0ef4Schristos 	  found = root->find ((item->get_flavors () & BaseMetric::DATASPACE) != 0 ?
137*f22f0ef4Schristos 			      L2_HWC_DSPACE : L2_HWC_GENERAL);
138*f22f0ef4Schristos 	  break;
139*f22f0ef4Schristos 	case BaseMetric::SYNC_WAIT_TIME:
140*f22f0ef4Schristos 	case BaseMetric::SYNC_WAIT_COUNT:
141*f22f0ef4Schristos 	  found = root->find (get_prof_data_type_name (DATA_SYNCH));
142*f22f0ef4Schristos 	  break;
143*f22f0ef4Schristos 	case BaseMetric::OMP_WORK:
144*f22f0ef4Schristos 	case BaseMetric::OMP_WAIT:
145*f22f0ef4Schristos 	case BaseMetric::OMP_OVHD:
146*f22f0ef4Schristos 	  found = root->find (get_prof_data_type_name (DATA_OMP));
147*f22f0ef4Schristos 	  break;
148*f22f0ef4Schristos 	case BaseMetric::IO_READ_TIME:
149*f22f0ef4Schristos 	case BaseMetric::IO_READ_BYTES:
150*f22f0ef4Schristos 	case BaseMetric::IO_READ_CNT:
151*f22f0ef4Schristos 	case BaseMetric::IO_WRITE_TIME:
152*f22f0ef4Schristos 	case BaseMetric::IO_WRITE_BYTES:
153*f22f0ef4Schristos 	case BaseMetric::IO_WRITE_CNT:
154*f22f0ef4Schristos 	case BaseMetric::IO_OTHER_TIME:
155*f22f0ef4Schristos 	case BaseMetric::IO_OTHER_CNT:
156*f22f0ef4Schristos 	case BaseMetric::IO_ERROR_TIME:
157*f22f0ef4Schristos 	case BaseMetric::IO_ERROR_CNT:
158*f22f0ef4Schristos 	  found = root->find (get_prof_data_type_name (DATA_IOTRACE));
159*f22f0ef4Schristos 	  break;
160*f22f0ef4Schristos 	case BaseMetric::ONAME:
161*f22f0ef4Schristos 	case BaseMetric::SIZES:
162*f22f0ef4Schristos 	case BaseMetric::ADDRESS:
163*f22f0ef4Schristos 	  found = root->find (L1_STATIC);
164*f22f0ef4Schristos 	  break;
165*f22f0ef4Schristos 	default:
166*f22f0ef4Schristos 	  found = root->find (L1_OTHER);
167*f22f0ef4Schristos 	  break;
168*f22f0ef4Schristos 	}
169*f22f0ef4Schristos       assert (found != NULL);
170*f22f0ef4Schristos       switch (item->get_type ())
171*f22f0ef4Schristos 	{
172*f22f0ef4Schristos 	case BaseMetric::CP_TOTAL:
173*f22f0ef4Schristos 	case BaseMetric::CP_TOTAL_CPU:
174*f22f0ef4Schristos 	  found->isCompositeMetric = true;
175*f22f0ef4Schristos 	  break;
176*f22f0ef4Schristos 	}
177*f22f0ef4Schristos       found = found->add_child (item);
178*f22f0ef4Schristos     }
179*f22f0ef4Schristos   register_node (found);
180*f22f0ef4Schristos   return found;
181*f22f0ef4Schristos }
182*f22f0ef4Schristos 
183*f22f0ef4Schristos void
register_node(BaseMetricTreeNode * node)184*f22f0ef4Schristos BaseMetricTreeNode::register_node (BaseMetricTreeNode *node)
185*f22f0ef4Schristos {
186*f22f0ef4Schristos   if (!node->registered)
187*f22f0ef4Schristos     {
188*f22f0ef4Schristos       node->registered = true;
189*f22f0ef4Schristos       BaseMetricTreeNode *tmp = node->parent;
190*f22f0ef4Schristos       while (tmp)
191*f22f0ef4Schristos 	{
192*f22f0ef4Schristos 	  tmp->num_registered_descendents++;
193*f22f0ef4Schristos 	  tmp = tmp->parent;
194*f22f0ef4Schristos 	}
195*f22f0ef4Schristos     }
196*f22f0ef4Schristos }
197*f22f0ef4Schristos 
198*f22f0ef4Schristos BaseMetricTreeNode *
find(const char * _name)199*f22f0ef4Schristos BaseMetricTreeNode::find (const char *_name)
200*f22f0ef4Schristos {
201*f22f0ef4Schristos   BaseMetricTreeNode *found = NULL;
202*f22f0ef4Schristos   if (dbe_strcmp (get_name (), _name) == 0)
203*f22f0ef4Schristos     return this;
204*f22f0ef4Schristos   if (bm && dbe_strcmp (bm->get_cmd (), _name) == 0)
205*f22f0ef4Schristos     return this;
206*f22f0ef4Schristos   BaseMetricTreeNode *child;
207*f22f0ef4Schristos   int index;
208*f22f0ef4Schristos 
209*f22f0ef4Schristos   Vec_loop (BaseMetricTreeNode*, children, index, child)
210*f22f0ef4Schristos   {
211*f22f0ef4Schristos     found = child->find (_name);
212*f22f0ef4Schristos     if (found)
213*f22f0ef4Schristos       return found;
214*f22f0ef4Schristos   }
215*f22f0ef4Schristos   return NULL;
216*f22f0ef4Schristos }
217*f22f0ef4Schristos 
218*f22f0ef4Schristos static void
int_get_registered_descendents(BaseMetricTreeNode * curr,Vector<BaseMetricTreeNode * > * dest,bool nearest_only)219*f22f0ef4Schristos int_get_registered_descendents (BaseMetricTreeNode* curr,
220*f22f0ef4Schristos 			  Vector<BaseMetricTreeNode*> *dest, bool nearest_only)
221*f22f0ef4Schristos {
222*f22f0ef4Schristos   if (!curr)
223*f22f0ef4Schristos     return;
224*f22f0ef4Schristos   if (curr->is_registered ())
225*f22f0ef4Schristos     {
226*f22f0ef4Schristos       dest->append (curr);
227*f22f0ef4Schristos       if (nearest_only)
228*f22f0ef4Schristos 	return; // soon as we hit a live node, stop following branch
229*f22f0ef4Schristos     }
230*f22f0ef4Schristos   int index;
231*f22f0ef4Schristos   BaseMetricTreeNode *child;
232*f22f0ef4Schristos 
233*f22f0ef4Schristos   Vec_loop (BaseMetricTreeNode*, curr->get_children (), index, child)
234*f22f0ef4Schristos   {
235*f22f0ef4Schristos     int_get_registered_descendents (child, dest, nearest_only);
236*f22f0ef4Schristos   }
237*f22f0ef4Schristos }
238*f22f0ef4Schristos 
239*f22f0ef4Schristos void
get_nearest_registered_descendents(Vector<BaseMetricTreeNode * > * dest)240*f22f0ef4Schristos BaseMetricTreeNode::get_nearest_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
241*f22f0ef4Schristos {
242*f22f0ef4Schristos   if (!dest || dest->size () != 0)
243*f22f0ef4Schristos     abort ();
244*f22f0ef4Schristos   bool nearest_only = true;
245*f22f0ef4Schristos   int_get_registered_descendents (this, dest, nearest_only);
246*f22f0ef4Schristos }
247*f22f0ef4Schristos 
248*f22f0ef4Schristos void
get_all_registered_descendents(Vector<BaseMetricTreeNode * > * dest)249*f22f0ef4Schristos BaseMetricTreeNode::get_all_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
250*f22f0ef4Schristos {
251*f22f0ef4Schristos   if (!dest || dest->size () != 0)
252*f22f0ef4Schristos     abort ();
253*f22f0ef4Schristos   bool nearest_only = false;
254*f22f0ef4Schristos   int_get_registered_descendents (this, dest, nearest_only);
255*f22f0ef4Schristos }
256*f22f0ef4Schristos 
257*f22f0ef4Schristos char *
get_description()258*f22f0ef4Schristos BaseMetricTreeNode::get_description ()
259*f22f0ef4Schristos {
260*f22f0ef4Schristos   if (bm)
261*f22f0ef4Schristos     {
262*f22f0ef4Schristos       Hwcentry* hw_ctr = bm->get_hw_ctr ();
263*f22f0ef4Schristos       if (hw_ctr)
264*f22f0ef4Schristos 	return hw_ctr->short_desc;
265*f22f0ef4Schristos     }
266*f22f0ef4Schristos   return NULL;
267*f22f0ef4Schristos }
268*f22f0ef4Schristos 
269*f22f0ef4Schristos void
build_basic_tree()270*f22f0ef4Schristos BaseMetricTreeNode::build_basic_tree ()
271*f22f0ef4Schristos {
272*f22f0ef4Schristos #define TREE_INSERT_DATA_TYPE(t) add_child(get_prof_data_type_name (t), get_prof_data_type_uname (t))
273*f22f0ef4Schristos   BaseMetricTreeNode *level1, *level2;
274*f22f0ef4Schristos   // register L1_DURATION here because it has a value but is not a true metric
275*f22f0ef4Schristos   register_node (add_child (L1_DURATION, L1_DURATION_UNAME, UNIT_SECONDS,
276*f22f0ef4Schristos 			    UNIT_SECONDS_UNAME));
277*f22f0ef4Schristos   register_node (add_child (L1_GCDURATION, L1_GCDURATION_UNAME, UNIT_SECONDS,
278*f22f0ef4Schristos 			    UNIT_SECONDS_UNAME));
279*f22f0ef4Schristos   TREE_INSERT_DATA_TYPE (DATA_HEAP);
280*f22f0ef4Schristos   level1 = TREE_INSERT_DATA_TYPE (DATA_CLOCK);
281*f22f0ef4Schristos   level1 = level1->add_child (L_CP_TOTAL, GTXT ("XXX Total Thread Time"));
282*f22f0ef4Schristos   level1->isCompositeMetric = true;
283*f22f0ef4Schristos   level2 = level1->add_child (L_CP_TOTAL_CPU, GTXT ("XXX Total CPU Time"));
284*f22f0ef4Schristos   level2->isCompositeMetric = true;
285*f22f0ef4Schristos 
286*f22f0ef4Schristos   add_child (L1_OTHER, L1_OTHER_UNAME);
287*f22f0ef4Schristos   level1 = TREE_INSERT_DATA_TYPE (DATA_HWC);
288*f22f0ef4Schristos   level1->add_child (L2_HWC_DSPACE, L2_HWC_DSPACE_UNAME);
289*f22f0ef4Schristos   level1->add_child (L2_HWC_GENERAL, L2_HWC_GENERAL_UNAME);
290*f22f0ef4Schristos   TREE_INSERT_DATA_TYPE (DATA_SYNCH);
291*f22f0ef4Schristos   TREE_INSERT_DATA_TYPE (DATA_OMP);
292*f22f0ef4Schristos   TREE_INSERT_DATA_TYPE (DATA_IOTRACE);
293*f22f0ef4Schristos   add_child (L1_STATIC, L1_STATIC_UNAME);
294*f22f0ef4Schristos }
295*f22f0ef4Schristos 
296*f22f0ef4Schristos BaseMetricTreeNode *
add_child(BaseMetric * item)297*f22f0ef4Schristos BaseMetricTreeNode::add_child (BaseMetric *item)
298*f22f0ef4Schristos {
299*f22f0ef4Schristos   return add_child (new BaseMetricTreeNode (item));
300*f22f0ef4Schristos }
301*f22f0ef4Schristos 
302*f22f0ef4Schristos BaseMetricTreeNode *
add_child(const char * _name,const char * _uname,const char * _unit,const char * _unit_uname)303*f22f0ef4Schristos BaseMetricTreeNode::add_child (const char * _name, const char *_uname,
304*f22f0ef4Schristos 			       const char * _unit, const char * _unit_uname)
305*f22f0ef4Schristos {
306*f22f0ef4Schristos   return add_child (new BaseMetricTreeNode (_name, _uname, _unit, _unit_uname));
307*f22f0ef4Schristos }
308*f22f0ef4Schristos 
309*f22f0ef4Schristos BaseMetricTreeNode *
add_child(BaseMetricTreeNode * new_node)310*f22f0ef4Schristos BaseMetricTreeNode::add_child (BaseMetricTreeNode *new_node)
311*f22f0ef4Schristos {
312*f22f0ef4Schristos   new_node->parent = this;
313*f22f0ef4Schristos   new_node->root = root;
314*f22f0ef4Schristos   children->append (new_node);
315*f22f0ef4Schristos   return new_node;
316*f22f0ef4Schristos }
317*f22f0ef4Schristos 
318*f22f0ef4Schristos char *
dump()319*f22f0ef4Schristos BaseMetricTreeNode::dump ()
320*f22f0ef4Schristos {
321*f22f0ef4Schristos   int len = 4;
322*f22f0ef4Schristos   char *s = bm ? bm->dump () : dbe_strdup ("<no base metric>");
323*f22f0ef4Schristos   char *msg = dbe_sprintf ("%s\n%*c %*c unit='%s' unit_uname='%s' uname='%s' name='%s'\n",
324*f22f0ef4Schristos 			   STR (s), len, ' ', len, ' ',
325*f22f0ef4Schristos 			   STR (get_unit_uname ()), STR (get_unit ()),
326*f22f0ef4Schristos 			   STR (get_user_name ()), STR (get_name ()));
327*f22f0ef4Schristos   free (s);
328*f22f0ef4Schristos   return msg;
329*f22f0ef4Schristos }
330