HPCToolkit
papi.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 // PAPI sample source simple oo interface
49 //
50 
51 
52 /******************************************************************************
53  * system includes
54  *****************************************************************************/
55 
56 #include <alloca.h>
57 #include <assert.h>
58 #include <ctype.h>
59 #include <papi.h>
60 #include <setjmp.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <ucontext.h>
65 #include <stdbool.h>
66 
67 #include <pthread.h>
68 
69 /******************************************************************************
70  * libmonitor
71  *****************************************************************************/
72 
73 #include <monitor.h>
74 
75 
76 /******************************************************************************
77  * local includes
78  *****************************************************************************/
79 
80 #include "simple_oo.h"
81 #include "sample_source_obj.h"
82 #include "common.h"
83 
84 #include <hpcrun/hpcrun_options.h>
85 #include <hpcrun/hpcrun_stats.h>
86 #include <hpcrun/metrics.h>
87 #include <hpcrun/safe-sampling.h>
89 #include <hpcrun/sample_event.h>
90 #include <hpcrun/thread_data.h>
91 
93 #include <utilities/tokenize.h>
94 #include <messages/messages.h>
95 #include <lush/lush-backtrace.h>
97 
98 
99 /******************************************************************************
100  * macros
101  *****************************************************************************/
102 
103 #define OVERFLOW_MODE 0
104 #define WEIGHT_METRIC 0
105 #define DEFAULT_THRESHOLD 2000000L
106 
107 
108 /******************************************************************************
109  * type declarations
110  *****************************************************************************/
111 
112 typedef struct {
113  int eventSet;
114  long long prev_values[MAX_EVENTS];
116 
117 
118 /******************************************************************************
119  * forward declarations
120  *****************************************************************************/
121 
122 static void papi_event_handler(int event_set, void *pc, long long ovec, void *context);
123 static int event_is_derived(int ev_code);
124 static void event_fatal_error(int ev_code, int papi_ret);
125 
126 
127 /******************************************************************************
128  * local variables
129  *****************************************************************************/
130 
131 // static int cyc_metric_id = -1; /* initialized to an illegal metric id */
132 
133 // Special case to make PAPI_library_init() a soft failure.
134 // Make sure that we call no other PAPI functions.
135 //
136 static int papi_unavail = 0;
137 
138 // Support for derived events (proxy sampling).
139 static int derived[MAX_EVENTS];
140 static int some_derived;
141 static int some_overflow;
142 
143 /******************************************************************************
144  * external thread-local variables
145  *****************************************************************************/
146 extern __thread bool hpcrun_thread_suppress_sample;
147 
148 /******************************************************************************
149  * method functions
150  *****************************************************************************/
151 
152 // strip the prefix "papi::" from an event name, if exists.
153 // this allows forcing a papi event over a perf event.
154 // allow case-insensitive and any number of ':'
155 static const char *
156 strip_papi_prefix(const char *str)
157 {
158  if (strncasecmp(str, "papi:", 5) == 0) {
159  str = &str[5];
160 
161  while (str[0] == ':') {
162  str = &str[1];
163  }
164  }
165 
166  return str;
167 }
168 
169 static void
171 {
172  PAPI_set_debug(0x3ff);
173 
174  // **NOTE: some papi components may start threads, so
175  // hpcrun must ignore these threads to ensure that PAPI_library_init
176  // succeeds
177  //
178  monitor_disable_new_threads();
179  int ret = PAPI_library_init(PAPI_VER_CURRENT);
180  monitor_enable_new_threads();
181  TMSG(PAPI,"PAPI_library_init = %d", ret);
182  TMSG(PAPI,"PAPI_VER_CURRENT = %d", PAPI_VER_CURRENT);
183 
184  // Delay reporting PAPI_library_init() errors. This allows running
185  // with other events if PAPI is not available.
186  if (ret < 0) {
188  papi_unavail = 1;
189  } else if (ret != PAPI_VER_CURRENT) {
191  papi_unavail = 1;
192  }
193 
194  // Tell PAPI to count events in all contexts (user, kernel, etc).
195  // FIXME: PAPI_DOM_ALL causes some syscalls to fail which then
196  // breaks some applications. For example, this breaks some Gemini
197  // (GNI) functions called from inside gasnet_init() or MPI_Init() on
198  // the Cray XE (hopper).
199  //
200  if (ENABLED(SYSCALL_RISKY)) {
201  ret = PAPI_set_domain(PAPI_DOM_ALL);
202  if (ret != PAPI_OK) {
203  EMSG("warning: PAPI_set_domain(PAPI_DOM_ALL) failed: %d", ret);
204  }
205  }
206 
207  self->state = INIT;
208 }
209 
210 static void
211 METHOD_FN(thread_init)
212 {
213  TMSG(PAPI, "thread init");
214  if (papi_unavail) { return; }
215 
216  int retval = PAPI_thread_init(pthread_self);
217  if (retval != PAPI_OK) {
218  EEMSG("PAPI_thread_init NOT ok, retval = %d", retval);
220  }
221  TMSG(PAPI, "thread init OK");
222 }
223 
224 static void
225 METHOD_FN(thread_init_action)
226 {
227  TMSG(PAPI, "register thread");
228  if (papi_unavail) { return; }
229 
230  int retval = PAPI_register_thread();
231  if (retval != PAPI_OK) {
232  EEMSG("PAPI_register_thread NOT ok, retval = %d", retval);
234  }
235  TMSG(PAPI, "register thread ok");
236 }
237 
238 static void
239 METHOD_FN(start)
240 {
241  TMSG(PAPI, "start");
242  if (papi_unavail) { return; }
243 
245  papi_source_info_t *psi = td->ss_info[self->sel_idx].ptr;
246  int eventSet = psi->eventSet;
247  source_state_t my_state = TD_GET(ss_state)[self->sel_idx];
248 
249  // make PAPI start idempotent. the application can turn on sampling
250  // anywhere via the start-stop interface, so we can't control what
251  // state PAPI is in.
252 
253  if (my_state == START) {
254  return;
255  }
256 
257  TMSG(PAPI,"starting PAPI w event set %d",eventSet);
258  int ret = PAPI_start(eventSet);
259  if (ret == PAPI_EISRUN) {
260  // this case should not happen, but maybe it's not fatal
261  EMSG("PAPI returned EISRUN, but state was not START");
262  }
263  else if (ret != PAPI_OK) {
264  EMSG("PAPI_start failed with %s (%d)", PAPI_strerror(ret), ret);
265  hpcrun_ssfail_start("PAPI");
266  }
267 
268  if (some_derived) {
269  ret = PAPI_read(eventSet, psi->prev_values);
270  if (ret != PAPI_OK) {
271  EMSG("PAPI_read failed with %s (%d)", PAPI_strerror(ret), ret);
272  }
273  }
274 
275  TD_GET(ss_state)[self->sel_idx] = START;
276 }
277 
278 static void
279 METHOD_FN(thread_fini_action)
280 {
281  TMSG(PAPI, "unregister thread");
282  if (papi_unavail) { return; }
283 
284  int retval = PAPI_unregister_thread();
285  char msg[] = "!!NOT PAPI_OK!! (code = -9999999)\n";
286  snprintf(msg, sizeof(msg)-1, "!!NOT PAPI_OK!! (code = %d)", retval);
287  TMSG(PAPI, "unregister thread returns %s", retval == PAPI_OK? "PAPI_OK" : msg);
288 }
289 
290 static void
292 {
293  TMSG(PAPI, "stop");
294  if (papi_unavail) { return; }
295 
297  papi_source_info_t *psi = td->ss_info[self->sel_idx].ptr;
298  int eventSet = psi->eventSet;
299  int nevents = self->evl.nevents;
300  source_state_t my_state = TD_GET(ss_state)[self->sel_idx];
301 
302  if (my_state == STOP) {
303  TMSG(PAPI,"--stop called on an already stopped event set %d",eventSet);
304  return;
305  }
306 
307  if (my_state != START) {
308  TMSG(PAPI,"*WARNING* Stop called on event set that has not been started");
309  return;
310  }
311 
312  TMSG(PAPI,"stop w event set = %d",eventSet);
313  long_long *values = (long_long *) alloca(sizeof(long_long) * (nevents+2));
314  int ret = PAPI_stop(eventSet, values);
315  if (ret != PAPI_OK){
316  EMSG("Failed to stop papi f eventset %d. Return code = %d ==> %s",
317  eventSet,ret,PAPI_strerror(ret));
318  }
319 
320  TD_GET(ss_state)[self->sel_idx] = STOP;
321 }
322 
323 static void
324 METHOD_FN(shutdown)
325 {
326  TMSG(PAPI, "shutdown");
327  if (papi_unavail) { return; }
328 
329  METHOD_CALL(self, stop); // make sure stop has been called
330  PAPI_shutdown();
331 
332  self->state = UNINIT;
333 }
334 
335 // Return true if PAPI recognizes the name, whether supported or not.
336 // We'll handle unsupported events later.
337 static bool
338 METHOD_FN(supports_event, const char *ev_str)
339 {
340  ev_str = strip_papi_prefix(ev_str);
341 
342  TMSG(PAPI, "supports event");
343  if (papi_unavail) { return false; }
344 
345  if (self->state == UNINIT){
346  METHOD_CALL(self, init);
347  }
348 
349  char evtmp[1024];
350  int ec;
351  long th;
352 
353  hpcrun_extract_ev_thresh(ev_str, sizeof(evtmp), evtmp, &th, DEFAULT_THRESHOLD);
354  return PAPI_event_name_to_code(evtmp, &ec) == PAPI_OK;
355 }
356 
357 static void
358 METHOD_FN(process_event_list, int lush_metrics)
359 {
360  TMSG(PAPI, "process event list");
361  if (papi_unavail) { return; }
362 
363  char *event;
364  int i, ret;
365  int num_lush_metrics = 0;
366 
367  char* evlist = METHOD_CALL(self, get_event_str);
368  for (event = start_tok(evlist); more_tok(); event = next_tok()) {
369  char name[1024];
370  int evcode;
371  long thresh;
372 
373  event = (char *) strip_papi_prefix(event);
374 
375  TMSG(PAPI,"checking event spec = %s",event);
376  if (! hpcrun_extract_ev_thresh(event, sizeof(name), name, &thresh, DEFAULT_THRESHOLD)) {
377  AMSG("WARNING: %s using default threshold %ld, "
378  "better to use an explicit threshold.", name, DEFAULT_THRESHOLD);
379  }
380  ret = PAPI_event_name_to_code(name, &evcode);
381  if (ret != PAPI_OK) {
382  EMSG("unexpected failure in PAPI process_event_list(): "
383  "PAPI_event_name_to_code() returned %s (%d)",
384  PAPI_strerror(ret), ret);
385  hpcrun_ssfail_unsupported("PAPI", name);
386  }
387  if (PAPI_query_event(evcode) != PAPI_OK) {
388  hpcrun_ssfail_unsupported("PAPI", name);
389  }
390 
391  // FIXME:LUSH: need a more flexible metric interface
392  if (lush_metrics == 1 && strncmp(event, "PAPI_TOT_CYC", 12) == 0) {
393  num_lush_metrics++;
394  }
395 
396  TMSG(PAPI,"got event code = %x, thresh = %ld", evcode, thresh);
397  METHOD_CALL(self, store_event, evcode, thresh);
398  }
399  int nevents = (self->evl).nevents;
400  TMSG(PAPI,"nevents = %d", nevents);
401 
402  hpcrun_pre_allocate_metrics(nevents + num_lush_metrics);
403 
404  some_derived = 0;
405  some_overflow = 0;
406  for (i = 0; i < nevents; i++) {
407  char buffer[PAPI_MAX_STR_LEN + 10];
408  int metric_id = hpcrun_new_metric(); /* weight */
410  METHOD_CALL(self, store_metric_id, i, metric_id);
411  PAPI_event_code_to_name(self->evl.events[i].event, buffer);
412  TMSG(PAPI, "metric for event %d = %s", i, buffer);
413  // blame shifting needs to know if there is a cycles metric
414  if (strcmp(buffer, "PAPI_TOT_CYC") == 0) {
415  prop = metric_property_cycles;
417  }
418 
419  // allow derived events (proxy sampling), as long as some event
420  // supports hardware overflow. use threshold = 0 to force proxy
421  // sampling (for testing).
422  if (event_is_derived(self->evl.events[i].event)
423  || self->evl.events[i].thresh == 0)
424  {
425  TMSG(PAPI, "using proxy sampling for event %s", buffer);
426  strcat(buffer, " (proxy)");
427  self->evl.events[i].thresh = 1;
428  derived[i] = 1;
429  some_derived = 1;
430  } else {
431  derived[i] = 0;
432  some_overflow = 1;
433  }
434 
435  hpcrun_set_metric_info_and_period(metric_id, strdup(buffer),
437  self->evl.events[i].thresh, prop);
438 
439  // FIXME:LUSH: need a more flexible metric interface
440  if (num_lush_metrics > 0 && strcmp(buffer, "PAPI_TOT_CYC") == 0) {
441  // there should be one lush metric; its source is the last event
442  assert(num_lush_metrics == 1 && (i == (nevents - 1)));
443  int mid_idleness = hpcrun_new_metric();
444  lush_agents->metric_time = metric_id;
445  lush_agents->metric_idleness = mid_idleness;
446 
447  hpcrun_set_metric_info_and_period(mid_idleness, "idleness",
449  self->evl.events[i].thresh, prop);
450  }
451  }
452 
453  if (! some_overflow) {
455  }
456 }
457 
458 static void
459 METHOD_FN(gen_event_set,int lush_metrics)
460 {
461  int i;
462  int ret;
463  int eventSet;
464 
465  TMSG(PAPI, "gen event set");
466  if (papi_unavail) { return; }
467 
468  int ss_info_size = sizeof(papi_source_info_t);
469  papi_source_info_t *psi = hpcrun_malloc(ss_info_size);
470  if (psi == NULL) {
471  hpcrun_abort("Failure to allocate space for PAPI sample source");
472  }
473 
474  psi->eventSet = PAPI_NULL;
475  memset(psi->prev_values,0, sizeof(psi->prev_values));
476 
477  // record the component state in thread state
479  td->ss_info[self->sel_idx].ptr = psi;
480 
481 
482  eventSet = PAPI_NULL;
483  ret = PAPI_create_eventset(&eventSet);
484  TMSG(PAPI,"PAPI_create_eventset = %d, eventSet = %d", ret, eventSet);
485  if (ret != PAPI_OK) {
486  hpcrun_abort("Failure: PAPI_create_eventset.Return code = %d ==> %s",
487  ret, PAPI_strerror(ret));
488  }
489 
490  int nevents = (self->evl).nevents;
491  for (i = 0; i < nevents; i++) {
492  int evcode = self->evl.events[i].event;
493  ret = PAPI_add_event(eventSet, evcode);
494  TMSG(PAPI, "PAPI_add_event(eventSet=%d, event_code=%x)", eventSet, evcode);
495  if (ret != PAPI_OK) {
496  EMSG("failure in PAPI gen_event_set(): PAPI_add_event() returned: %s (%d)",
497  PAPI_strerror(ret), ret);
498  event_fatal_error(evcode, ret);
499  }
500  }
501 
502  for (i = 0; i < nevents; i++) {
503  int evcode = self->evl.events[i].event;
504  long thresh = self->evl.events[i].thresh;
505 
506  if (! derived[i]) {
507  TMSG(PAPI, "PAPI_overflow(eventSet=%d, evcode=%x, thresh=%d)",
508  eventSet, evcode, thresh);
509  ret = PAPI_overflow(eventSet, evcode, thresh, OVERFLOW_MODE,
511  TMSG(PAPI, "PAPI_overflow = %d", ret);
512  if (ret != PAPI_OK) {
513  EMSG("failure in PAPI gen_event_set(): PAPI_overflow() returned: %s (%d)",
514  PAPI_strerror(ret), ret);
515  event_fatal_error(evcode, ret);
516  }
517  }
518  }
519  psi->eventSet= eventSet;
520 }
521 
522 static void
523 METHOD_FN(display_events)
524 {
525  PAPI_event_info_t info;
526  char name[200], *prof;
527  int ev, ret, num_total, num_prof;
528 
529  printf("===========================================================================\n");
530  printf("Available PAPI preset events\n");
531  printf("===========================================================================\n");
532  printf("Name\t Profilable\tDescription\n");
533  printf("---------------------------------------------------------------------------\n");
534 
535  if (papi_unavail) {
536  printf("PAPI is not available. Probably, the kernel doesn't support PAPI,\n"
537  "or else maybe HPCToolkit is out of sync with PAPI.\n\n");
538  return;
539  }
540 
541  num_total = 0;
542  num_prof = 0;
543  ev = PAPI_PRESET_MASK;
544  ret = PAPI_OK;
545 #ifdef PAPI_ENUM_FIRST
546  ret = PAPI_enum_event(&ev, PAPI_ENUM_FIRST);
547 #endif
548  while (ret == PAPI_OK) {
549  if (PAPI_query_event(ev) == PAPI_OK
550  && PAPI_get_event_info(ev, &info) == PAPI_OK
551  && info.count != 0)
552  {
553  PAPI_event_code_to_name(ev, name);
554  if (event_is_derived(ev)) {
555  prof = "No";
556  } else {
557  prof = "Yes";
558  num_prof++;
559  }
560  num_total++;
561  printf("%-10s\t%s\t%s\n", name, prof, info.long_descr);
562  }
563  ret = PAPI_enum_event(&ev, PAPI_ENUM_EVENTS);
564  }
565  printf("Total PAPI events: %d, able to profile: %d\n",
566  num_total, num_prof);
567  printf("\n");
568 
569  printf("===========================================================================\n");
570  printf("Available native events\n");
571  printf("===========================================================================\n");
572  printf("Name\t\t\t\tDescription\n");
573  printf("---------------------------------------------------------------------------\n");
574 
575  num_total = 0;
576  ev = PAPI_NATIVE_MASK;
577  ret = PAPI_OK;
578 #ifdef PAPI_ENUM_FIRST
579  ret = PAPI_enum_event(&ev, PAPI_ENUM_FIRST);
580 #endif
581  while (ret == PAPI_OK) {
582  if (PAPI_query_event(ev) == PAPI_OK) {
583  PAPI_event_code_to_name(ev, name);
584  PAPI_get_event_info(ev, &info);
585  num_total++;
586  printf("%-30s\t%s\n", name, info.long_descr);
587  }
588  ret = PAPI_enum_event(&ev, PAPI_ENUM_EVENTS);
589  }
590  printf("Total native events: %d\n", num_total);
591  printf("\n");
592 }
593 
594 /***************************************************************************
595  * object
596  ***************************************************************************/
597 
598 #define ss_name papi
599 #define ss_cls SS_HARDWARE
600 #define ss_sort_order 70
601 
602 #include "ss_obj.h"
603 
604 /******************************************************************************
605  * public operations
606  *****************************************************************************/
607 
608 //
609 // Do not need to disable the papi cuda component if there is no papi component
610 //
611 void
613 {
614  ;
615 }
616 
617 /******************************************************************************
618  * private operations
619  *****************************************************************************/
620 
621 // Returns: 1 if the event code is a derived event.
622 // The papi_avail(1) utility shows how to do this.
623 static int
624 event_is_derived(int ev_code)
625 {
626  PAPI_event_info_t info;
627 
628  // "Is derived" is kind of a bad thing, so if any unexpected failure
629  // occurs, we'll return the "bad" answer.
630  if (PAPI_get_event_info(ev_code, &info) != PAPI_OK
631  || info.derived == NULL) {
632  return 1;
633  }
634  if (info.count == 1
635  || strlen(info.derived) == 0
636  || strcmp(info.derived, "NOT_DERIVED") == 0
637  || strcmp(info.derived, "DERIVED_CMPD") == 0) {
638  return 0;
639  }
640  return 1;
641 }
642 
643 static void
644 event_fatal_error(int ev_code, int papi_ret)
645 {
646  char name[1024];
647 
648  PAPI_event_code_to_name(ev_code, name);
649  if (PAPI_query_event(ev_code) != PAPI_OK) {
650  hpcrun_ssfail_unsupported("PAPI", name);
651  }
652  if (event_is_derived(ev_code)) {
653  hpcrun_ssfail_derived("PAPI", name);
654  }
655  if (papi_ret == PAPI_ECNFLCT) {
656  hpcrun_ssfail_conflict("PAPI", name);
657  }
658  hpcrun_ssfail_unsupported("PAPI", name);
659 }
660 
661 static void
662 papi_event_handler(int event_set, void *pc, long long ovec,
663  void *context)
664 {
665  sample_source_t *self = &_papi_obj;
666  long long values[MAX_EVENTS];
667  int my_events[MAX_EVENTS];
668  int my_event_count = MAX_EVENTS;
669  int nevents = self->evl.nevents;
670  int i, ret;
671 
672  // if sampling disabled explicitly for this thread, skip all processing
673  if (hpcrun_thread_suppress_sample) return;
674 
675 
676  // If the interrupt came from inside our code, then drop the sample
677  // and return and avoid any MSG.
678  if (! hpcrun_safe_enter_async(pc)) {
680  return;
681  }
682 
683  TMSG(PAPI_SAMPLE,"papi event happened, ovec = %ld",ovec);
684 
685  if (some_derived) {
686  ret = PAPI_read(event_set, values);
687  if (ret != PAPI_OK) {
688  EMSG("PAPI_read failed with %s (%d)", PAPI_strerror(ret), ret);
689  }
690  }
691 
692  ret = PAPI_get_overflow_event_index(event_set, ovec, my_events, &my_event_count);
693  if (ret != PAPI_OK) {
694  hpcrun_abort("Failed inside papi_event_handler at get_overflow_event_index."
695  "Return code = %d ==> %s", ret, PAPI_strerror(ret));
696  }
697 
698  for (i = 0; i < my_event_count; i++) {
699  // FIXME: SUBTLE ERROR: metric_id may not be same from hpcrun_new_metric()!
700  // This means lush's 'time' metric should be *last*
701 
702  int metric_id = hpcrun_event2metric(&_papi_obj, my_events[i]);
703 
704  TMSG(PAPI_SAMPLE,"sampling call path for metric_id = %d", metric_id);
705  hpcrun_metricVal_t value = {.i=1};
706  sample_val_t sv = hpcrun_sample_callpath(context, metric_id, value/*metricIncr*/,
707  0/*skipInner*/, 0/*isSync*/, NULL);
708 
709  blame_shift_apply(metric_id, sv.sample_node, 1 /*metricIncr*/);
710  }
711 
712  // Add metric values for derived events by the difference in counter
713  // values. Some samples can take a long time (eg, analyzing a new
714  // load module), so read the counters both on entry and exit to
715  // avoid counting our work.
716 
717  if (some_derived) {
719  papi_source_info_t *psi = td->ss_info[self->sel_idx].ptr;
720  for (i = 0; i < nevents; i++) {
721  if (derived[i]) {
722  hpcrun_metricVal_t value = {.i = values[i] - psi->prev_values[i]};
724  value, 0, 0, NULL);
725  }
726  }
727 
728  ret = PAPI_read(event_set, psi->prev_values);
729  if (ret != PAPI_OK) {
730  EMSG("PAPI_read failed with %s (%d)", PAPI_strerror(ret), ret);
731  }
732  }
733 
735 }
static int derived[MAX_EVENTS]
Definition: papi.c:139
source_state_t
static void hpcrun_safe_exit(void)
sample_val_t hpcrun_sample_callpath(void *context, int metricId, hpcrun_metricVal_t metricIncr, int skipInner, int isSync, sampling_info_t *data)
Definition: sample_event.c:160
void hpcrun_ssfail_derived(char *source, char *event)
Definition: common.c:238
long long prev_values[MAX_EVENTS]
Definition: papi.c:114
void blame_shift_source_register(bs_type bst)
Definition: blame-shift.c:25
void hpcrun_save_papi_error(int error)
Definition: common.c:184
void hpcrun_ssfail_all_derived(char *source)
Definition: common.c:246
#define hpcrun_abort(...)
Definition: messages.h:102
cct_node_t * sample_node
Definition: sample_event.h:96
static const char * strip_papi_prefix(const char *str)
Definition: papi.c:156
void blame_shift_apply(int metric_id, cct_node_t *node, int metric_incr)
Definition: blame-shift.c:15
void hpcrun_stats_num_samples_blocked_async_inc(void)
Definition: hpcrun_stats.c:148
static void METHOD_FN(init)
Definition: papi.c:170
static int event_is_derived(int ev_code)
Definition: papi.c:624
char * next_tok(void)
Definition: tokenize.c:87
metric_desc_t * hpcrun_set_metric_info_and_period(int metric_id, const char *name, MetricFlags_ValFmt_t valFmt, size_t period, metric_desc_properties_t prop)
Definition: metrics.c:411
static int some_derived
Definition: papi.c:140
#define OVERFLOW_MODE
Definition: papi.c:103
#define EMSG
Definition: messages.h:70
void hpcrun_ssfail_unsupported(char *source, char *event)
Definition: common.c:230
#define metric_property_cycles
Definition: hpcrun-fmt.h:201
char * start_tok(char *lst)
Definition: tokenize.c:70
static void papi_event_handler(int event_set, void *pc, long long ovec, void *context)
Definition: papi.c:662
static int papi_unavail
Definition: papi.c:136
int lush_metrics
Definition: main.c:188
void hpcrun_ssfail_start(char *source)
Definition: common.c:265
void * hpcrun_malloc(size_t size)
Definition: mem.c:275
#define TD_GET(field)
Definition: thread_data.h:256
__thread bool hpcrun_thread_suppress_sample
Definition: main.c:193
int metric_idleness
Definition: lush.h:96
#define TMSG(f,...)
Definition: messages.h:93
int hpcrun_extract_ev_thresh(const char *in, int evlen, char *ev, long *th, long def)
Definition: tokenize.c:157
static int hpcrun_safe_enter_async(void *pc)
int hpcrun_event2metric(sample_source_t *ss, int event_idx)
Definition: common.c:143
#define AMSG
Definition: messages.h:71
#define METHOD_CALL(obj, meth,...)
Definition: simple_oo.h:87
#define EEMSG(...)
Definition: messages.h:90
#define NULL
Definition: ElfHelper.cpp:85
int hpcrun_new_metric(void)
Definition: metrics.c:333
#define HPCRUN_PAPI_ERROR_VERSION
Definition: common.h:53
static void event_fatal_error(int ev_code, int papi_ret)
Definition: papi.c:644
#define MAX_EVENTS
Definition: evlist.h:51
void monitor_real_abort(void)
#define DEFAULT_THRESHOLD
Definition: papi.c:105
void hpcrun_pre_allocate_metrics(size_t num)
Definition: metrics.c:190
source_info_t * ss_info
Definition: thread_data.h:151
static int some_overflow
Definition: papi.c:141
lush_agent_pool_t * lush_agents
int more_tok(void)
Definition: tokenize.c:78
void hpcrun_disable_papi_cuda(void)
Definition: papi.c:612
#define ENABLED(f)
Definition: debug-flag.h:76
#define HPCRUN_PAPI_ERROR_UNAVAIL
Definition: common.h:52
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition: thread_data.c:168
#define metric_property_none
Definition: hpcrun-fmt.h:202
int metric_time
Definition: lush.h:95
void hpcrun_ssfail_conflict(char *source, char *event)
Definition: common.c:255