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