HPCToolkit
cct.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // cct.c
51 //
52 // Purpose:
53 // A variable degree-tree for storing call stack samples. Each node
54 // may have zero or more children and each node contains a single
55 // instruction pointer value. Call stack samples are represented
56 // implicitly by a path from some node x (where x may or may not be
57 // a leaf node) to the tree root (with the root being the bottom of
58 // the call stack).
59 //
60 // The basic tree functionality is based on NonUniformDegreeTree.h/C
61 // from HPCView/HPCTools.
62 //
63 // Description:
64 // [The set of functions, macros, etc. defined in the file]
65 //
66 //***************************************************************************
67 
68 //************************* System Include Files ****************************
69 
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <stdbool.h>
74 #include <assert.h>
75 
76 //*************************** User Include Files ****************************
77 
78 #include <memory/hpcrun-malloc.h>
79 #include <hpcrun/metrics.h>
80 #include <messages/messages.h>
85 
86 #include "cct.h"
87 #include "cct_addr.h"
88 #include "cct2metrics.h"
89 
90 //***************************** macros **********
91 
92 
93 //***************************** concrete data structure definition **********
94 
95 
96 struct cct_node_t {
97 
98  // ---------------------------------------------------------
99  // a persistent node id is assigned for each node. this id
100  // is used both to reassemble a tree when reading it from
101  // a file as well as to identify call paths. a call path
102  // can simply be represented by the node id of the deepest
103  // node in the path.
104  // ---------------------------------------------------------
105  int32_t persistent_id;
106 
107  uint16_t node_type;
108 
109  cct_addr_t addr; // bundle abstract address components into a data type
110 
111  // ---------------------------------------------------------
112  // tree structure
113  // ---------------------------------------------------------
114 
115  // parent node and the beginning of the child list
118 
119  // left and right pointers for splay tree of siblings
120  struct cct_node_t* left;
121  struct cct_node_t* right;
122 };
123 
124 //
125 // cache of info from most recent splay
126 //
127 static struct {
129  bool found;
131 } splay_cache;
132 
133 //
134 // ******************* Local Routines ********************
135 //
136 static uint32_t
138 {
139  // by default, all persistent ids are even; odd ids signify that we need
140  // to retain them as call path ids associated with a trace.
141  // Furthermore, global ids start at 12: 0,1 are special ids, 2-11 are for
142  // users (and conceivably hpcrun).
143  //
144  static atomic_uint_least32_t global_persistent_id = ATOMIC_VAR_INIT(12);
145  return atomic_fetch_add_explicit(&global_persistent_id, 2, memory_order_relaxed);
146 }
147 
148 static cct_node_t*
150 {
151  size_t sz = sizeof(cct_node_t);
152  cct_node_t *node;
153 
154  // FIXME: when multiple epochs really work, this will always be freeable.
155  // WARN ME (krentel) if/when we really use freeable memory.
156  if (ENABLED(FREEABLE)) {
157  node = hpcrun_malloc_freeable(sz);
158  }
159  else {
160  node = hpcrun_malloc(sz);
161  }
162 
163  memset(node, 0, sz);
164 
165  if (addr != NULL) {
166  node->addr.as_info = addr->as_info; // LUSH
167  node->addr.ip_norm = addr->ip_norm;
168  node->addr.lip = addr->lip; // LUSH
169  }
170 
172 
173  node->parent = parent;
174  node->children = NULL;
175  node->left = NULL;
176  node->right = NULL;
177 
178  // by default it's a regular node.
179  // for other type of nodes, we need to assign it manually
181 
182  return node;
183 }
184 
185 //
186 // ******* SPLAY TREE section ********
187 // [ Thanks to Mark Krentel ]
188 //
189 
190 //
191 // local comparison macros
192 //
193 // NOTE: argument asymmetry due to
194 // type of key value passed in = cct_addr_t*, BUT
195 // type of key in splay tree = cct_addr_t
196 //
197 
198 #define l_lt(a, b) cct_addr_lt(a, &(b))
199 #define l_gt(a, b) cct_addr_gt(a, &(b))
200 
201 static cct_node_t*
203 {
204  GENERAL_SPLAY_TREE(cct_node_t, cct, addr, addr, addr, left, right, l_lt, l_gt);
205  return cct;
206 }
207 
208 #undef l_lt
209 #undef l_gt
210 
211 //
212 // helper for walking functions
213 //
214 
215 //
216 // lrs abbreviation for "left-right-self"
217 //
218 static void
220  cct_op_t op, cct_op_arg_t arg, size_t level,
221  void (*wf)(cct_node_t* n, cct_op_t o, cct_op_arg_t a, size_t l))
222 {
223  if (!cct) return;
224 
225  walk_child_lrs(cct->left, op, arg, level, wf);
226  walk_child_lrs(cct->right, op, arg, level, wf);
227  wf(cct, op, arg, level);
228 }
229 
230 static void
231 walkset_l(cct_node_t* cct, cct_op_t fn, cct_op_arg_t arg, size_t level)
232 {
233  if (! cct) return;
234  walkset_l(cct->left, fn, arg, level);
235  walkset_l(cct->right, fn, arg, level);
236  fn(cct, arg, level);
237 }
238 
239 //
240 // walker op used by counting utility
241 //
242 static void
243 l_count(cct_node_t* n, cct_op_arg_t arg, size_t level)
244 {
245  size_t* cnt = (size_t*) arg;
246  (*cnt)++;
247 }
248 
249 //
250 // Special purpose path walking helper
251 //
252 static void
254 {
255  if (! node) return;
256  walk_path_l(node->parent, op, arg, level+1);
257  op(node, arg, level);
258 }
259 
260 //
261 // Writing helpers
262 //
263 
264 typedef struct {
266  FILE* fs;
270 } write_arg_t;
271 
272 
273 static void
274 lwrite(cct_node_t* node, cct_op_arg_t arg, size_t level)
275 {
276  write_arg_t* my_arg = (write_arg_t*) arg;
279  epoch_flags_t flags = my_arg->flags;
281 
282  tmp->id = hpcrun_cct_persistent_id(node);
283  tmp->id_parent = parent ? hpcrun_cct_persistent_id(parent) : 0;
284 
285  // if no children, chg sign of id when written out
286  if (hpcrun_cct_no_children(node)) {
287  tmp->id = - tmp->id;
288  }
289  if (flags.fields.isLogicalUnwind){
290  tmp->as_info = addr->as_info;
291  lush_lip_init(&tmp->lip);
292  if (addr->lip) {
293  memcpy(&(tmp->lip), &(addr->lip), sizeof(lush_lip_t));
294  }
295  }
296  tmp->lm_id = (addr->ip_norm).lm_id;
297 
298  // double casts to avoid warnings when pointer is < 64 bits
299  tmp->lm_ip = (hpcfmt_vma_t) (uintptr_t) (addr->ip_norm).lm_ip;
300 
301  tmp->node_type = node->node_type;
302 
303  // -------------------------
304  // metrics
305  // -------------------------
306  tmp->num_metrics = my_arg->num_metrics;
307 
308  // -------------------------
309  // write to IO
310  // -------------------------
312 
314  hpcrun_fmt_cct_node_fwrite(tmp, flags, my_arg->fs);
315 }
316 
317 //
318 // ********************* Interface procedures **********************
319 //
320 
321 //
322 // ********** Constructors
323 //
324 
325 cct_node_t*
327 {
328  return cct_node_create(&(ADDR(CCT_ROOT)), NULL);
329 }
330 
331 cct_node_t*
333 {
334  return cct_node_create(&(ADDR(PARTIAL_ROOT)), NULL);
335 }
336 
337 cct_node_t*
339 {
340  ip_normalized_t tmp_ip = hpcrun_normalize_ip(addr, NULL);
341 
342  cct_addr_t tmp = NON_LUSH_ADDR_INI(tmp_ip.lm_id, tmp_ip.lm_ip);
343 
344  return cct_node_create(&tmp, NULL);
345 }
346 
347 cct_node_t*
348 hpcrun_cct_top_new(uint16_t lmid, uintptr_t lmip)
349 {
350  return cct_node_create(&(ADDR2(lmid, lmip)), NULL);
351 }
352 
353 //
354 // ********** Accessor functions
355 //
356 cct_node_t*
358 {
359  return x? x->parent : NULL;
360 }
361 
362 int32_t
364 {
365  return x ? x->persistent_id : -1;
366 }
367 
368 cct_addr_t*
370 {
371  return node ? &(node->addr) : NULL;
372 }
373 
374 
375 //
376 // NOTE: having no children is not exactly the same as being a leaf
377 // A leaf represents a full path. There might be full paths
378 // that are a prefix of other full paths. So, a "leaf" can have children
379 //
380 bool
382 {
383  return node ? ! node->children : false;
384 }
385 
386 bool
388 {
389  return ! node->parent;
390 }
391 
392 
393 //
394 // ********** Mutator functions: modify a given cct
395 //
396 
397 //
398 // Fundamental mutation operation: insert a given addr into the
399 // set of children of a given cct node. Return the cct_node corresponding
400 // to the inserted addr [NB: if the addr is already in the node children, then
401 // the already-present node is returned. Otherwise, a new node is created, linked in,
402 // and returned]
403 //
404 cct_node_t*
406 {
407  if ( ! node)
408  return NULL;
409 
410  cct_node_t* found = splay(node->children, frm);
411  //
412  // !! SPECIAL CASE for cct splay !!
413  // !! The splay tree (represented by the root) is the data structure for the set
414  // !! of children of the parent. Consequently, when the splay operation changes the root,
415  // !! the parent's children pointer must point to the NEW root node
416  // !! NOT the old (pre-splay) root node
417  //
418 
419  node->children = found;
420 
421  if (found && cct_addr_eq(frm, &(found->addr))){
422  return found;
423  }
424  // cct_node_t* new = cct_node_create(frm->as_info, frm->ip_norm, frm->lip, node);
425  cct_node_t* new = cct_node_create(frm, node);
426 
427  node->children = new;
428  if (! found){
429  return new;
430  }
431  if (cct_addr_lt(frm, &(found->addr))){
432  new->left = found->left;
433  new->right = found;
434  found->left = NULL;
435  }
436  else { // addr > addr of found
437  new->left = found;
438  new->right = found->right;
439  found->right = NULL;
440  }
441  return new;
442 }
443 
444 //***************************************************************************
445 // node type interface
446 //***************************************************************************
447 //
448 // 2nd fundamental mutator: mark a node as "terminal". That is,
449 // it is the last node of a path
450 //
451 void
453 {
454  node->node_type |= NODE_TYPE_LEAF;
455 }
456 
457 bool
459 {
460  if (node) {
461  bool leaf_type = (node->node_type & NODE_TYPE_LEAF) == NODE_TYPE_LEAF;
462  return leaf_type || (!node->children);
463  }
464  return false;
465 }
466 
467 void
469 {
471 }
472 
473 bool
475 {
477 }
478 
479 void
481 {
483 }
484 
485 bool
487 {
489 }
490 
491 //
492 // mark the node as the node that has access to the memory
493 // this node type is used by data-centric profiling
494 void
496 {
498 }
499 
500 //
501 // check if the node is a memaccess node
502 // which means the node has access to the memory hierarchy
503 bool
505 {
507 }
508 
509 // mark that the node is supposed to be a root
510 // theoretically, a root has no parent, but to make it easy
511 // we need a fake root and hang it to the invisible parent
512 void
514 {
515  root->node_type |= NODE_TYPE_ROOT;
516 }
517 
518 // check if the node is supposed to be a root
519 bool
521 {
522  return hpcrun_fmt_node_type_root(node->node_type);
523 }
524 
525 //***************************************************************************
526 //
527 // Special purpose mutator:
528 // This operation is somewhat akin to concatenation.
529 // An already constructed cct ('src') is inserted as a
530 // child of the 'target' cct. The addr field of the src
531 // cct is ASSUMED TO BE DIFFERENT FROM ANY ADDR IN target's
532 // child set. [Otherwise something recursive has to happen]
533 //
534 //***************************************************************************
535 //
536 cct_node_t*
538 {
539  src->parent = target;
540 
541  cct_node_t* found = splay(target->children, &(src->addr));
542  target->children = src;
543  if (! found) {
544  return src;
545  }
546 
547  // NOTE: Assume equality cannot happen
548 
549  if (cct_addr_lt(&(src->addr), &(found->addr))){
550  src->left = found->left;
551  src->right = found;
552  found->left = NULL;
553  }
554  else { // addr > addr of found
555  src->left = found;
556  src->right = found->right;
557  found->right = NULL;
558  }
559  return src;
560 }
561 
562 // mark a node for retention as the leaf of a traced call path.
563 // for marked nodes, hpcprof must preserve the association between
564 // the node number recorded in the trace and its call path so that
565 // hpctraceviewer can recover the call path for a trace record.
566 void
568 {
570 }
571 
572 
573 // check if a node was marked for retention as the leaf of a traced
574 // call path.
575 int
577 {
579 }
580 
581 //
582 // Walking functions section:
583 //
584 
585 //
586 // general walking functions: (client may select starting level)
587 // visits every node in the cct, calling op(node, arg, level)
588 // level has property that node at level n ==> children at level n+1
589 // there are 2 different walking strategies:
590 // 1) walk the children, then walk the node
591 // 2) walk the node, then walk the children
592 // there is no implied children ordering
593 //
594 
595 //
596 // visting order: children first, then node
597 //
598 void
600 {
601  if (!cct) return;
602  walk_child_lrs(cct->children, op, arg, level+1,
604  op(cct, arg, level);
605 }
606 
607 //
608 // visting order: node first, then children
609 //
610 void
612 {
613  if (!cct) return;
614  op(cct, arg, level);
615  walk_child_lrs(cct->children, op, arg, level+1,
617 }
618 
619 //
620 // utility walker for cct sets (part of the substructure of a cct)
621 //
622 void
624 {
625  walkset_l(cct, fn, arg, 0);
626 }
627 
628 //
629 // Special routine to walk a path represented by a cct node.
630 // The actual path represented by a node is list reversal of the nodes
631 // linked by the parent link. So walking a path means visiting the
632 // path nodes in list reverse order
633 //
634 
635 void
637 {
638  walk_path_l(node, op, arg, 0);
639 }
640 
641 
642 //
643 // helper for inserting creation contexts
644 //
645 static void
647 {
648  // convenient constant cct_addr_t's
649  static cct_addr_t root = ADDR_I(CCT_ROOT);
650 
652  if (cct_addr_eq(addr, &root)) return;
653 
654  cct_node_t** tree = (cct_node_t**) arg;
655  *tree = hpcrun_cct_insert_addr(*tree, addr);
656 }
657 
658 
659 // Inserts cct path pointed by 'path' into a cct rooted at 'root'
660 
661 void
663 {
665 }
666 
667 
668 //
669 // Writing operation
670 //
671 int
672 hpcrun_cct_fwrite(cct2metrics_t* cct2metrics_map, cct_node_t* cct, FILE* fs, epoch_flags_t flags)
673 {
674  if (!fs) return HPCRUN_ERR;
675 
676  hpcfmt_int8_fwrite((uint64_t) hpcrun_cct_num_nodes(cct), fs);
677  TMSG(DATA_WRITE, "num cct nodes = %d", hpcrun_cct_num_nodes(cct));
678 
679  hpcfmt_uint_t num_metrics = hpcrun_get_num_metrics();
680  TMSG(DATA_WRITE, "num metrics in a cct node = %d", num_metrics);
681 
682  hpcrun_fmt_cct_node_t tmp_node;
683 
684  write_arg_t write_arg = {
685  .num_metrics = num_metrics,
686  .fs = fs,
687  .flags = flags,
688  .tmp_node = &tmp_node,
689 
690  // multithreaded code: add personalized cct2metrics_map for multithreading programs
691  // this is to allow a thread to write the profile data of another thread.
692  .cct2metrics_map = cct2metrics_map
693  };
694 
695  hpcrun_metricVal_t metrics[num_metrics];
696  tmp_node.metrics = &(metrics[0]);
697 
698  hpcrun_cct_walk_node_1st(cct, lwrite, &write_arg);
699 
700  return HPCRUN_OK;
701 }
702 
703 //
704 // Utilities
705 //
706 size_t
708 {
709  size_t n = 0;
711  return n;
712 }
713 
714 //
715 // look up addr in the set of cct's children
716 // return the found node or NULL
717 //
718 cct_node_t*
720 {
721  if ( ! cct)
722  return NULL;
723 
724  cct_node_t* found = splay(cct->children, addr);
725  //
726  // !! SPECIAL CASE for cct splay !!
727  // !! The splay tree (represented by the root) is the data structure for the set
728  // !! of children of the parent. Consequently, when the splay operation changes the root,
729  // !! the parent's children pointer must point to the NEW root node
730  // !! NOT the old (pre-splay) root node
731  //
732 
733  cct->children = found;
734 
735  if (found && cct_addr_eq(addr, &(found->addr))){
736  return found;
737  }
738  return NULL;
739 }
740 
741 //
742 // Merging operation: Given 2 ccts : CCT_A, CCT_B,
743 // merge means add all paths in CCT_B that are NOT in CCT_A
744 // to CCT_A. For paths that are common, perform the merge operation on
745 // each common node, using auxiliary arg merge_arg
746 //
747 // NOTE: this merge operation presumes
748 // cct_addr_data(CCT_A) == cct_addr_data(CCT_B)
749 //
750 
751 //
752 // Helpers & datatypes for cct_merge operation
753 //
754 static void merge_or_join(cct_node_t* n, cct_op_arg_t a, size_t l);
756 static void cct_disjoint_union_cached(cct_node_t* target, cct_node_t* src);
757 
758 typedef struct {
762 } mjarg_t;
763 
764 //
765 // The merging operation main code
766 //
767 
768 void
770  merge_op_t merge, merge_op_arg_t arg)
771 {
772  if (hpcrun_cct_is_leaf (cct_a) && hpcrun_cct_is_leaf(cct_b)) {
773  merge(cct_a, cct_b, arg);
774  }
775  if (! cct_b->children)
776  cct_b->children = cct_a->children;
777  else {
778  mjarg_t local = (mjarg_t) {.targ = cct_a, .fn = merge, .arg = arg};
779  hpcrun_cct_walkset(cct_b->children, merge_or_join, (cct_op_arg_t) &local);
780  }
781 }
782 
783 //
784 // merge helper functions (forward declared above)
785 //
786 static void
788 {
789  mjarg_t* the_arg = (mjarg_t*) a;
790  cct_node_t* targ = the_arg->targ;
792  hpcrun_cct_merge(splay_cache.node, n, the_arg->fn, the_arg->arg);
793  else
794  cct_disjoint_union_cached(targ, n);
795 }
796 
797 static cct_addr_t dc = ADDR2_I(-1, -1);
798 
799 static void
801 {
802  splay_cache.node = NULL;
803  splay_cache.found = false;
804  splay_cache.addr = &dc;
805 
806  if ( ! cct) return;
807 
808  cct_node_t* found = splay(cct->children, addr);
809  //
810  // !! SPECIAL CASE for cct splay !!
811  // !! The splay tree (represented by the root) is the data structure for the set
812  // !! of children of the parent. Consequently, when the splay operation changes the root,
813  // !! the parent's children pointer must point to the NEW root node
814  // !! NOT the old (pre-splay) root node
815  //
816 
817  cct->children = found;
818  if (found) {
819  splay_cache.node = found;
820  splay_cache.addr = &(found->addr);
821  splay_cache.found = found && cct_addr_eq(addr, &(found->addr));
822  }
823 }
824 
825 //
826 // Differs from the main accessor by setting the splay cache as a side
827 // effect
828 //
829 static cct_node_t*
831 {
833  return splay_cache.found ? splay_cache.node : NULL;
834 }
835 
836 //
837 // This procedure assumes that cct_child_find_cache has been
838 // called, and that no other intervening splay operations have been called
839 //
840 static void
842 {
843  src->parent = target;
844  if (splay_cache.node) {
845  if (cct_addr_lt(hpcrun_cct_addr(src), splay_cache.addr)) {
846  src->left = splay_cache.node->left;
847  src->right = splay_cache.node;
848  splay_cache.node->left = NULL;
849  }
850  else { // src addr > addr(splay(target))
851  src->left = splay_cache.node;
852  src->right = splay_cache.node->right;
853  splay_cache.node->right = NULL;
854  }
855  }
856  target->children = src;
857 }
858 
859 
860 cct_node_t*
862 {
863  ip_normalized_t tmp_ip = hpcrun_normalize_ip(addr, NULL);
864  // plus 1 make sure lm_ip points to the correct callsite
865  cct_addr_t tmp = ADDR2(tmp_ip.lm_id, tmp_ip.lm_ip+1);
866  return hpcrun_cct_insert_addr(root, &tmp);
867 }
868 
869 
870 cct_node_t*
872 {
873  if(!path || ! path->parent) return root;
874  root = hpcrun_cct_insert_path_return_leaf(path->parent, root);
875 
876  return hpcrun_cct_insert_addr(root, &(path->addr));
877 }
878 
879 
880 
881 cct_node_t *
883 {
884  cct_node_t *current = node;
885  while(current && hpcrun_cct_parent(current)) {
886  current = hpcrun_cct_parent(current);
887  }
888  return current;
889 }
890 
cct_node_t * hpcrun_cct_top_new(uint16_t lmid, uintptr_t lmip)
Definition: cct.c:348
cct_node_t * targ
Definition: cct.c:759
ip_normalized_t hpcrun_normalize_ip(void *unnormalized_ip, load_module_t *lm)
Definition: ip-normalized.c:70
#define ADDR_I(L)
Definition: cct.h:101
cct_node_t * hpcrun_cct_new_special(void *addr)
Definition: cct.c:338
struct cct_node_t * parent
Definition: cct.c:116
void hpcrun_cct_terminate_path(cct_node_t *node)
Definition: cct.c:452
#define ADDR2_I(id, ip)
Definition: cct.h:103
static char * tmp
Definition: tokenize.c:63
hpcfmt_vma_t lm_ip
Definition: hpcrun-fmt.h:554
#define GENERAL_SPLAY_TREE(type, root, key, lt_field, gt_field, left, right, lt, gt)
Definition: splay-macros.h:120
static void walkset_l(cct_node_t *cct, cct_op_t fn, cct_op_arg_t arg, size_t level)
Definition: cct.c:231
void hpcrun_cct_merge(cct_node_t *cct_a, cct_node_t *cct_b, merge_op_t merge, merge_op_arg_t arg)
Definition: cct.c:769
hpcfmt_uint_t num_metrics
Definition: cct.c:265
int32_t persistent_id
Definition: cct.c:105
#define HPCRUN_FMT_RetainIdFlag
Definition: hpcrun-fmt.h:499
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:366
static struct @10 splay_cache
#define ATOMIC_VAR_INIT(value)
Definition: stdatomic.h:132
size_t hpcrun_cct_num_nodes(cct_node_t *cct)
Definition: cct.c:707
void hpcrun_cct_insert_path(cct_node_t **root, cct_node_t *path)
Definition: cct.c:662
static cct_node_t * splay(cct_node_t *cct, cct_addr_t *addr)
Definition: cct.c:202
static papi_cuda_data_t local
Definition: papi-c-cupti.c:89
uint64_t hpcfmt_vma_t
Definition: hpcfmt.h:102
#define l_gt(a, b)
Definition: cct.c:199
cct_node_t * node
Definition: cct.c:128
bool hpcrun_cct_is_node_allocation(cct_node_t *node)
Definition: cct.c:474
bool hpcrun_cct_is_root(cct_node_t *node)
Definition: cct.c:387
void hpcrun_walk_path(cct_node_t *node, cct_op_t op, cct_op_arg_t arg)
Definition: cct.c:636
lush_lip_t * lip
Definition: cct_addr.h:69
hpcrun_fmt_cct_node_t * tmp_node
Definition: cct.c:268
cct_node_t * hpcrun_cct_get_root(cct_node_t *node)
Definition: cct.c:882
int hpcrun_get_num_metrics()
Definition: metrics.c:209
static cct_node_t * cct_child_find_cache(cct_node_t *cct, cct_addr_t *addr)
Definition: cct.c:830
#define ADDR(L)
Definition: cct.h:102
uintptr_t lm_ip
Definition: ip-normalized.h:78
uint64_t hpcfmt_uint_t
Definition: hpcfmt.h:103
void * cct_op_arg_t
Definition: cct.h:186
void hpcrun_cct_walk_node_1st_w_level(cct_node_t *cct, cct_op_t op, cct_op_arg_t arg, size_t level)
Definition: cct.c:611
static void lwrite(cct_node_t *node, cct_op_arg_t arg, size_t level)
Definition: cct.c:274
merge_op_t fn
Definition: cct.c:760
Definition: cct.c:758
cct_node_t * hpcrun_cct_parent(cct_node_t *x)
Definition: cct.c:357
struct cct_node_t * children
Definition: cct.c:117
static bool hpcrun_fmt_node_type_root(uint16_t type)
Definition: hpcrun-fmt.h:587
hpcfmt_uint_t num_metrics
Definition: hpcrun-fmt.h:559
static void l_count(cct_node_t *n, cct_op_arg_t arg, size_t level)
Definition: cct.c:243
#define HPCRUN_ERR
static bool cct_addr_eq(const cct_addr_t *a, const cct_addr_t *b)
Definition: cct_addr.h:78
static cct_addr_t dc
Definition: cct.c:797
#define ADDR2(id, ip)
Definition: cct.h:104
cct_node_t * hpcrun_cct_insert_addr(cct_node_t *node, cct_addr_t *frm)
Definition: cct.c:405
struct cct_node_t * right
Definition: cct.c:121
cct_addr_t addr
Definition: cct.c:109
struct cct_node_t cct_node_t
Definition: cct.h:109
#define NODE_TYPE_ROOT
Definition: hpcrun-fmt.h:520
cct_node_t * hpcrun_insert_special_node(cct_node_t *root, void *addr)
Definition: cct.c:861
static void walk_path_l(cct_node_t *node, cct_op_t op, cct_op_arg_t arg, size_t level)
Definition: cct.c:253
static void cct_disjoint_union_cached(cct_node_t *target, cct_node_t *src)
Definition: cct.c:841
bool hpcrun_cct_is_leaf(cct_node_t *node)
Definition: cct.c:458
lush_assoc_info_t as_info
Definition: hpcrun-fmt.h:545
void hpcrun_cct_retain(cct_node_t *x)
Definition: cct.c:567
bool hpcrun_cct_is_node_root(cct_node_t *node)
Definition: cct.c:520
#define NODE_TYPE_GLOBAL_VARIABLE
Definition: hpcrun-fmt.h:518
static void walk_child_lrs(cct_node_t *cct, cct_op_t op, cct_op_arg_t arg, size_t level, void(*wf)(cct_node_t *n, cct_op_t o, cct_op_arg_t a, size_t l))
Definition: cct.c:219
int hpcrun_cct_fwrite(cct2metrics_t *cct2metrics_map, cct_node_t *cct, FILE *fs, epoch_flags_t flags)
Definition: cct.c:672
cct_node_t * hpcrun_cct_new(void)
Definition: cct.c:326
bool hpcrun_cct_is_node_memaccess(cct_node_t *node)
Definition: cct.c:504
void * merge_op_arg_t
Definition: cct.h:274
static uint32_t new_persistent_id()
Definition: cct.c:137
static int hpcfmt_int8_fwrite(uint64_t val, FILE *outfs)
Definition: hpcfmt.h:227
static void lush_lip_init(lush_lip_t *x)
Definition: lush-support.h:319
#define CCT_ROOT
Definition: cct.h:99
ip_normalized_t ip_norm
Definition: cct_addr.h:66
static void help_cct_child_find_set_cache(cct_node_t *cct, cct_addr_t *addr)
Definition: cct.c:800
epoch_flags_bitfield fields
Definition: hpcrun-fmt.h:181
#define NON_LUSH_ADDR_INI(id, ip)
Definition: cct_addr.h:106
void * hpcrun_malloc(size_t size)
Definition: mem.c:275
metric_set_t * hpcrun_get_metric_set_specific(cct2metrics_t **map, cct_node_id_t cct_id)
Definition: cct2metrics.c:135
bool hpcrun_cct_no_children(cct_node_t *node)
Definition: cct.c:381
#define NODE_TYPE_MEMACCESS
Definition: hpcrun-fmt.h:519
lush_assoc_info_t as_info
Definition: cct_addr.h:60
void hpcrun_cct_set_node_variable(cct_node_t *node)
Definition: cct.c:480
int32_t hpcrun_cct_persistent_id(cct_node_t *x)
Definition: cct.c:363
cct_node_t * hpcrun_cct_new_partial(void)
Definition: cct.c:332
void * hpcrun_malloc_freeable(size_t size)
Definition: mem.c:351
bool found
Definition: cct.c:129
int hpcrun_cct_retained(cct_node_t *x)
Definition: cct.c:576
#define TMSG(f,...)
Definition: messages.h:93
static cct_node_t * cct_node_create(cct_addr_t *addr, cct_node_t *parent)
Definition: cct.c:149
void(* merge_op_t)(cct_node_t *a, cct_node_t *b, merge_op_arg_t arg)
Definition: cct.h:275
struct cct_node_t * left
Definition: cct.c:120
static void l_insert_path(cct_node_t *node, cct_op_arg_t arg, size_t level)
Definition: cct.c:646
cct2metrics_t * cct2metrics_map
Definition: cct.c:269
int hpcrun_fmt_cct_node_fwrite(hpcrun_fmt_cct_node_t *x, epoch_flags_t flags, FILE *fs)
Definition: hpcrun-fmt.c:660
void hpcrun_cct_set_node_root(cct_node_t *root)
Definition: cct.c:513
merge_op_arg_t arg
Definition: cct.c:761
#define NULL
Definition: ElfHelper.cpp:85
int metrics[MAX_EVENTS][MAX_METRICS]
Definition: generic.c:147
#define HPCRUN_OK
cct_node_t * hpcrun_cct_insert_path_return_leaf(cct_node_t *path, cct_node_t *root)
Definition: cct.c:871
#define PARTIAL_ROOT
Definition: cct.h:100
#define NODE_TYPE_REGULAR
Definition: hpcrun-fmt.h:515
static bool cct_addr_lt(const cct_addr_t *a, const cct_addr_t *b)
Definition: cct_addr.h:86
#define NODE_TYPE_LEAF
Definition: hpcrun-fmt.h:516
Definition: cct.c:96
static void merge_or_join(cct_node_t *n, cct_op_arg_t a, size_t l)
Definition: cct.c:787
FILE * fs
Definition: cct.c:266
void hpcrun_cct_set_node_memaccess(cct_node_t *node)
Definition: cct.c:495
#define l_lt(a, b)
Definition: cct.c:198
uint16_t node_type
Definition: cct.c:107
<!-- ********************************************************************--> n<!-- HPCToolkit Experiment DTD --> n<!-- Version 2.1 --> n<!-- ********************************************************************--> n<!ELEMENT HPCToolkitExperiment(Header,(SecCallPathProfile|SecFlatProfile) *)> n<!ATTLIST HPCToolkitExperiment\n version CDATA #REQUIRED > n n<!-- ******************************************************************--> n n<!-- Info/NV:flexible name-value pairs:(n) ame;(t) ype;(v) alue --> n<!ELEMENT Info(NV *)> n<!ATTLIST Info\n n CDATA #IMPLIED > n<!ELEMENT NV EMPTY > n<!ATTLIST NV\n n CDATA #REQUIRED\n t CDATA #IMPLIED\n v CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Header --> n<!-- ******************************************************************--> n<!ELEMENT Header(Info *)> n<!ATTLIST Header\n n CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Section Header --> n<!-- ******************************************************************--> n<!ELEMENT SecHeader(MetricTable?, MetricDBTable?, TraceDBTable?, LoadModuleTable?, FileTable?, ProcedureTable?, Info *)> n n<!-- MetricTable:--> n<!ELEMENT MetricTable(Metric) * > n n<!-- Metric:(i) d;(n) ame --> n<!--(v) alue-type:transient type of values --> n<!--(t) ype:persistent type of metric --> n<!-- fmt:format;show;--> n<!ELEMENT Metric(MetricFormula *, Info?)> n<!ATTLIST Metric\n i CDATA #REQUIRED\n n CDATA #REQUIRED\n es CDATA #IMPLIED\n em CDATA #IMPLIED\n ep CDATA #IMPLIED\n v(raw|final|derived-incr|derived) \"raw\\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ fmt CDATA #IMPLIED\ show (1|0) \1\\ show-percent (1|0) \1> n n<!-- MetricFormula represents derived metrics: (t)ype; (frm): formula --> n<!ELEMENT MetricFormula (Info?)> n<!ATTLIST MetricFormula\ t (combine|finalize) \finalize\\ i CDATA #IMPLIED\ frm CDATA #REQUIRED> n n<!-- Metric data, used in sections: (n)ame [from Metric]; (v)alue --> n<!ELEMENT M EMPTY> n<!ATTLIST M\ n CDATA #REQUIRED\ v CDATA #REQUIRED> n n<!-- MetricDBTable: --> n<!ELEMENT MetricDBTable (MetricDB)*> n n<!-- MetricDB: (i)d; (n)ame --> n<!-- (t)ype: persistent type of metric --> n<!-- db-glob: file glob describing files in metric db --> n<!-- db-id: id within metric db --> n<!-- db-num-metrics: number of metrics in db --> n<!-- db-header-sz: size (in bytes) of a db file header --> n<!ELEMENT MetricDB EMPTY> n<!ATTLIST MetricDB\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ db-glob CDATA #IMPLIED\ db-id CDATA #IMPLIED\ db-num-metrics CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- TraceDBTable: --> n<!ELEMENT TraceDBTable (TraceDB)> n n<!-- TraceDB: (i)d --> n<!-- db-min-time: min beginning time stamp (global) --> n<!-- db-max-time: max ending time stamp (global) --> n<!ELEMENT TraceDB EMPTY> n<!ATTLIST TraceDB\ i CDATA #REQUIRED\ db-glob CDATA #IMPLIED\ db-min-time CDATA #IMPLIED\ db-max-time CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- LoadModuleTable assigns a short name to a load module --> n<!ELEMENT LoadModuleTable (LoadModule)*> n n<!ELEMENT LoadModule (Info?)> n<!ATTLIST LoadModule\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- FileTable assigns a short name to a file --> n<!ELEMENT FileTable (File)*> n n<!ELEMENT File (Info?)> n<!ATTLIST File\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- ProcedureTable assigns a short name to a procedure --> n<!ELEMENT ProcedureTable (Procedure)*> n n<!-- Info/NV: flexible name-value pairs: (n)ame; (t)ype; (v)alue --> n<!-- f: family of the procedure (fake, root, ...)--> n<!ELEMENT Procedure (Info?)> n<!ATTLIST Procedure\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ f CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Call path profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecCallPathProfile (SecHeader, SecCallPathProfileData)> n<!ATTLIST SecCallPathProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecCallPathProfileData (PF|M)*> n<!-- Procedure frame --> n<!-- (i)d: unique identifier for cross referencing --> n<!-- (s)tatic scope id --> n<!-- (n)ame: a string or an id in ProcedureTable --> n<!-- (lm) load module: a string or an id in LoadModuleTable --> n<!-- (f)ile name: a string or an id in LoadModuleTable --> n<!-- (l)ine range: \beg-end\ (inclusive range) --> n<!-- (a)lien: whether frame is alien to enclosing P --> n<!-- (str)uct: hpcstruct node id --> n<!-- (t)ype: hpcrun node type: memory access, variable declaration, ... --> n<!-- (v)ma-range-set: \{[beg-end), [beg-end)...}\ --> n<!ELEMENT PF (PF|Pr|L|C|S|M)*> n<!ATTLIST PF\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Procedure (static): GOAL: replace with 'P' --> n<!ELEMENT Pr (Pr|L|C|S|M)*> n<!ATTLIST Pr\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ a (1|0) \0\\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Callsite (a special StatementRange) --> n<!ELEMENT C (PF|M)*> n<!ATTLIST C\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Flat profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecFlatProfile (SecHeader, SecFlatProfileData)> n<!ATTLIST SecFlatProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecFlatProfileData (LM|M)*> n<!-- Load module: (i)d; (n)ame; (v)ma-range-set --> n<!ELEMENT LM (F|P|M)*> n<!ATTLIST LM\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ v CDATA #IMPLIED> n<!-- File --> n<!ELEMENT F (P|L|S|M)*> n<!ATTLIST F\ i CDATA #IMPLIED\ n CDATA #REQUIRED> n<!-- Procedure (Note 1) --> n<!ELEMENT P (P|A|L|S|C|M)*> n<!ATTLIST P\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Alien (Note 1) --> n<!ELEMENT A (A|L|S|C|M)*> n<!ATTLIST A\ i CDATA #IMPLIED\ f CDATA #IMPLIED\ n CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Loop (Note 1,2) --> n<!ELEMENT L (A|Pr|L|S|C|M)*> n<!ATTLIST L\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ f CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Statement (Note 2) --> n<!-- (it): trace record identifier --> n<!ELEMENT S (S|M)*> n<!ATTLIST S\ i CDATA #IMPLIED\ it CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Note 1: Contained Cs may not contain PFs --> n<!-- Note 2: The 's' attribute is not used for flat profiles --> n
void hpcrun_cct_set_node_allocation(cct_node_t *node)
Definition: cct.c:468
void hpcrun_cct_walkset(cct_node_t *cct, cct_op_t fn, cct_op_arg_t arg)
Definition: cct.c:623
#define NODE_TYPE_ALLOCATION
Definition: hpcrun-fmt.h:517
epoch_flags_t flags
Definition: cct.c:267
cct_node_t * hpcrun_cct_find_addr(cct_node_t *cct, cct_addr_t *addr)
Definition: cct.c:719
bitree_uwi_t * tree
hpcrun_metricVal_t * metrics
Definition: hpcrun-fmt.h:560
void(* cct_op_t)(cct_node_t *cct, cct_op_arg_t arg, size_t level)
Definition: cct.h:187
void hpcrun_cct_walk_child_1st_w_level(cct_node_t *cct, cct_op_t op, cct_op_arg_t arg, size_t level)
Definition: cct.c:599
cct_node_t * hpcrun_cct_insert_node(cct_node_t *target, cct_node_t *src)
Definition: cct.c:537
#define ENABLED(f)
Definition: debug-flag.h:76
bool hpcrun_cct_is_node_variable(cct_node_t *node)
Definition: cct.c:486
static void hpcrun_cct_walk_node_1st(cct_node_t *cct, cct_op_t op, cct_op_arg_t arg)
Definition: cct.h:226
cct_addr_t * hpcrun_cct_addr(cct_node_t *node)
Definition: cct.c:369
void hpcrun_metric_set_dense_copy(cct_metric_data_t *dest, metric_set_t *set, int num_metrics)
Definition: metrics.c:560