1 /* Copyright (C) 2021 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 <strings.h>
23 #include <stdlib.h>
24 
25 #include "util.h"
26 #include "BaseMetric.h"
27 #include "DbeSession.h"
28 #include "Expression.h"
29 
30 int BaseMetric::last_id = 0;
31 
32 void
init(Type t)33 BaseMetric::init (Type t)
34 {
35   id = last_id++;
36   type = t;
37   aux = NULL;
38   cmd = NULL;
39   username = NULL;
40   hw_ctr = NULL;
41   cond = NULL;
42   val = NULL;
43   expr = NULL;
44   cond_spec = NULL;
45   val_spec = NULL;
46   expr_spec = NULL;
47   legend = NULL;
48   definition = NULL;
49   dependent_bm = NULL;
50   zeroThreshold = 0;
51   clock_unit = (Presentation_clock_unit) 0;
52   for (int ii = 0; ii < NSUBTYPES; ii++)
53     default_visbits[ii] = VAL_NA;
54   valtype = VT_DOUBLE;
55   precision = METRIC_HR_PRECISION;
56   flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
57   value_styles = VAL_TIMEVAL | VAL_PERCENT;
58 }
59 
BaseMetric(Type t)60 BaseMetric::BaseMetric (Type t)
61 {
62   init (t);
63   switch (t)
64     {
65     case CP_LMS_USER:
66     case CP_LMS_SYSTEM:
67     case CP_LMS_WAIT_CPU:
68     case CP_LMS_USER_LOCK:
69     case CP_LMS_TFAULT:
70     case CP_LMS_DFAULT:
71     case OMP_MASTER_THREAD:
72     case CP_TOTAL:
73     case CP_TOTAL_CPU:
74     case CP_LMS_TRAP:
75     case CP_LMS_KFAULT:
76     case CP_LMS_SLEEP:
77     case CP_LMS_STOPPED:
78     case OMP_NONE:
79     case OMP_OVHD:
80     case OMP_WORK:
81     case OMP_IBAR:
82     case OMP_EBAR:
83     case OMP_WAIT:
84     case OMP_SERL:
85     case OMP_RDUC:
86     case OMP_LKWT:
87     case OMP_CTWT:
88     case OMP_ODWT:
89     case OMP_MSTR:
90     case OMP_SNGL:
91     case OMP_ORDD:
92     case CP_KERNEL_CPU:
93       // all of these are floating point, precision = clock profile tick
94       valtype = VT_DOUBLE;
95       precision = METRIC_SIG_PRECISION;
96       flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
97       value_styles = VAL_TIMEVAL | VAL_PERCENT;
98       break;
99     case SYNC_WAIT_TIME:
100     case IO_READ_TIME:
101     case IO_WRITE_TIME:
102     case IO_OTHER_TIME:
103     case IO_ERROR_TIME:
104       // all of these are floating point, precision = hrtime tick
105       valtype = VT_DOUBLE;
106       precision = METRIC_HR_PRECISION;
107       flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
108       value_styles = VAL_TIMEVAL | VAL_PERCENT;
109       break;
110     case SYNC_WAIT_COUNT:
111     case HEAP_ALLOC_CNT:
112     case HEAP_LEAK_CNT:
113     case IO_READ_CNT:
114     case IO_WRITE_CNT:
115     case IO_OTHER_CNT:
116     case IO_ERROR_CNT:
117       valtype = VT_LLONG;
118       precision = 1;
119       flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
120       value_styles = VAL_VALUE | VAL_PERCENT;
121       break;
122     case RACCESS:
123     case DEADLOCKS:
124       // all of these are integer
125       valtype = VT_LLONG;
126       precision = 1;
127       flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
128       value_styles = VAL_VALUE | VAL_PERCENT;
129       zeroThreshold = 1;
130       break;
131     case HEAP_ALLOC_BYTES:
132     case HEAP_LEAK_BYTES:
133     case IO_READ_BYTES:
134     case IO_WRITE_BYTES:
135       // all of these are longlong
136       valtype = VT_ULLONG;
137       precision = 1;
138       flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
139       value_styles = VAL_VALUE | VAL_PERCENT;
140       break;
141     case SIZES:
142       valtype = VT_LLONG;
143       precision = 1;
144       flavors = STATIC;
145       value_styles = VAL_VALUE;
146       break;
147     case ADDRESS:
148       valtype = VT_ADDRESS;
149       precision = 1;
150       flavors = STATIC;
151       value_styles = VAL_VALUE;
152       break;
153     case ONAME:
154       valtype = VT_LABEL;
155       precision = 0;
156       flavors = STATIC;
157       value_styles = VAL_VALUE;
158       break;
159     case HWCNTR: // We should call the other constructor for hwc metric
160     default:
161       abort ();
162     }
163   specify ();
164 }
165 
166 // Constructor for linked HW counters (base counter)
BaseMetric(Hwcentry * ctr,const char * _aux,const char * _username,int v_styles,BaseMetric * _dependent_bm)167 BaseMetric::BaseMetric (Hwcentry *ctr, const char* _aux, const char* _username,
168 			int v_styles, BaseMetric* _dependent_bm)
169 {
170   hwc_init (ctr, _aux, _aux, _username, v_styles);
171   dependent_bm = _dependent_bm;
172 }
173 
174 // Constructor for linked HW counters (derived counter)
175 
BaseMetric(Hwcentry * ctr,const char * _aux,const char * _cmdname,const char * _username,int v_styles)176 BaseMetric::BaseMetric (Hwcentry *ctr, const char *_aux, const char *_cmdname,
177 			const char *_username, int v_styles)
178 {
179   hwc_init (ctr, _aux, _cmdname, _username, v_styles);
180 }
181 
182 void
hwc_init(Hwcentry * ctr,const char * _aux,const char * _cmdname,const char * _username,int v_styles)183 BaseMetric::hwc_init (Hwcentry *ctr, const char* _aux, const char* _cmdname,
184 		      const char* _username, int v_styles)
185 {
186   init (HWCNTR);
187   aux = dbe_strdup (_aux);      // HWC identifier
188   cmd = dbe_strdup (_cmdname);  // may differ from _aux for cycles->time hwcs
189   username = dbe_strdup (_username);
190   flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
191   value_styles = v_styles | VAL_PERCENT;
192   if ((value_styles & (VAL_TIMEVAL | VAL_VALUE)) == VAL_TIMEVAL)
193     valtype = VT_DOUBLE;
194   else
195     valtype = VT_ULLONG;
196   if (ABST_MEMSPACE_ENABLED (ctr->memop))
197     flavors |= DATASPACE; // only for ctrs with memop definitions
198   hw_ctr = ctr;
199   specify ();
200 }
201 
202 // Constructor for derived metrics
BaseMetric(const char * _cmd,const char * _username,Definition * def)203 BaseMetric::BaseMetric (const char *_cmd, const char *_username,
204 			Definition *def)
205 {
206   init (DERIVED);
207   cmd = dbe_strdup (_cmd);
208   username = dbe_strdup (_username);
209   aux = dbe_strdup (_cmd);
210   definition = def;
211   flavors = EXCLUSIVE | INCLUSIVE | ATTRIBUTED;
212   clock_unit = CUNIT_NULL; // should it be CUNIT_TIME or 0 or something?
213 
214   /* we're not going to process packets for derived metrics */
215   packet_type = (ProfData_type) (-1);
216   value_styles = VAL_VALUE;
217   valtype = VT_DOUBLE;
218   precision = 1000;
219 }
220 
221 // Copy constructor
BaseMetric(const BaseMetric & m)222 BaseMetric::BaseMetric (const BaseMetric& m)
223 {
224   id = m.id;
225   type = m.type;
226   aux = dbe_strdup (m.aux);
227   cmd = dbe_strdup (m.cmd);
228   username = dbe_strdup (m.username);
229   flavors = m.flavors;
230   value_styles = m.value_styles;
231   valtype = m.valtype;
232   precision = m.precision;
233   hw_ctr = m.hw_ctr;
234   packet_type = m.packet_type;
235   zeroThreshold = m.zeroThreshold;
236   clock_unit = m.clock_unit;
237   for (int ii = 0; ii < NSUBTYPES; ii++)
238     default_visbits[ii] = m.default_visbits[ii];
239   if (m.cond_spec)
240     {
241       cond_spec = strdup (m.cond_spec);
242       cond = m.cond->copy ();
243     }
244   else
245     {
246       cond = NULL;
247       cond_spec = NULL;
248     }
249   if (m.val_spec)
250     {
251       val_spec = strdup (m.val_spec);
252       val = m.val->copy ();
253     }
254   else
255     {
256       val = NULL;
257       val_spec = NULL;
258     }
259   if (m.expr_spec)
260     {
261       expr_spec = strdup (m.expr_spec);
262       expr = m.expr->copy ();
263     }
264   else
265     {
266       expr = NULL;
267       expr_spec = NULL;
268     }
269   legend = dbe_strdup (m.legend);
270   definition = NULL;
271   if (m.definition)
272     definition = Definition::add_definition (m.definition->def);
273   dependent_bm = m.dependent_bm;
274 }
275 
~BaseMetric()276 BaseMetric::~BaseMetric ()
277 {
278   free (aux);
279   free (cmd);
280   free (cond_spec);
281   free (val_spec);
282   free (expr_spec);
283   free (legend);
284   free (username);
285   delete cond;
286   delete val;
287   delete expr;
288   delete definition;
289 }
290 
291 bool
is_internal()292 BaseMetric::is_internal ()
293 {
294   return (get_value_styles () & VAL_INTERNAL) != 0;
295 }
296 
297 int
get_default_visbits(SubType subtype)298 BaseMetric::get_default_visbits (SubType subtype)
299 {
300   int rc = VAL_NA;
301   switch (subtype)
302     {
303     case STATIC:
304     case EXCLUSIVE:
305       rc = default_visbits[0];
306       break;
307     case INCLUSIVE:
308       rc = default_visbits[1];
309       break;
310     default:
311       break;
312     }
313   return rc;
314 }
315 
316 void
set_default_visbits(SubType subtype,int _visbits)317 BaseMetric::set_default_visbits (SubType subtype, int _visbits)
318 {
319   switch (subtype)
320     {
321     case STATIC:
322     case EXCLUSIVE:
323       default_visbits[0] = _visbits;
324       break;
325     case INCLUSIVE:
326       default_visbits[1] = _visbits;
327       break;
328     default:
329       break;
330     }
331 }
332 
333 void
set_cond_spec(char * _cond_spec)334 BaseMetric::set_cond_spec (char *_cond_spec)
335 {
336   if (cond_spec)
337     {
338       free (cond_spec);
339       delete cond;
340       cond_spec = NULL;
341       cond = NULL;
342     }
343   if (_cond_spec)
344     {
345       cond = dbeSession->ql_parse (_cond_spec);
346       if (cond == NULL)
347 	{
348 	  fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _cond_spec);
349 	  abort ();
350 	}
351       cond_spec = dbe_strdup (_cond_spec);
352     }
353 }
354 
355 void
set_val_spec(char * _val_spec)356 BaseMetric::set_val_spec (char *_val_spec)
357 {
358   if (val_spec)
359     {
360       free (val_spec);
361       delete val;
362       val_spec = NULL;
363       val = NULL;
364     }
365   if (_val_spec)
366     {
367       val = dbeSession->ql_parse (_val_spec);
368       if (val == NULL)
369 	{
370 	  fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _val_spec);
371 	  abort ();
372 	}
373       val_spec = dbe_strdup (_val_spec);
374     }
375 }
376 
377 void
set_expr_spec(char * _expr_spec)378 BaseMetric::set_expr_spec (char *_expr_spec)
379 {
380   id = last_id++;
381   if (expr_spec)
382     {
383       free (expr_spec);
384       delete expr;
385       expr_spec = NULL;
386       expr = NULL;
387     }
388   if (_expr_spec)
389     {
390       expr = dbeSession->ql_parse (_expr_spec);
391       if (expr == NULL)
392 	{
393 	  fprintf (stderr, GTXT ("Invalid expression in metric specification `%s'\n"), _expr_spec);
394 	  return;
395 	}
396       expr_spec = dbe_strdup (_expr_spec);
397     }
398 }
399 
400 void
specify_mstate_metric(int st)401 BaseMetric::specify_mstate_metric (int st)
402 {
403   char buf[128];
404   snprintf (buf, sizeof (buf), NTXT ("MSTATE==%d"), st);
405   specify_prof_metric (buf);
406 }
407 
408 void
specify_ompstate_metric(int st)409 BaseMetric::specify_ompstate_metric (int st)
410 {
411   char buf[128];
412   snprintf (buf, sizeof (buf), NTXT ("OMPSTATE==%d"), st);
413   specify_prof_metric (buf);
414 }
415 
416 void
specify_prof_metric(char * _cond_spec)417 BaseMetric::specify_prof_metric (char *_cond_spec)
418 {
419   packet_type = DATA_CLOCK;
420   specify_metric (_cond_spec, NTXT ("NTICK_USEC")); // microseconds
421 }
422 
423 void
specify_metric(char * _cond_spec,char * _val_spec)424 BaseMetric::specify_metric (char *_cond_spec, char *_val_spec)
425 {
426   set_cond_spec (_cond_spec);
427   set_val_spec (_val_spec);
428 }
429 
430 void
specify()431 BaseMetric::specify ()
432 {
433   enum
434   {
435     IDLE_STATE_BITS =
436 	(1 << OMP_IDLE_STATE) | (1 << OMP_IBAR_STATE) | (1 << OMP_EBAR_STATE) |
437 	(1 << OMP_LKWT_STATE) | (1 << OMP_CTWT_STATE) | (1 << OMP_ODWT_STATE) |
438 	(1 << OMP_ATWT_STATE) | (1 << OMP_TSKWT_STATE),
439     LMS_USER_BITS =
440 	(1 << OMP_NO_STATE) | (1 << OMP_WORK_STATE) | (1 << OMP_SERL_STATE) |
441 	(1 << OMP_RDUC_STATE)
442   };
443 
444   char buf[256];
445   char buf2[256];
446   packet_type = (ProfData_type) - 1; // illegal value
447   clock_unit = CUNIT_TIME;
448   switch (type)
449     {
450     case SIZES:
451       username = dbe_strdup (GTXT ("Size"));
452       clock_unit = CUNIT_BYTES;
453       cmd = dbe_strdup (NTXT ("size"));
454       break;
455     case ADDRESS:
456       username = dbe_strdup (GTXT ("PC Address"));
457       cmd = dbe_strdup (NTXT ("address"));
458       break;
459     case ONAME:
460       username = dbe_strdup (GTXT ("Name"));
461       cmd = dbe_strdup (NTXT ("name"));
462       break;
463     case CP_LMS_SYSTEM:
464       username = dbe_strdup (GTXT ("System CPU Time"));
465       specify_mstate_metric (LMS_SYSTEM);
466       cmd = dbe_strdup (NTXT ("system"));
467       break;
468     case CP_TOTAL_CPU:
469       username = dbe_strdup (GTXT ("Total CPU Time"));
470       snprintf (buf, sizeof (buf),
471 		"(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)||(MSTATE==%d)",
472 		LMS_USER, LMS_SYSTEM, LMS_TRAP, LMS_LINUX_CPU);
473       specify_prof_metric (buf);
474       cmd = dbe_strdup (NTXT ("totalcpu"));
475       break;
476     case CP_TOTAL:
477       username = dbe_strdup (GTXT ("Total Thread Time"));
478       snprintf (buf, sizeof (buf), NTXT ("(MSTATE!=%d)&&(MSTATE!=%d)"),
479 		LMS_KERNEL_CPU, LMS_LINUX_CPU);
480       specify_prof_metric (buf);
481       cmd = dbe_strdup (NTXT ("total"));
482       break;
483     case CP_KERNEL_CPU:
484       username = dbe_strdup (GTXT ("Kernel CPU Time"));
485       specify_mstate_metric (LMS_KERNEL_CPU);
486       cmd = dbe_strdup (NTXT ("kcpu"));
487       break;
488     case OMP_MASTER_THREAD:
489       username = dbe_strdup (GTXT ("Master Thread Time"));
490       specify_prof_metric (NTXT ("LWPID==1"));
491       cmd = dbe_strdup (NTXT ("masterthread"));
492       break;
493     case CP_LMS_USER:
494       username = dbe_strdup (GTXT ("User CPU Time"));
495       specify_mstate_metric (LMS_USER);
496       cmd = dbe_strdup (NTXT ("user"));
497       break;
498     case CP_LMS_WAIT_CPU:
499       username = dbe_strdup (GTXT ("Wait CPU Time"));
500       specify_mstate_metric (LMS_WAIT_CPU);
501       cmd = dbe_strdup (NTXT ("wait"));
502       break;
503     case CP_LMS_USER_LOCK:
504       username = dbe_strdup (GTXT ("User Lock Time"));
505       specify_mstate_metric (LMS_USER_LOCK);
506       cmd = dbe_strdup (NTXT ("lock"));
507       break;
508     case CP_LMS_TFAULT:
509       username = dbe_strdup (GTXT ("Text Page Fault Time"));
510       specify_mstate_metric (LMS_TFAULT);
511       cmd = dbe_strdup (NTXT ("textpfault"));
512       break;
513     case CP_LMS_DFAULT:
514       username = dbe_strdup (GTXT ("Data Page Fault Time"));
515       specify_mstate_metric (LMS_DFAULT);
516       cmd = dbe_strdup (NTXT ("datapfault"));
517       break;
518     case CP_LMS_TRAP:
519       username = dbe_strdup (GTXT ("Trap CPU Time"));
520       specify_mstate_metric (LMS_TRAP);
521       cmd = dbe_strdup (NTXT ("trap"));
522       break;
523     case CP_LMS_KFAULT:
524       username = dbe_strdup (GTXT ("Kernel Page Fault Time"));
525       specify_mstate_metric (LMS_KFAULT);
526       cmd = dbe_strdup (NTXT ("kernelpfault"));
527       break;
528     case CP_LMS_SLEEP:
529       username = dbe_strdup (GTXT ("Sleep Time"));
530       specify_mstate_metric (LMS_SLEEP);
531       cmd = dbe_strdup (NTXT ("sleep"));
532       break;
533     case CP_LMS_STOPPED:
534       username = dbe_strdup (GTXT ("Stopped Time"));
535       specify_mstate_metric (LMS_STOPPED);
536       cmd = dbe_strdup (NTXT ("stop"));
537       break;
538     case OMP_OVHD:
539       username = dbe_strdup (GTXT ("OpenMP Overhead Time"));
540       specify_ompstate_metric (OMP_OVHD_STATE);
541       cmd = dbe_strdup (NTXT ("ompovhd"));
542       break;
543     case OMP_WORK:
544       username = dbe_strdup (GTXT ("OpenMP Work Time"));
545       snprintf (buf, sizeof (buf),
546 		NTXT ("(OMPSTATE>=0) && (MSTATE==%d) && ((1<<OMPSTATE) & %d)"),
547 		LMS_USER, LMS_USER_BITS);
548       specify_prof_metric (buf);
549       cmd = dbe_strdup (NTXT ("ompwork"));
550       break;
551     case OMP_WAIT:
552       username = dbe_strdup (GTXT ("OpenMP Wait Time"));
553       snprintf (buf, sizeof (buf),
554 		"OMPSTATE>=0 && ((1<<OMPSTATE) & ((MSTATE!=%d) ? %d : %d))",
555 		LMS_USER, (LMS_USER_BITS | IDLE_STATE_BITS), IDLE_STATE_BITS);
556       specify_prof_metric (buf);
557       cmd = dbe_strdup (NTXT ("ompwait"));
558       break;
559     case OMP_IBAR:
560       username = dbe_strdup (GTXT ("OpenMP Implicit Barrier Time"));
561       specify_ompstate_metric (OMP_IBAR_STATE);
562       cmd = dbe_strdup (NTXT ("ompibar"));
563       break;
564     case OMP_EBAR:
565       username = dbe_strdup (GTXT ("OpenMP Explicit Barrier Time"));
566       specify_ompstate_metric (OMP_EBAR_STATE);
567       cmd = dbe_strdup (NTXT ("ompebar"));
568       break;
569     case OMP_SERL:
570       username = dbe_strdup (GTXT ("OpenMP Serial Time"));
571       specify_ompstate_metric (OMP_SERL_STATE);
572       cmd = dbe_strdup (NTXT ("ompserl"));
573       break;
574     case OMP_RDUC:
575       username = dbe_strdup (GTXT ("OpenMP Reduction Time"));
576       specify_ompstate_metric (OMP_RDUC_STATE);
577       cmd = dbe_strdup (NTXT ("omprduc"));
578       break;
579     case OMP_LKWT:
580       username = dbe_strdup (GTXT ("OpenMP Lock Wait Time"));
581       specify_ompstate_metric (OMP_LKWT_STATE);
582       cmd = dbe_strdup (NTXT ("omplkwt"));
583       break;
584     case OMP_CTWT:
585       username = dbe_strdup (GTXT ("OpenMP Critical Section Wait Time"));
586       specify_ompstate_metric (OMP_CTWT_STATE);
587       cmd = dbe_strdup (NTXT ("ompctwt"));
588       break;
589     case OMP_ODWT:
590       username = dbe_strdup (GTXT ("OpenMP Ordered Section Wait Time"));
591       specify_ompstate_metric (OMP_ODWT_STATE);
592       cmd = dbe_strdup (NTXT ("ompodwt"));
593       break;
594     case SYNC_WAIT_TIME:
595       packet_type = DATA_SYNCH;
596       username = dbe_strdup (GTXT ("Sync Wait Time"));
597       snprintf (buf, sizeof (buf), NTXT ("(EVT_TIME)/%lld"),
598 		(long long) (NANOSEC / METRIC_HR_PRECISION));
599       specify_metric (NULL, buf);
600       cmd = dbe_strdup (NTXT ("sync"));
601       break;
602     case SYNC_WAIT_COUNT:
603       packet_type = DATA_SYNCH;
604       username = dbe_strdup (GTXT ("Sync Wait Count"));
605       specify_metric (NULL, NTXT ("1"));
606       cmd = dbe_strdup (NTXT ("syncn"));
607       break;
608     case HEAP_ALLOC_CNT:
609       packet_type = DATA_HEAP;
610       username = dbe_strdup (GTXT ("Allocations"));
611       snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"),
612 		FREE_TRACE, MUNMAP_TRACE);
613       specify_metric (buf, NTXT ("1"));
614       cmd = dbe_strdup (NTXT ("heapalloccnt"));
615       break;
616     case HEAP_ALLOC_BYTES:
617       packet_type = DATA_HEAP;
618       username = dbe_strdup (GTXT ("Bytes Allocated"));
619       snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"),
620 		FREE_TRACE, MUNMAP_TRACE);
621       specify_metric (buf, NTXT ("HSIZE"));
622       cmd = dbe_strdup (NTXT ("heapallocbytes"));
623       break;
624     case HEAP_LEAK_CNT:
625       packet_type = DATA_HEAP;
626       username = dbe_strdup (GTXT ("Leaks"));
627       snprintf (buf, sizeof (buf), "(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR&&HLEAKED",
628 		FREE_TRACE, MUNMAP_TRACE);
629       specify_metric (buf, NTXT ("1"));
630       cmd = dbe_strdup (NTXT ("heapleakcnt"));
631       break;
632     case HEAP_LEAK_BYTES:
633       packet_type = DATA_HEAP;
634       username = dbe_strdup (GTXT ("Bytes Leaked"));
635       snprintf (buf, sizeof (buf), NTXT ("(HTYPE!=%d)&&(HTYPE!=%d)&&HVADDR"),
636 		FREE_TRACE, MUNMAP_TRACE);
637       specify_metric (buf, NTXT ("HLEAKED"));
638       cmd = dbe_strdup (NTXT ("heapleakbytes"));
639       break;
640 
641     case IO_READ_CNT:
642       packet_type = DATA_IOTRACE;
643       username = dbe_strdup (GTXT ("Read Count"));
644       snprintf (buf, sizeof (buf), "(IOTYPE==%d)", READ_TRACE);
645       specify_metric (buf, NTXT ("1"));
646       cmd = dbe_strdup (NTXT ("ioreadcnt"));
647       break;
648     case IO_WRITE_CNT:
649       packet_type = DATA_IOTRACE;
650       username = dbe_strdup (GTXT ("Write Count"));
651       snprintf (buf, sizeof (buf), "(IOTYPE==%d)", WRITE_TRACE);
652       specify_metric (buf, NTXT ("1"));
653       cmd = dbe_strdup (NTXT ("iowritecnt"));
654       break;
655     case IO_OTHER_CNT:
656       packet_type = DATA_IOTRACE;
657       username = dbe_strdup (GTXT ("Other I/O Count"));
658       snprintf (buf, sizeof (buf), "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)",
659 		OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE);
660       specify_metric (buf, NTXT ("1"));
661       cmd = dbe_strdup (NTXT ("ioothercnt"));
662       break;
663     case IO_ERROR_CNT:
664       packet_type = DATA_IOTRACE;
665       username = dbe_strdup (GTXT ("I/O Error Count"));
666       snprintf (buf, sizeof (buf),
667 	 "(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)",
668 	 READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR,
669 	 CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR);
670       specify_metric (buf, NTXT ("1"));
671       cmd = dbe_strdup (NTXT ("ioerrorcnt"));
672       break;
673     case IO_READ_BYTES:
674       packet_type = DATA_IOTRACE;
675       username = dbe_strdup (GTXT ("Read Bytes"));
676       snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&IONBYTE"),
677 		READ_TRACE);
678       specify_metric (buf, NTXT ("IONBYTE"));
679       cmd = dbe_strdup (NTXT ("ioreadbytes"));
680       break;
681     case IO_WRITE_BYTES:
682       packet_type = DATA_IOTRACE;
683       username = dbe_strdup (GTXT ("Write Bytes"));
684       snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&IONBYTE", WRITE_TRACE);
685       specify_metric (buf, NTXT ("IONBYTE"));
686       cmd = dbe_strdup (NTXT ("iowritebytes"));
687       break;
688     case IO_READ_TIME:
689       packet_type = DATA_IOTRACE;
690       username = dbe_strdup (GTXT ("Read Time"));
691       snprintf (buf, sizeof (buf), "(IOTYPE==%d)&&EVT_TIME", READ_TRACE);
692       snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
693 		(long long) (NANOSEC / METRIC_HR_PRECISION));
694       specify_metric (buf, buf2);
695       cmd = dbe_strdup (NTXT ("ioreadtime"));
696       break;
697     case IO_WRITE_TIME:
698       packet_type = DATA_IOTRACE;
699       username = dbe_strdup (GTXT ("Write Time"));
700       snprintf (buf, sizeof (buf), NTXT ("(IOTYPE==%d)&&EVT_TIME"),
701 		WRITE_TRACE);
702       snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
703 		(long long) (NANOSEC / METRIC_HR_PRECISION));
704       specify_metric (buf, buf2);
705       cmd = dbe_strdup (NTXT ("iowritetime"));
706       break;
707     case IO_OTHER_TIME:
708       packet_type = DATA_IOTRACE;
709       username = dbe_strdup (GTXT ("Other I/O Time"));
710       snprintf (buf, sizeof (buf),
711 		"(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME",
712 		OPEN_TRACE, CLOSE_TRACE, OTHERIO_TRACE);
713       snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
714 		(long long) (NANOSEC / METRIC_HR_PRECISION));
715       specify_metric (buf, buf2);
716       cmd = dbe_strdup (NTXT ("ioothertime"));
717       break;
718     case IO_ERROR_TIME:
719       packet_type = DATA_IOTRACE;
720       username = dbe_strdup (GTXT ("I/O Error Time"));
721       snprintf (buf, sizeof (buf),
722 		"(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)||(IOTYPE==%d)&&EVT_TIME",
723 		READ_TRACE_ERROR, WRITE_TRACE_ERROR, OPEN_TRACE_ERROR,
724 		CLOSE_TRACE_ERROR, OTHERIO_TRACE_ERROR);
725       snprintf (buf2, sizeof (buf2), NTXT ("(EVT_TIME)/%lld"),
726 		(long long) (NANOSEC / METRIC_HR_PRECISION));
727       specify_metric (buf, buf2);
728       cmd = dbe_strdup (NTXT ("ioerrortime"));
729       break;
730     case RACCESS:
731       packet_type = DATA_RACE;
732       username = dbe_strdup (GTXT ("Race Accesses"));
733       specify_metric (NULL, NTXT ("RCNT"));
734       cmd = dbe_strdup (NTXT ("raccess"));
735       break;
736     case DEADLOCKS:
737       packet_type = DATA_DLCK;
738       username = dbe_strdup (GTXT ("Deadlocks"));
739       specify_metric (NULL, NTXT ("1"));
740       cmd = dbe_strdup (NTXT ("deadlocks"));
741       break;
742     case HWCNTR:
743       packet_type = DATA_HWC;
744       // username, cmd, and aux set by hwc constructor
745       if (valtype == VT_DOUBLE)
746 	{
747 	  if (hw_ctr->timecvt > 0)  // CPU cycles
748 	    specify_metric (NULL, NTXT ("((HWCINT*1000000)/FREQ_MHZ)"));
749 	  else if (hw_ctr->timecvt < 0)
750 	    { // reference clock (frequency is -timecvt MHz)
751 	      snprintf (buf, sizeof (buf), NTXT ("((HWCINT*1000000)/%d)"), -hw_ctr->timecvt);
752 	      specify_metric (NULL, buf);
753 	    }
754 	  else  // shouldn't happen
755 	    specify_metric (NULL, NTXT ("0"));
756 	  // resulting unit: seconds * 1e12
757 	  precision = 1000000LL * 1000000LL; // Seconds * 1e12
758 	}
759       else
760 	{
761 	  specify_metric (NULL, NTXT ("HWCINT"));
762 	  precision = 1;
763 	}
764       break;
765     case OMP_MSTR:
766     case OMP_SNGL:
767     case OMP_ORDD:
768     case OMP_NONE:
769     default:
770       username = dbe_strdup (GTXT ("****"));
771       fprintf (stderr, "BaseMetric::init Undefined basemetric %s\n",
772 	       get_basetype_name ());
773     }
774 }
775 
776 #define CASE_S(x)   case x: s = (char *) #x; break
777 char *
get_basetype_name()778 BaseMetric::get_basetype_name ()
779 {
780   static char buf[128];
781   char *s;
782   switch (type)
783     {
784       CASE_S (CP_LMS_SYSTEM);
785       CASE_S (CP_TOTAL_CPU);
786       CASE_S (CP_TOTAL);
787       CASE_S (OMP_MASTER_THREAD);
788       CASE_S (CP_LMS_USER);
789       CASE_S (CP_LMS_WAIT_CPU);
790       CASE_S (CP_LMS_USER_LOCK);
791       CASE_S (CP_LMS_TFAULT);
792       CASE_S (CP_LMS_DFAULT);
793       CASE_S (CP_LMS_TRAP);
794       CASE_S (CP_LMS_KFAULT);
795       CASE_S (CP_LMS_SLEEP);
796       CASE_S (CP_LMS_STOPPED);
797       CASE_S (OMP_NONE);
798       CASE_S (OMP_OVHD);
799       CASE_S (OMP_WORK);
800       CASE_S (OMP_IBAR);
801       CASE_S (OMP_EBAR);
802       CASE_S (OMP_WAIT);
803       CASE_S (OMP_SERL);
804       CASE_S (OMP_RDUC);
805       CASE_S (OMP_LKWT);
806       CASE_S (OMP_CTWT);
807       CASE_S (OMP_ODWT);
808       CASE_S (OMP_MSTR);
809       CASE_S (OMP_SNGL);
810       CASE_S (OMP_ORDD);
811       CASE_S (CP_KERNEL_CPU);
812       CASE_S (SYNC_WAIT_TIME);
813       CASE_S (IO_READ_TIME);
814       CASE_S (IO_WRITE_TIME);
815       CASE_S (IO_OTHER_TIME);
816       CASE_S (IO_ERROR_TIME);
817       CASE_S (HWCNTR);
818       CASE_S (SYNC_WAIT_COUNT);
819       CASE_S (HEAP_ALLOC_CNT);
820       CASE_S (HEAP_LEAK_CNT);
821       CASE_S (IO_READ_CNT);
822       CASE_S (IO_WRITE_CNT);
823       CASE_S (IO_OTHER_CNT);
824       CASE_S (IO_ERROR_CNT);
825       CASE_S (RACCESS);
826       CASE_S (DEADLOCKS);
827       CASE_S (HEAP_ALLOC_BYTES);
828       CASE_S (HEAP_LEAK_BYTES);
829       CASE_S (IO_READ_BYTES);
830       CASE_S (IO_WRITE_BYTES);
831       CASE_S (SIZES);
832       CASE_S (ADDRESS);
833       CASE_S (ONAME);
834       CASE_S (DERIVED);
835     default:
836       s = NTXT ("???");
837       break;
838     }
839   snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, type);
840   buf[sizeof (buf) - 1] = 0;
841   return buf;
842 }
843 
844 char *
dump()845 BaseMetric::dump ()
846 {
847   int len = 4;
848   char *msg = dbe_sprintf (NTXT ("id=%d %s aux='%s' cmd='%s' user_name='%s' expr_spec='%s'\n"
849 				 "%*c cond_spec='%s' val_spec='%s'"),
850 			   id, get_basetype_name (), STR (aux), STR (cmd),
851 			   STR (username), STR (expr_spec),
852 			   len, ' ', STR (cond_spec), STR (val_spec));
853   return msg;
854 }
855 
856 Histable *
get_comparable_obj(Histable * obj)857 BaseMetric::get_comparable_obj (Histable *obj)
858 {
859   if (obj == NULL || expr == NULL)
860     return obj;
861   if (strncmp (expr_spec, NTXT ("EXPGRID=="), 9) == 0)
862     {
863       int n = atoi (expr_spec + 9);
864       Vector<Histable *> *cmpObjs = obj->get_comparable_objs ();
865       if (cmpObjs && cmpObjs->size () >= n)
866 	return cmpObjs->get (n - 1);
867       return NULL;
868     }
869   return obj;
870 }
871 
Definition(opType _op)872 Definition::Definition (opType _op)
873 {
874   op = _op;
875   bm = NULL;
876   arg1 = NULL;
877   arg2 = NULL;
878   def = NULL;
879   dependencies = NULL;
880   map = NULL;
881   index = 0;
882 }
883 
~Definition()884 Definition::~Definition ()
885 {
886   delete arg1;
887   delete arg2;
888   delete dependencies;
889   delete[] map;
890 }
891 
892 Vector<BaseMetric *> *
get_dependencies()893 Definition::get_dependencies ()
894 {
895   if (dependencies == NULL)
896     {
897       if (arg1 && arg1->bm && arg2 && arg2->bm)
898 	{
899 	  dependencies = new Vector<BaseMetric *>(2);
900 	  arg1->index = dependencies->size ();
901 	  dependencies->append (arg1->bm);
902 	  arg2->index = dependencies->size ();
903 	  dependencies->append (arg2->bm);
904 	  map = new long[2];
905 	}
906     }
907   return dependencies;
908 }
909 
910 long *
get_map()911 Definition::get_map ()
912 {
913   get_dependencies ();
914   return map;
915 }
916 
917 Definition *
add_definition(char * _def)918 Definition::add_definition (char *_def)
919 {
920   // parse the definition
921   char *op_ptr = strchr (_def, '/');
922   if (op_ptr == NULL)
923     {
924       // it's a primitive metric
925       BaseMetric *bm = dbeSession->find_base_reg_metric (_def);
926       if (bm)
927 	{
928 	  Definition *p = new Definition (opPrimitive);
929 	  p->bm = bm;
930 	  return p;
931 	}
932       return NULL; // BaseMetric is not yet specified
933     }
934   Definition *p2 = add_definition (op_ptr + 1);
935   if (p2 == NULL)
936     return NULL;
937   _def = dbe_strdup (_def);
938   op_ptr = strchr (_def, '/');
939   *op_ptr = 0;
940   Definition *p1 = add_definition (_def);
941   if (p1)
942     {
943       *op_ptr = '/';
944       Definition *p = new Definition (opDivide);
945       p->arg1 = p1;
946       p->arg2 = p2;
947       p->def = _def;
948       return p;
949     }
950   free (_def);
951   delete p1;
952   delete p2;
953   return NULL;
954 }
955 
956 double
eval(long * indexes,TValue * values)957 Definition::eval (long *indexes, TValue *values)
958 {
959   switch (op)
960     {
961     case opPrimitive:
962       return values[indexes[index]].to_double ();
963     case opDivide:
964       {
965 	double x2 = arg2->eval (indexes, values);
966 	if (x2 == 0)
967 	  return 0.;
968 	double x1 = arg1->eval (indexes, values);
969 	return x1 / x2;
970       }
971     default:
972       fprintf (stderr, GTXT ("unknown expression\n"));
973       return 0.;
974     }
975 }
976