HPCToolkit
lush-backtrace.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 // $HeadURL$
51 //
52 // Purpose:
53 // LUSH: Logical Unwind Support for HPCToolkit
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 // Author:
59 // Nathan Tallent, Rice University.
60 //
61 //***************************************************************************
62 
63 //************************* System Include Files ****************************
64 
65 #include <stdlib.h>
66 #include <string.h>
67 
68 //************************ libmonitor Include Files *************************
69 
70 #include <monitor.h>
71 
72 //*************************** User Include Files ****************************
73 
74 #include <include/uint.h>
75 #include <include/min-max.h>
76 
77 #include "lush.h"
78 #include "lush-backtrace.h"
80 
81 #include <epoch.h>
82 #include <sample_event.h> // hpcrun_drop_sample()
83 #include <unwind/common/backtrace.h> // dump_backtrace()
84 
85 
86 //*************************** Forward Declarations **************************
87 
88 #define MYDBG 0
89 
90 static frame_t*
92  uint pchord_len, uint lchord_len);
93 
94 
95 //***************************************************************************
96 // LUSH Agents
97 //***************************************************************************
98 
100 bool is_lush_agent = false;
101 
102 
103 //***************************************************************************
104 // LUSH backtrace
105 //***************************************************************************
106 
107 cct_node_t*
108 lush_backtrace2cct(cct_bundle_t* cct, ucontext_t* context,
109  int metricId,
110  hpcrun_metricVal_t metricIncr,
111  int skipInner, int isSync)
112 {
113  // ---------------------------------------------------------
114  // Record backtrace if:
115  // 1) a lush agent indicates we should
116  // 2) a non-lush-relevant metric
117  // 3) a synchronous unwind (may have a lush relevant metric)
118  // ---------------------------------------------------------
119  bool doMetric = false;
120  uint64_t incrMetric = metricIncr.i;
121 
122  bool doMetricIdleness = false;
123  double incrMetricIdleness = 0.0;
124  // lush_agentid_t aidMetricIdleness; // = lush_agentid_NULL; // list of agents
125 
126  if (metricId == lush_agents->metric_time) {
127  lush_agentid_t aid = 1; // TODO: multiple agents
128  if (lush_agents->LUSHI_do_metric[aid](metricIncr.i,
129  &doMetric, &doMetricIdleness,
130  &incrMetric, &incrMetricIdleness)) {
131  //aidMetricIdleness = aid; // case 1
132  }
133  }
134 
135  if (isSync || metricId != lush_agents->metric_time) {
136  doMetric = true; // case 2 and 3
137  }
138 
139  if (!doMetric) {
140  return NULL;
141  }
142 
143 
144  // ---------------------------------------------------------
145  // Perform the backtrace
146  // ---------------------------------------------------------
147 
148  lush_cursor_t cursor;
149  lush_init_unw(&cursor, lush_agents, context);
150 
151  // FIXME: unwind/common/backtrace.c
153  td->btbuf_cur = td->btbuf_beg; // innermost
154 
155  td->btbuf_sav = td->btbuf_end;
156 
157  // ---------------------------------------------------------
158  // Step through bichords
159  // ---------------------------------------------------------
160  uint unw_len = 0;
162 
163  while ( (ty = lush_step_bichord(&cursor)) != LUSH_STEP_END_PROJ
164  && ty != LUSH_STEP_ERROR ) {
165  lush_agentid_t aid = lush_cursor_get_aid(&cursor);
166  lush_assoc_t as = lush_cursor_get_assoc(&cursor);
167 
168  TMSG(LUNW, "Chord: aid:%d assoc:%d", aid, as);
169 
170  // FIXME: short circuit unwind if we hit the 'active return'
171 
173  frame_t* chord_beg = td->btbuf_cur; // innermost note
174  uint pchord_len = 0, lchord_len = 0;
175 
176  // ---------------------------------------------------------
177  // Step through p-notes of p-chord
178  // ---------------------------------------------------------
179  while (lush_step_pnote(&cursor) != LUSH_STEP_END_CHORD) {
181 
182  //unw_word_t ip = lush_cursor_get_ip(&cursor);
183  ip_normalized_t ip_norm = lush_cursor_get_ip_norm(&cursor);
184  TMSG(LUNW, "IP: lm-id = %d and lm-ip = %p", ip_norm.lm_id,
185  ip_norm.lm_ip);
186  td->btbuf_cur->ip_norm = ip_norm;
187 
188  pchord_len++;
189  td->btbuf_cur++;
190  }
191 
192  td->btbuf_cur = chord_beg;
193 
194  // ---------------------------------------------------------
195  // Step through l-notes of l-chord
196  // ---------------------------------------------------------
197  lush_lip_t* lip_persistent = NULL;
198  while (lush_step_lnote(&cursor) != LUSH_STEP_END_CHORD) {
200 
201  lush_lip_t* lip = lush_cursor_get_lip(&cursor); // ephemeral
202  TMSG(LUNW, "LIP: %p", *((void**)lip));
203 
204  if (lush_assoc_is_a_to_1(as)) {
205  if (!lip_persistent) {
206  lip_persistent = lush_lip_clone(lip);
207  }
208  // else: lip_persistent is already set
209  }
210  else {
211  // INVARIANT: as must be 1-to-M
212  lip_persistent = lush_lip_clone(lip);
213  }
214  td->btbuf_cur->lip = lip_persistent;
215 
216  lchord_len++;
217  td->btbuf_cur++;
218  }
219 
220  // ---------------------------------------------------------
221  // canonicalize frames to form a chord
222  // ---------------------------------------------------------
223  frame_t* chord_end;
224  chord_end = canonicalize_chord(chord_beg, as, pchord_len, lchord_len);
225  unw_len++;
226 
227  td->btbuf_cur = chord_end;
228  }
229 
230  if (ty == LUSH_STEP_ERROR) {
231  hpcrun_drop_sample(); // NULL
232  }
233 
234  // ---------------------------------------------------------
235  // insert backtrace into calling context tree (if sensible)
236  // ---------------------------------------------------------
237  if (MYDBG) {
238  hpcrun_bt_dump(td->btbuf_cur, "LUSH");
239  }
240 
241  frame_t* bt_beg = td->btbuf_beg; // innermost, inclusive
242  frame_t* bt_end = td->btbuf_cur - 1; // outermost, inclusive
243  cct_node_t* cct_cursor = cct->tree_root;
244 
245  if (skipInner) {
246  bt_beg = hpcrun_skip_chords(bt_end, bt_beg, skipInner);
247  }
248 
249  cct_node_t* node = NULL;
250  node = hpcrun_cct_insert_backtrace_w_metric(cct, cct_cursor, metricId,
251  bt_end, bt_beg,
252  metricIncr, NULL);
253 
254  if (doMetricIdleness) {
255  // lush_agentid_t aid = aidMetricIdleness;
256  int mid = lush_agents->metric_idleness;
257  cct_metric_data_increment(mid, node,
258  (cct_metric_data_t){.r = incrMetricIdleness});
259  }
260 
261  // FIXME: register active return
262 
263  return node;
264 }
265 
266 
267 // returns the end of the chord (exclusive)
268 static frame_t*
270  uint pchord_len, uint lchord_len)
271 {
272  // Set assoc and fill empty p-notes/l-notes
273 
274  // INVARIANT: chord_len >= 1
275  // [chord_beg = innermost ... outermost, chord_end)
276 
277  uint chord_len = MAX(pchord_len, lchord_len);
278  frame_t* chord_end = chord_beg + chord_len; // N.B.: exclusive
279  frame_t* pchord_end = chord_beg + pchord_len;
280  frame_t* lchord_end = chord_beg + lchord_len;
281 
283  lush_lip_t* lip = NULL;
284 
285  if (as == LUSH_ASSOC_1_to_M) {
286  ip_norm = chord_beg->ip_norm;
287  }
288  else if (as == LUSH_ASSOC_M_to_1) {
289  lip = chord_beg->lip;
290  }
291  // else: default is fine for a-to-0 and 1-to-1
292 
293  uint path_len = chord_len;
294  for (frame_t* x = chord_beg; x < chord_end; ++x, --path_len) {
295  lush_assoc_info__set_assoc(x->as_info, as);
296  lush_assoc_info__set_path_len(x->as_info, path_len);
297 
298  if (x >= pchord_end) {
299  // INVARIANT: as must be 1-to-M
300  x->ip_norm = ip_norm;
301  }
302  if (x >= lchord_end) {
303  // INVARIANT: as is one of: M-to-1, a-to-0
304  x->lip = lip;
305  }
306  }
307 
308  return chord_end;
309 }
310 
311 
312 //***************************************************************************
#define MAX(a, b)
Definition: min-max.h:77
lush_step_t lush_step_bichord(lush_cursor_t *cursor)
Definition: lush.c:244
#define ip_normalized_NULL
Definition: ip-normalized.h:83
bool is_lush_agent
static lush_lip_t * lush_cursor_get_lip(lush_cursor_t *cursor)
void hpcrun_ensure_btbuf_avail(void)
Definition: thread_data.c:426
ip_normalized_t ip_norm
Definition: frame.h:61
#define MYDBG
frame_t * btbuf_cur
Definition: thread_data.h:184
#define lush_assoc_info__set_path_len(x, new_len)
Definition: lush-support.h:276
cct_node_t * node
Definition: cct.c:128
cct_node_t * tree_root
Definition: cct_bundle.h:65
static void cct_metric_data_increment(int metric_id, cct_node_t *x, cct_metric_data_t incr)
Definition: cct2metrics.h:86
uintptr_t lm_ip
Definition: ip-normalized.h:78
void lush_init_unw(lush_cursor_t *cursor, lush_agent_pool_t *apool, ucontext_t *context)
Definition: lush.c:231
#define doMetric(metricIdExpr, metricIncr, type)
Definition: ga-overrides.c:296
#define lush_assoc_info__set_assoc(x, new_as)
Definition: lush-support.h:264
cct_node_t * lush_backtrace2cct(cct_bundle_t *cct, ucontext_t *context, int metricId, hpcrun_metricVal_t metricIncr, int skipInner, int isSync)
static ip_normalized_t lush_cursor_get_ip_norm(lush_cursor_t *cursor)
unsigned int uint
Definition: uint.h:124
frame_t * btbuf_sav
Definition: thread_data.h:190
int lush_agentid_t
Definition: lush-support.h:99
lush_step_t lush_step_lnote(lush_cursor_t *cursor)
Definition: lush.c:335
lush_lip_t * lip
Definition: frame.h:64
static frame_t * canonicalize_chord(frame_t *chord_beg, lush_assoc_t as, uint pchord_len, uint lchord_len)
enum lush_step lush_step_t
frame_t * hpcrun_skip_chords(frame_t *bt_outer, frame_t *bt_inner, int skip)
Definition: backtrace.c:152
lush_step_t lush_step_pnote(lush_cursor_t *cursor)
Definition: lush.c:300
enum lush_assoc lush_assoc_t
Definition: lush-support.h:164
int metric_idleness
Definition: lush.h:96
#define TMSG(f,...)
Definition: messages.h:93
static bool lush_assoc_is_a_to_1(lush_assoc_t as)
Definition: lush-support.h:203
static lush_assoc_t lush_cursor_get_assoc(lush_cursor_t *cursor)
static lush_agentid_t lush_cursor_get_aid(lush_cursor_t *cursor)
#define NULL
Definition: ElfHelper.cpp:85
Definition: cct.c:96
void hpcrun_drop_sample(void)
Definition: sample_event.c:151
frame_t * btbuf_beg
Definition: thread_data.h:185
Definition: frame.h:58
void hpcrun_bt_dump(frame_t *unwind, const char *tag)
Definition: backtrace.c:90
frame_t * btbuf_end
Definition: thread_data.h:189
cct_node_t * hpcrun_cct_insert_backtrace_w_metric(cct_bundle_t *cct, cct_node_t *treenode, int metric_id, frame_t *path_beg, frame_t *path_end, cct_metric_data_t datum, struct cct_custom_update_s *custom_update)
lush_agent_pool_t * lush_agents
static lush_lip_t * lush_lip_clone(lush_lip_t *x)
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition: thread_data.c:168
int metric_time
Definition: lush.h:95