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
30int BaseMetric::last_id = 0;
31
32void
33BaseMetric::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
60BaseMetric::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)
167BaseMetric::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
176BaseMetric::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
182void
183BaseMetric::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
203BaseMetric::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
222BaseMetric::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
276BaseMetric::~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
291bool
292BaseMetric::is_internal ()
293{
294  return (get_value_styles () & VAL_INTERNAL) != 0;
295}
296
297int
298BaseMetric::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
316void
317BaseMetric::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
333void
334BaseMetric::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
355void
356BaseMetric::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
377void
378BaseMetric::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
400void
401BaseMetric::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
408void
409BaseMetric::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
416void
417BaseMetric::specify_prof_metric (char *_cond_spec)
418{
419  packet_type = DATA_CLOCK;
420  specify_metric (_cond_spec, NTXT ("NTICK_USEC")); // microseconds
421}
422
423void
424BaseMetric::specify_metric (char *_cond_spec, char *_val_spec)
425{
426  set_cond_spec (_cond_spec);
427  set_val_spec (_val_spec);
428}
429
430void
431BaseMetric::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
777char *
778BaseMetric::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
844char *
845BaseMetric::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
856Histable *
857BaseMetric::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
872Definition::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
884Definition::~Definition ()
885{
886  delete arg1;
887  delete arg2;
888  delete dependencies;
889  delete[] map;
890}
891
892Vector<BaseMetric *> *
893Definition::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
910long *
911Definition::get_map ()
912{
913  get_dependencies ();
914  return map;
915}
916
917Definition *
918Definition::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
956double
957Definition::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