HPCToolkit
monitor.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 // A library of routines for preparing and finalizing monitoring
54 // for a process. The library can determine a process' list of
55 // load modules (including DSOs), prepare PAPI_sprofil for
56 // profiling over each load module, finalize profiling and write
57 // the data for later processing.
58 //
59 // Description:
60 // [The set of functions, macros, etc. defined in the file]
61 //
62 // Author:
63 // Written by John Mellor-Crummey and Nathan Tallent, Rice University.
64 //
65 // Acknowledgements:
66 // Phil Mucci's 'papiex' code provided guidance for handling threads.
67 //
68 // The PAPI Initialization code was originally adapted from parts of The
69 // Visual Profiler by Curtis L. Janssen (vmon.c).
70 //
71 *****************************************************************************/
72 
73 /************************** System Include Files ****************************/
74 
75 #include <stdlib.h>
76 #include <unistd.h>
77 #include <stdio.h>
78 #include <stdarg.h> /* va_arg */
79 #include <ctype.h>
80 #include <signal.h>
81 #include <string.h>
82 #include <limits.h> /* for 'PATH_MAX' */
83 #include <errno.h>
84 #include <dlfcn.h>
85 #include <pthread.h>
86 #include <sys/stat.h>
87 #include <sys/types.h>
88 
89 /**************************** User Include Files ****************************/
90 
91 #include <include/hpctoolkit-config.h>
92 #include <include/uint.h>
93 #include <include/min-max.h>
94 
95 #include "monitor.h"
96 
97 #ifdef HAVE_MONITOR
98 // FIXME: use libmonitor completely and include it
99 extern unsigned long monitor_gettid();
100 #endif
101 
102 #include "hpcrun.h"
103 #include "hpcpapi.h" /* <papi.h>, etc. */
104 #include "rtmap.h"
105 
106 #include <lib/prof-lean/hpcio.h>
107 
108 /**************************** Forward Declarations **************************/
109 
110 /* FIXME: this should be part of the data file */
111 typedef uint32_t hpc_hist_bucket; /* a 4 byte histogram bucket */
112 
113 static const uint64_t default_period = 999999; /* not (2^15 - 1) */
114 
115 /**************************** Forward Declarations **************************/
116 
117 /* intercepted signals */
118 static void hpcrun_sighandler(int sig);
119 
120 /*************************** Variable Declarations **************************/
121 
122 /* This info is constant throughout the process and can therefore be
123  shared among multiple threads. */
124 
125 /* hpcrun options: set when the library is initialized */
126 int opt_debug = 0;
130 char opt_outpath[PATH_MAX] = "";
131 char opt_prefix[PATH_MAX] = "";
132 char opt_file[PATH_MAX] = "";
134 
135 /* monitored command: set when library or process is initialized */
136 const char* hpcrun_cmd = NULL;
137 
138 /* monitoring variables: set when the process is initialized */
139 static rtloadmap_t* rtloadmap = NULL; /* run time load map */
140 static uint numSysEvents = 0; /* estimate */
141 static uint numPAPIEvents = 0; /* estimate */
142 
143 /* Profiling information for the first thread of execution in a
144  process. N.B. The _shared_ profiling buffers live here when
145  combining thread profiles. */
147 
148 /* PAPI-specific variables */
149 static int domain = 0;
150 
151 #define OPEN_OUTPUTFILE_AT_BEG 1
152 
153 /****************************************************************************
154  * Library initialization and finalization
155  ****************************************************************************/
156 
157 static void init_option_debug();
158 static void init_options();
159 
160 /*
161  * Library initialization
162  */
163 extern void
165 {
167 
168  if (opt_debug >= 1) { MSG0(stderr, "*** init_library ***"); }
169 
170  init_options();
171 
172 #ifndef HAVE_MONITOR
174 #endif
175 }
176 
177 
178 /*
179  * Library finalization. Since this routine can be called more than
180  * once per process, ensure that it is idempotent.
181  */
182 extern void
184 {
185  static int is_finalized = 0;
186  if (is_finalized) {
187  if (opt_debug >= 1) { MSG0(stderr, "*** fini_library (skip) ***"); }
188  return;
189  }
190 
191  is_finalized = 1;
192  if (opt_debug >= 1) { MSG0(stderr, "*** fini_library ***"); }
193 }
194 
195 
196 static void
198 {
199  /* Debugging (get this first) : default is off */
200  char *env_debug = getenv("HPCRUN_DEBUG");
201  opt_debug = (env_debug ? atoi(env_debug) : 0);
202 }
203 
204 
205 static void
207 {
208  char *env_recursive, *env_thread, *env_eventlist, *env_outpath, *env_flags;
209  int is_opt_file, is_opt_prefix, is_opt_dir;
210  is_opt_file = is_opt_prefix = is_opt_dir = 0; /* off be default */
211 
212  /* Handle HPCRUN_OPTIONS */
213  char *opts = getenv("HPCRUN_OPTIONS");
214  if (opts && (strlen(opts)>0)) {
215  char* tmp = strtok(opts,", ");
216  if (tmp) {
217  do {
218  if (strcmp(tmp,"USER") == 0)
219  domain |= PAPI_DOM_USER;
220  else if (strcmp(tmp,"KERNEL") == 0)
221  domain |= PAPI_DOM_KERNEL;
222  else if (strcmp(tmp,"OTHER") == 0)
223  domain |= PAPI_DOM_OTHER;
224  else if (strcmp(tmp,"SUPERVISOR") == 0)
225  domain |= PAPI_DOM_SUPERVISOR;
226  else if (strcmp(tmp, "FILE") == 0)
227  is_opt_file = 1;
228  else if (strcmp(tmp, "PREFIX") == 0)
229  is_opt_prefix = 1;
230  else if (strcmp(tmp, "DIR") == 0)
231  is_opt_dir = 1;
232  } while ((tmp = strtok(NULL,",")) != NULL);
233  }
234  }
235 
236  if (opt_debug >= 1) {
237  MSGx(stderr, " LD_PRELOAD: %s", getenv("LD_PRELOAD"));
238  }
239 
240  /* Recursive profiling: default is on */
241  env_recursive = getenv("HPCRUN_RECURSIVE");
242  opt_recursive = (env_recursive ? atoi(env_recursive) : 1);
243  if (!opt_recursive) {
244  /* turn off profiling for any processes spawned by this one */
245  unsetenv("LD_PRELOAD");
246  /* FIXME: just extract HPCRUN_LIB */
247  }
248 
249  if (opt_debug >= 1) {
250  MSGx(stderr, " recursive profiling: %d", opt_recursive);
251  }
252 
253  /* Threaded profiling: default is off */
254  env_thread = getenv("HPCRUN_THREAD");
255  if (env_thread) {
256  opt_thread = (hpc_threadprof_t)atoi(env_thread);
257  }
258 
259  /* Profiling event list: default PAPI_TOT_CYC:999999 (default_period) */
260  opt_eventlist = "PAPI_TOT_CYC:999999";
261  env_eventlist = getenv("HPCRUN_EVENT_LIST");
262  if (env_eventlist) {
263  opt_eventlist = env_eventlist;
264  }
265 
266  if (opt_debug >= 1) { MSGx(stderr, " event list: %s", opt_eventlist); }
267 
268  /* Output path: default . */
269  env_outpath = getenv("HPCRUN_OUTPUT");
270  if (is_opt_dir && env_outpath) {
271  strncpy(opt_outpath, env_outpath, PATH_MAX);
272  if(mkdir(opt_outpath, 0755))
273  if (errno != EEXIST) {
274  DIEx("error: mkdir(%s) failed. %s\n", opt_outpath, strerror(errno));
275  }
276  }
277  else
278  strcpy(opt_outpath, ".");
279 
280  /* user-supplied prefix */
281  if (is_opt_prefix && env_outpath)
282  strncpy(opt_prefix, env_outpath, PATH_MAX);
283 
284  /* user-supplied file name */
285  if (is_opt_file && env_outpath)
286  strncpy(opt_file, env_outpath, PATH_MAX);
287 
288  /* Profiling flags: default PAPI_PROFIL_POSIX */
289  {
290  const hpcpapi_flagdesc_t *f = hpcpapi_flag_by_name("PAPI_PROFIL_POSIX");
291  opt_flagscode = f->code;
292 
293  env_flags = getenv("HPCRUN_EVENT_FLAG");
294  if (env_flags) {
295  char *ptr = NULL, *token = NULL;
296  token = strtok_r(env_flags,",:",&ptr);
297  while (token) {
298  if ((f = hpcpapi_flag_by_name(token)) == NULL) {
299  DIEx("error: Invalid profiling flag '%s'.", token);
300  }
301  opt_flagscode |= f->code;
302  if (opt_debug >=1) {
303  MSGx(stderr, " flag: %s, 0x%x, 0x%x", token, f->code, opt_flagscode);
304  }
305  token = strtok_r(NULL,",:",&ptr);
306  }
307  }
308  }
309 }
310 
311 
312 /****************************************************************************
313  * Intercepted routines
314  ****************************************************************************/
315 
316 /* none for now */
317 
318 /****************************************************************************
319  * Intercepted signals
320  ****************************************************************************/
321 
322 /* We allow the user to kill profiling by intercepting the certain
323  signals. This can be very useful on long-running or misbehaving
324  applications. */
325 
326 static void
328 {
329  if (opt_debug >= 1) { MSGx(stderr, "*** catching signal %d ***", sig); }
330 
331  signal(sig, SIG_DFL); /* return to default action */
332 
333  switch (sig) {
334  case SIGINT:
335  case SIGABRT: {
336  break;
337  }
338  default:
339  MSGx(stderr, "warning: Handling unknown signal %d.", sig);
340  break;
341  }
342 
343  fini_process();
344  fini_library();
345 
346  signal(SIGABRT, SIG_DFL); /* return SIGABRT to default before abort()! */
347  abort();
348 }
349 
350 
351 /****************************************************************************/
352 /****************************************************************************/
353 
354 /****************************************************************************
355  * Initialize profiling
356  ****************************************************************************/
357 
358 static void
359 count_events(uint* sysEvents, uint* papiEvents);
360 
361 static void
363  uint numSysEv, uint numPapiEv,
364  rtloadmap_t* rtmap,
365  hpcrun_profiles_desc_t* sharedprofdesc);
366 
367 static void
369  uint numEv, rtloadmap_t* rtmap,
370  hpcsys_profile_desc_vec_t* sharedprofdesc);
371 static void
373  uint numEv, rtloadmap_t* rtmap,
374  hpcsys_profile_desc_vec_t* sharedprofdesc);
375 static void
377  uint numEv, rtloadmap_t* rtmap,
378  hpcpapi_profile_desc_vec_t* sharedprofdesc);
379 static void
381  uint numEv, rtloadmap_t* rtmap,
382  hpcpapi_profile_desc_vec_t* sharedprofdesc);
383 
384 static void
386  int sharedprofdesc);
387 
388 static void
390  hpcrun_profiles_desc_t* sharedprofdesc);
391 
392 static void
394  rtloadmap_t* rtmap, int profidx,
395  char* eventnm, uint64_t period);
396 
397 static void
399 
400 static void
402 
403 static void
405  rtloadmap_t* rtmap, int profidx,
406  char* eventnm, uint64_t period);
407 
408 static void
410 
411 static void
413 
414 
415 /* Stop profiling */
416 static void
418 
419 static void
421 
422 
423 
424 volatile int DEBUGGER_WAIT = 1;
425 
426 /*
427  * Prepare for profiling this process
428  */
429 extern void
431 {
432  if (getenv("HPCRUN_WAIT")){
433  while(DEBUGGER_WAIT);
434  }
435 
436  if (opt_debug >= 1) { MSG0(stderr, "*** init_process ***"); }
437 
438  rtloadmap = hpcrun_get_rtloadmap(opt_debug);
439 
440  /* Initialize PAPI if necessary */
441  count_events(&numSysEvents, &numPAPIEvents); /* no error checking */
442  if (numPAPIEvents > 0) {
444  }
445 
446  hpc_profdesc = init_thread(0 /*is_thread*/);
447 }
448 
449 /*
450  * Called after the loading of a module using dlopen() to update the
451  * profiling tables
452  *
453  */
454 extern void
456 {
457  if (hpc_profdesc == NULL) {
458  DIE0("dlopen before process initialization!");
459  }
460 
461  /* Stop profiling */
463  stop_sysprof(HPC_GET_SYSPROFS(hpc_profdesc));
464 
465  /* Clear the rtloadmap */
466  free(rtloadmap->module);
467 
468  /* Get the new module(s) from /proc/pid/maps */
469  rtloadmap = hpcrun_get_rtloadmap(opt_debug);
470 
471  /* Determine if profile data needs to be shared across threads */
472  hpcrun_profiles_desc_t* sharedprofdesc = NULL;
474  sharedprofdesc = hpc_profdesc;
475 
476  /* For each sys profdescs entry, append sprofil()-specific info */
477  if (HPC_GET_SYSPROFS(hpc_profdesc)) {
479  (sharedprofdesc) ? HPC_GET_SYSPROFS(sharedprofdesc) : NULL;
481  rtloadmap, sh);
482  }
483 
484  /* For each papi profdescs entry, append sprofil()-specific info */
485  if (HPC_GET_PAPIPROFS(hpc_profdesc)) {
487  (sharedprofdesc) ? HPC_GET_PAPIPROFS(sharedprofdesc) : NULL;
489  rtloadmap, sh);
490  }
491 
492  /* Restart profiling */
493  if (HPC_GET_SYSPROFS(hpc_profdesc)) {
494  start_sysprof(HPC_GET_SYSPROFS(hpc_profdesc));
495  }
496  if (HPC_GET_PAPIPROFS(hpc_profdesc)) {
498  }
499  if (opt_debug >= 1) { MSG0(stderr, "*** dlopen handling complete ***"); }
500 }
501 
502 
503 /*
504  * Prepare profiling for this thread of execution. N.B.: the caller
505  * must keep the returned data structure safe! (The boolean argument
506  * 'is_thread' refers to whether we are in an actual thread, i.e. not
507  * simply a the execution of a process.)
508  */
509 extern hpcrun_profiles_desc_t*
510 init_thread(int is_thread)
511 {
512  hpcrun_profiles_desc_t* profdesc = NULL, *sharedprofdesc = NULL;
513 
514  if (opt_debug >= 1) { MSG0(stderr, "*** init_thread ***"); }
515 
516  /* Create profile info from event list and perform error checking. */
517  if (is_thread && opt_thread == HPCRUN_THREADPROF_ALL) {
518  sharedprofdesc = hpc_profdesc; /* share the histogram buffers */
519  }
520  init_profdesc(&profdesc, numSysEvents, numPAPIEvents, rtloadmap,
521  sharedprofdesc);
522 
523 #if (OPEN_OUTPUTFILE_AT_BEG)
524  /* Init file info if necessary. */
525  init_profdesc_ofile(profdesc, (sharedprofdesc != NULL));
526  notify_ofile(profdesc, sharedprofdesc);
527 #endif
528 
529  /* Init signal handlers */
531 
532  /* Launch profilers */
533  if (HPC_GET_SYSPROFS(profdesc)) {
534  start_sysprof(HPC_GET_SYSPROFS(profdesc));
535  }
536  if (HPC_GET_PAPIPROFS(profdesc)) {
537  if (opt_debug >= 3) {
539  }
541  }
542 
543  return profdesc;
544 }
545 
546 
547 static void
548 count_events(uint* sysEvents, uint* papiEvents)
549 {
550  char* tok, *tmp_eventlist;
551 
552  /* note: arguments must not be NULL */
553  *sysEvents = 0;
554  *papiEvents = 0;
555 
556  /* note: strtok() will destroy the string so we use strdup */
557  tmp_eventlist = strdup(opt_eventlist);
558  for (tok = strtok(tmp_eventlist, ";"); (tok != NULL);
559  tok = strtok((char*)NULL, ";")) {
560  /* There may be a ':' within 'tok'... */
561  if ( (strncmp(tok, HPCRUN_EVENT_WALLCLK_STR,
563  (strncmp(tok, HPCRUN_EVENT_FWALLCLK_STR,
564  HPCRUN_EVENT_FWALLCLK_STRLN) == 0) ) {
565  (*sysEvents)++;
566  }
567  else {
568  (*papiEvents)++;
569  }
570  }
571  free(tmp_eventlist);
572 }
573 
574 
575 static void
577  uint numSysEv, uint numPapiEv, rtloadmap_t* rtmap,
578  hpcrun_profiles_desc_t* sharedprofdesc)
579 {
580  /* PAPI should already be initialized if necessary */
581 
582  int xprofidx = -1, yprofidx = -1; /* nth prof event for x/y */
583  const uint eventbufSZ = 128; /* really the last index, not the size */
584  char eventbuf[eventbufSZ+1];
585  char* tok, *tmp_eventlist;
586  int rval, i;
587 
588  if (opt_debug >= 1) {
589  MSG0(stderr, "Initializing profile descriptors");
590  MSGx(stderr, " Found %d sys events and %d PAPI events",
591  numSysEv, numPapiEv);
592  }
593 
594  /* 1a. Ensure we do not profile both system and PAPI events. */
595  if (numSysEv > 0 && numPapiEv > 0) {
596  DIE0("Cannot profile both WALLCLK and PAPI events at the same time. (Both use SIGPROF.)");
597  }
598 
599  /* 1b. Ensure no more than one wall clock event is profiled. (Only
600  one appropriate itimer (ITIMER_PROF) is provided per process.) */
601  if (numSysEv > 1) {
602  numSysEv = 1;
603  }
604 
605  /* 1c. Ensure that we do not use system profile with threads */
606  if (numSysEv > 0 && opt_thread) {
607  DIE0("Cannot profile WALLCLK on multithreaded process. (sprofil() limitation.)");
608  }
609 
610  /* 1d. Ensure we have enough hardware counters if using PAPI. Note:
611  PAPI cannot profile when using multiplexing. */
612  {
613  int numHwCntrs = PAPI_num_hwctrs();
614  if (numPapiEv > numHwCntrs) {
615  MSGx(stderr, "warning: Too many events (%d) for hardware counters (%d). Only using first %d events.", numPapiEv, numHwCntrs, numHwCntrs);
616  numPapiEv = numHwCntrs;
617  }
618  }
619 
620 
621  /* 2a. Initialize profdesc */
623  if (!(*profdesc)) { DIE0("error: malloc() failed!"); }
624  memset(*profdesc, 0x00, sizeof(hpcrun_profiles_desc_t));
625 
626  /* 2b. Initialize system profdescs */
627  if (numSysEv > 0) {
628  uint vecsz, sz = sizeof(hpcsys_profile_desc_vec_t);
629 
631  if (!HPC_GET_SYSPROFS(*profdesc)) {
632  DIE0("error: malloc() failed!");
633  }
634 
635  vecsz = sizeof(hpcsys_profile_desc_t) * numSysEv;
636  HPC_GET_SYSPROFS(*profdesc)->size = numSysEv;
637 
638  HPC_GET_SYSPROFS(*profdesc)->vec = (hpcsys_profile_desc_t*)malloc(vecsz);
639  if (!HPC_GET_SYSPROFS(*profdesc)->vec) {
640  DIE0("error: malloc() failed!");
641  }
642  memset(HPC_GET_SYSPROFS(*profdesc)->vec, 0x00, vecsz);
643  }
644 
645  /* 2c. Initialize papi profdescs */
646  if (numPapiEv > 0) {
647  uint vecsz, sz = sizeof(hpcpapi_profile_desc_vec_t);
648 
650  if (!HPC_GET_PAPIPROFS(*profdesc)) {
651  DIE0("error: malloc() failed!");
652  }
653 
654  vecsz = sizeof(hpcpapi_profile_desc_t) * numPapiEv;
655  HPC_GET_PAPIPROFS(*profdesc)->size = numPapiEv;
656 
657  HPC_GET_PAPIPROFS(*profdesc)->vec = (hpcpapi_profile_desc_t*)malloc(vecsz);
658  if (!HPC_GET_PAPIPROFS(*profdesc)->vec) {
659  DIE0("error: malloc() failed!");
660  }
661  memset(HPC_GET_PAPIPROFS(*profdesc)->vec, 0x00, vecsz);
662 
663  HPC_GET_PAPIPROFS(*profdesc)->eset = PAPI_NULL;
664  rval = PAPI_create_eventset(&HPC_GET_PAPIPROFS(*profdesc)->eset);
665  if (rval != PAPI_OK) {
666  DIEx("error: PAPI_create_eventset (%d): %s.", rval, PAPI_strerror(rval));
667  }
668  }
669 
670 
671  /* 3. For each event:period pair, init corresponding profdescs
672  entry. Classification of events *must* be the same as count_events(). */
673  tmp_eventlist = strdup(opt_eventlist);
674  tok = strtok(tmp_eventlist, ";");
675  for (i = 0; (tok != NULL); i++, tok = strtok((char*)NULL, ";")) {
676  uint64_t period = 0;
677  char* dlm;
678  uint evty = 0; /* 1 is system; 2 is papi */
679 
680  // Extract event field from token.
681  // 'dlm' points to the optional period delimiter (a colon), if
682  // available; search from the end of the string in case the event
683  // name itself has colon.
684  dlm = strrchr(tok, ':');
685  if (dlm) {
686  if (isdigit(dlm[1])) { // assume this is the period
687  uint len = MIN(dlm - tok, eventbufSZ);
688  strncpy(eventbuf, tok, len);
689  eventbuf[len] = '\0';
690  }
691  else {
692  dlm = NULL; // it's not the period; fall through
693  }
694  }
695  if (!dlm) { // the fall through, not the 'else'!
696  strncpy(eventbuf, tok, eventbufSZ);
697  eventbuf[eventbufSZ] = '\0';
698  }
699 
700  /* Determine the event type */
701  if ( (strcmp(eventbuf, HPCRUN_EVENT_WALLCLK_STR) == 0) ||
702  (strcmp(eventbuf, HPCRUN_EVENT_FWALLCLK_STR) == 0) ) {
703  evty = 1;
704  }
705  else {
706  evty = 2;
707  }
708 
709  // Extract period field from token
710  if (dlm) {
711  period = strtol(dlm+1, (char **)NULL, 10);
712  }
713  else if (evty == 1) {
714  period = 0;
715  }
716  else if (evty == 2) {
717  period = default_period;
718  }
719 
720  if (opt_debug >= 1) {
721  MSGx(stderr, " Event: '%s' (%d) '%"PRIu64"'", eventbuf, evty, period);
722  }
723 
724  /* Add the event to the appropriate place */
725  if (evty == 1) {
726  xprofidx++;
727  add_sysevent(HPC_GET_SYSPROFS(*profdesc), rtmap, xprofidx,
728  eventbuf, period);
729  }
730  else if (evty == 2) {
731  yprofidx++;
732  add_papievent(HPC_GET_PAPIPROFS(*profdesc), rtmap, yprofidx,
733  eventbuf, period);
734  }
735  else {
736  DIE0("error: internal programming error - invalid event.");
737  }
738  }
739  free(tmp_eventlist);
740 
741  /* N.B.: at this point x->sprofs an1d (*y)->sprofs remains uninitialized */
742 
743  /* 4a. For each sys profdescs entry, init sprofil()-specific info */
744  if (HPC_GET_SYSPROFS(*profdesc)) {
746  (sharedprofdesc) ? HPC_GET_SYSPROFS(sharedprofdesc) : NULL;
747  init_sysprofdesc_buffer(HPC_GET_SYSPROFS(*profdesc), numSysEv, rtmap, sh);
748  }
749 
750  /* 4b. For each papi profdescs entry, init sprofil()-specific info */
751  if (HPC_GET_PAPIPROFS(*profdesc)) {
753  (sharedprofdesc) ? HPC_GET_PAPIPROFS(sharedprofdesc) : NULL;
754  init_papiprofdesc_buffer(HPC_GET_PAPIPROFS(*profdesc), numPapiEv, rtmap,
755  sh);
756  }
757 }
758 
759 
760 static void
762  uint numEv, rtloadmap_t* rtmap,
763  hpcsys_profile_desc_vec_t* sharedprofdesc)
764 {
765  int i;
766 
767  for (i = 0; i < numEv; ++i) {
768  int mapi;
769  uint sprofbufsz = sizeof(struct prof) * rtmap->count;
770  hpcsys_profile_desc_t* prof = &profdesc->vec[i];
771 
772  if (sharedprofdesc) {
773  prof->sprofs = sharedprofdesc->vec[i].sprofs;
774  prof->numsprofs = sharedprofdesc->vec[i].numsprofs;
775  }
776  else {
777  prof->sprofs = (struct prof*)malloc(sprofbufsz);
778  if (!prof->sprofs) { DIE0("error: malloc() failed!"); }
779  memset(prof->sprofs, 0x00, sprofbufsz);
780  prof->numsprofs = rtmap->count;
781  }
782 
783  if (opt_debug >= 4) {
784  MSGx(stderr, "profile buffer details for %s:", prof->ename);
785  MSGx(stderr, " count = %d, sp=%"PRIu64" ef=%d",
786  prof->numsprofs, prof->period, prof->flags);
787  }
788 
789  if (sharedprofdesc) {
790  /* print msg */
791  }
792  else {
793  for (mapi = 0; mapi < rtmap->count; ++mapi) {
794  uint bufsz;
795  uint ncntr;
796 
797  /* eliminate use of ceil() (link with libm) by adding 1 */
798  ncntr = (rtmap->module[mapi].length / prof->bytesPerCodeBlk) + 1;
799  bufsz = ncntr * prof->bytesPerCntr;
800 
801  /* buffer base and size */
802  prof->sprofs[mapi].pr_base = (void*)malloc(bufsz);
803  prof->sprofs[mapi].pr_size = bufsz;
804  if (!prof->sprofs[mapi].pr_base) {
805  DIE0("error: malloc() failed!");
806  }
807  memset(prof->sprofs[mapi].pr_base, 0x00, bufsz);
808 
809  /* pc offset and scaling factor */
810  prof->sprofs[mapi].pr_off = rtmap->module[mapi].offset;
811  prof->sprofs[mapi].pr_scale = prof->scale;
812 
813  if (opt_debug >= 4) {
814  /* 'pr_size'/'pr_off' are of type 'size_t' which is of pointer size */
815  MSGx(stderr, "\tprofile[%d] base = %p size = %#"PRIxPTR" off = %#"PRIxPTR" scale = %#lx",
816  mapi, prof->sprofs[mapi].pr_base, prof->sprofs[mapi].pr_size,
817  prof->sprofs[mapi].pr_off, prof->sprofs[mapi].pr_scale);
818  }
819  }
820  }
821  }
822 }
823 
824 static void
826  uint numEv, rtloadmap_t* rtmap,
827  hpcsys_profile_desc_vec_t* sharedprofdesc)
828 {
829  int i;
830 
831  for (i = 0; i < numEv; ++i) {
832  int mapi;
833  uint sprofbufsz = sizeof(struct prof) * rtmap->count;
834  hpcsys_profile_desc_t* prof = &profdesc->vec[i];
835  uint oldcount = prof->numsprofs;
836 
837  if (!sharedprofdesc) {
838  prof->sprofs = (struct prof*)realloc(prof->sprofs, sprofbufsz);
839  if (!prof->sprofs) { DIE0("error: realloc() failed!"); }
840  memset(&(prof->sprofs[oldcount]), 0x00, sprofbufsz-(oldcount*sizeof(PAPI_sprofil_t)));
841  prof->numsprofs = rtmap->count;
842  }
843 
844  if (opt_debug >= 4) {
845  MSGx(stderr, "profile buffer details for %s:", prof->ename);
846  MSGx(stderr, " count = %d, sp=%"PRIu64" ef=%d",
847  prof->numsprofs, prof->period, prof->flags);
848  }
849 
850  if (sharedprofdesc) {
851  /* print msg */
852  }
853  else {
854  for (mapi = oldcount; mapi < rtmap->count; ++mapi) {
855  uint bufsz;
856  uint ncntr;
857 
858  /* eliminate use of ceil() (link with libm) by adding 1 */
859  ncntr = (rtmap->module[mapi].length / prof->bytesPerCodeBlk) + 1;
860  bufsz = ncntr * prof->bytesPerCntr;
861 
862  /* buffer base and size */
863  prof->sprofs[mapi].pr_base = (void*)malloc(bufsz);
864  prof->sprofs[mapi].pr_size = bufsz;
865  if (!prof->sprofs[mapi].pr_base) {
866  DIE0("error: malloc() failed!");
867  }
868  memset(prof->sprofs[mapi].pr_base, 0x00, bufsz);
869 
870  /* pc offset and scaling factor */
871  prof->sprofs[mapi].pr_off = rtmap->module[mapi].offset;
872  prof->sprofs[mapi].pr_scale = prof->scale;
873 
874  if (opt_debug >= 4) {
875  /* 'pr_size'/'pr_off' are of type 'size_t' which is of pointer size */
876  MSGx(stderr, "\tprofile[%d] base = %p size = %#"PRIxPTR" off = %#"PRIxPTR" scale = %#lx",
877  mapi, prof->sprofs[mapi].pr_base, prof->sprofs[mapi].pr_size,
878  prof->sprofs[mapi].pr_off, prof->sprofs[mapi].pr_scale);
879  }
880  }
881  }
882  }
883 }
884 
885 static void
887  uint numEv, rtloadmap_t* rtmap,
888  hpcpapi_profile_desc_vec_t* sharedprofdesc)
889 {
890  int i;
891 
892  for (i = 0; i < numEv; ++i) {
893  int mapi;
894  uint sprofbufsz = sizeof(PAPI_sprofil_t) * rtmap->count;
895  hpcpapi_profile_desc_t* prof = &profdesc->vec[i];
896 
897  if (sharedprofdesc) {
898  prof->sprofs = sharedprofdesc->vec[i].sprofs;
899  prof->numsprofs = sharedprofdesc->vec[i].numsprofs;
900  }
901  else {
902  prof->sprofs = (PAPI_sprofil_t*)malloc(sprofbufsz);
903  if (!prof->sprofs) { DIE0("error: malloc() failed!"); }
904  memset(prof->sprofs, 0x00, sprofbufsz);
905  prof->numsprofs = rtmap->count;
906 
907  }
908 
909  if (opt_debug >= 4) {
910  MSGx(stderr, "profile buffer details for %s:", prof->einfo.symbol);
911  MSGx(stderr, " count = %d, es=%#x ec=%#x sp=%"PRIu64" ef=%d",
912  prof->numsprofs, profdesc->eset,
913  prof->ecode, prof->period, prof->flags);
914  }
915 
916  if (sharedprofdesc) {
917  /* print msg */
918  }
919  else {
920  for (mapi = 0; mapi < rtmap->count; ++mapi) {
921  uint bufsz;
922  uint ncntr;
923 
924  /* eliminate use of ceil() (link with libm) by adding 1 */
925  ncntr = (rtmap->module[mapi].length / prof->bytesPerCodeBlk) + 1;
926  bufsz = ncntr * prof->bytesPerCntr;
927 
928  /* buffer base and size */
929  prof->sprofs[mapi].pr_base = (void*)malloc(bufsz);
930  prof->sprofs[mapi].pr_size = bufsz;
931  if (!prof->sprofs[mapi].pr_base) {
932  DIE0("error: malloc() failed!");
933  }
934  memset(prof->sprofs[mapi].pr_base, 0x00, bufsz);
935 
936  /* pc offset and scaling factor (note: 'caddr_t' is a 'void*') */
937  prof->sprofs[mapi].pr_off =
938  (caddr_t)(uintptr_t)rtmap->module[mapi].offset;
939  prof->sprofs[mapi].pr_scale = prof->scale;
940 
941  if (opt_debug >= 4) {
942  MSGx(stderr,
943  "\tprofile[%d] base = %p size = %#x off = %p scale = %#x",
944  mapi, prof->sprofs[mapi].pr_base, prof->sprofs[mapi].pr_size,
945  prof->sprofs[mapi].pr_off, prof->sprofs[mapi].pr_scale);
946  }
947  }
948  }
949  }
950 }
951 
952 static void
954  uint numEv, rtloadmap_t* rtmap,
955  hpcpapi_profile_desc_vec_t* sharedprofdesc)
956 {
957  int i;
958 
959  for (i = 0; i < numEv; ++i) {
960  int mapi;
961  uint sprofbufsz = sizeof(PAPI_sprofil_t) * rtmap->count;
962  hpcpapi_profile_desc_t* prof = &profdesc->vec[i];
963  uint oldcount = prof->numsprofs;
964 
965  if (!sharedprofdesc) {
966  prof->sprofs = (PAPI_sprofil_t*)realloc(prof->sprofs, sprofbufsz);
967  if (!prof->sprofs) { DIE0("error: realloc() failed!"); }
968  memset(&(prof->sprofs[oldcount]), 0x00, sprofbufsz-(oldcount*sizeof(PAPI_sprofil_t)));
969  prof->numsprofs = rtmap->count;
970  }
971 
972  if (opt_debug >= 4) {
973  MSGx(stderr, "profile buffer details for %s:", prof->einfo.symbol);
974  MSGx(stderr, " count = %d, es=%#x ec=%#x sp=%"PRIu64" ef=%d",
975  prof->numsprofs, profdesc->eset,
976  prof->ecode, prof->period, prof->flags);
977  }
978 
979  if (sharedprofdesc) {
980  /* print msg */
981  }
982  else {
983  for (mapi = oldcount; mapi < rtmap->count; ++mapi) {
984  uint bufsz;
985  uint ncntr;
986 
987  /* eliminate use of ceil() (link with libm) by adding 1 */
988  ncntr = (rtmap->module[mapi].length / prof->bytesPerCodeBlk) + 1;
989  bufsz = ncntr * prof->bytesPerCntr;
990 
991  /* buffer base and size */
992  prof->sprofs[mapi].pr_base = (void*)malloc(bufsz);
993  prof->sprofs[mapi].pr_size = bufsz;
994  if (!prof->sprofs[mapi].pr_base) {
995  DIE0("error: malloc() failed!");
996  }
997  memset(prof->sprofs[mapi].pr_base, 0x00, bufsz);
998 
999  /* pc offset and scaling factor (note: 'caddr_t' is a 'void*') */
1000  prof->sprofs[mapi].pr_off =
1001  (caddr_t)(uintptr_t)rtmap->module[mapi].offset;
1002  prof->sprofs[mapi].pr_scale = prof->scale;
1003 
1004  if (opt_debug >= 4) {
1005  MSGx(stderr,
1006  "\tprofile[%d] base = %p size = %#x off = %p scale = %#x",
1007  mapi, prof->sprofs[mapi].pr_base, prof->sprofs[mapi].pr_size,
1008  prof->sprofs[mapi].pr_off, prof->sprofs[mapi].pr_scale);
1009  }
1010  }
1011  }
1012  }
1013 
1014  //dump_hpcpapi_profile_desc_vec(HPC_GET_PAPIPROFS(profdesc));
1015 }
1016 
1017 
1018 // This function checks the existence of path,
1019 // if it doesn't exist, 0 is returned, else, the
1020 // next available generation is returned
1021 static int get_next_gen(const char *path) {
1022  struct stat buf;
1023  char tmp_path[PATH_MAX];
1024  strcpy(tmp_path, path);
1025  int rc = stat(tmp_path, &buf);
1026  if ((rc<0) && (errno==ENOENT)) return 0;
1027  int inst = 0;
1028  do {
1029  inst++;
1030  strcpy(tmp_path, path);
1031  sprintf(tmp_path, "%s.%d", path, inst);
1032  rc = stat(tmp_path, &buf);
1033  } while (!((rc<0) && (errno==ENOENT)));
1034  return inst;
1035 }
1036 
1037 
1038 static void
1039 init_profdesc_ofile(hpcrun_profiles_desc_t* profdesc, int sharedprofdesc)
1040 {
1041  /* Perform a filesystem test to make sure we will be able to write
1042  output data. */
1043 
1044  static uint outfilenmLen = PATH_MAX; /* never redefined */
1045  static uint hostnmLen = 128; /* never redefined */
1046  char outfilenm[outfilenmLen];
1047  char hostnm[hostnmLen];
1048  const char* cmd = hpcrun_cmd;
1049  char* slash = NULL;
1050  //uint numEvents = 0;
1051  //char* event = NULL;
1052  FILE* fs;
1053 
1054  if (sharedprofdesc) {
1055  profdesc->ofile.fs = NULL;
1056  profdesc->ofile.fname = NULL;
1057  return;
1058  }
1059 
1060 
1061  /* Get components for constructing file name:
1062  <outpath>/<command>.hpcrun.<hostname>.<pid>.<tid> */
1063 
1064  /* <command> */
1065  slash = rindex(cmd, '/');
1066  if (slash) {
1067  cmd = slash + 1; /* basename of cmd */
1068  }
1069 
1070 #if 0
1071  /* <event1> */
1072  if (HPC_GET_SYSPROFS(profdesc)) {
1073  numEvents += HPC_GET_SYSPROFS(profdesc)->size;
1074  event = HPC_GET_SYSPROFS(profdesc)->vec[0].ename;
1075  }
1076  if (!event && HPC_GET_PAPIPROFS(profdesc)) {
1077  numEvents += HPC_GET_PAPIPROFS(profdesc)->size;
1078  event = HPC_GET_PAPIPROFS(profdesc)->vec[0].einfo.symbol; /* first name */
1079  }
1080 #endif
1081 
1082  /* <hostname> */
1083  gethostname(hostnm, hostnmLen);
1084  hostnm[hostnmLen-1] = '\0'; /* ensure NULL termination */
1085 
1086  /* Create file name */
1087  snprintf(outfilenm, outfilenmLen, "%s/%s%s."HPCRUN_NAME".%s.%d.0x%lx",
1088  opt_outpath, opt_prefix, cmd, hostnm, getpid(), hpcrun_gettid());
1089 
1090  /* Use a generation suffix if file exists */
1091  if (strlen(opt_file) != 0) {
1092  /* If user has supplied an output filename use that overrides the
1093  setting above */
1094  int inst = get_next_gen(opt_file);
1095  if (inst) {
1096  snprintf(outfilenm, outfilenmLen, "%s.%d", opt_file, inst);
1097  }
1098  else {
1099  strncpy(outfilenm, opt_file, outfilenmLen);
1100  }
1101  }
1102  else {
1103  int inst = get_next_gen(outfilenm);
1104  if (inst) {
1105  snprintf(opt_file, outfilenmLen, "%s.%d", outfilenm, inst);
1106  strncpy(outfilenm, opt_file, outfilenmLen);
1107  }
1108  }
1109 
1110 
1111  profdesc->ofile.fs = NULL;
1112  profdesc->ofile.fname = (char*)malloc(strlen(outfilenm)+1);
1113  if (!profdesc->ofile.fname) { DIE0("error: malloc() failed!"); }
1114  strcpy(profdesc->ofile.fname, outfilenm);
1115 
1116  /* Test whether we can write to this filesystem */
1117  do {
1118  if (opt_debug >= 1 && (errno == ENFILE || errno == EMFILE)) {
1119  MSG0(stderr, "* waiting for file descriptors to test filesystem!");
1120  }
1121  errno = 0;
1122  fs = fopen(outfilenm, "w");
1123  }
1124  while (errno == ENFILE || errno == EMFILE /* too many open files */);
1125 
1126  if (fs == NULL) {
1127  DIEx("error: Filesystem test failed (cannot open file '%s'): %s",
1128  outfilenm, strerror(errno));
1129  }
1130  fclose(fs);
1131 }
1132 
1133 
1134 static void
1136  hpcrun_profiles_desc_t* sharedprofdesc)
1137 {
1138  /* Let user know about output file */
1139  const char* out_fname = profdesc->ofile.fname;
1140  const char* out_sfx = "";
1141  if (!out_fname) {
1142  out_fname = sharedprofdesc->ofile.fname;
1143  out_sfx = " (SHARED)";
1144  }
1145  MSGx(stderr, "Using output file %s%s\n", out_fname, out_sfx);
1146 }
1147 
1148 
1149 
1150 static void
1152  int profidx, char* eventnm, uint64_t period)
1153 {
1154  /* Cf. the notes below on PAPI_sprofil(). As is presented below,
1155 
1156  scale = ( scaleval / 65536 ) = ( bh / b )
1157 
1158  In contrast to the below bh is not fixed at 2 but actually
1159  represents the size of histogram buckets (which leads to lost
1160  profiling resolution).
1161 
1162  Some sample scale values, when bh is 4.
1163 
1164  scaleval bytes_per_code_block (b)
1165  ----------------------------------------
1166  0x10000 (or 0xffff) 4 (size of many RISC instructions)
1167  0x8000 8
1168  0x4000 16 (size of Itanium instruction packet)
1169  */
1170 
1171  hpcsys_profile_desc_t* prof = NULL;
1172 
1173  if (profidx >= profdescs->size) {
1174  /* Assumes that the only system event is wallclock time */
1175  DIE0("error: Only one wallclock event may be profiled at a time.");
1176  }
1177 
1178  prof = &(profdescs->vec[profidx]);
1179 
1180  /* Find event */
1181  if (strcmp(eventnm, HPCRUN_EVENT_WALLCLK_STR) == 0) {
1183  prof->flags = 0;
1184  prof->period = 1; /* 1 millisecond (not 10!); discovered empirically */
1185  }
1186  else if (strcmp(eventnm, HPCRUN_EVENT_FWALLCLK_STR) == 0) {
1188  prof->flags = PROF_FAST;
1189  prof->period = 1; /* should be 1 ms; cf. /usr/include/sys/profile.h */
1190  }
1191  else {
1192  DIEx("error: Invalid event: '%s'.", eventnm);
1193  }
1194 
1195  /* Profiling period (already set) */
1196  if (period != 0) {
1197  DIEx("error: Invalid period %"PRIu64" for event '%s'.",
1198  period, eventnm);
1199  }
1200 
1201  /* Profiling flags */
1202  prof->flags |= PROF_UINT; /* hpc_hist_bucket */
1203 
1204  prof->bytesPerCntr = sizeof(hpc_hist_bucket); /* 4 */
1205  prof->bytesPerCodeBlk = 4;
1206  prof->scale = 0x10000;
1207 
1208  if ((prof->scale * prof->bytesPerCodeBlk) != (65536 * prof->bytesPerCntr)) {
1209  DIE0("error: internal programming error - invalid profiling scale.");
1210  }
1211 }
1212 
1213 
1214 static void
1216 {
1217  int ecode;
1218 
1219  /* Note: should only be one profdesc! */
1220  hpcsys_profile_desc_t* prof = &profdescs->vec[0];
1221 
1222  if (opt_debug >= 1) { MSGx(stderr, "Calling sprofil(): %s", prof->ename); }
1223 
1224  ecode = sprofil(prof->sprofs, prof->numsprofs, NULL, prof->flags);
1225  if (ecode != 0) {
1226  DIEx("error: sprofil() error. %s.", strerror(errno));
1227  }
1228 }
1229 
1230 
1231 static void
1233 {
1234  int rval;
1235 
1236  /* Initialize papi: hpc_init_papi_force() *must* be used for forks();
1237  it works for non-forks also. */
1238  if (hpc_init_papi_force(PAPI_library_init) != 0) {
1239  exit(1); /* error already printed */
1240  }
1241 
1242  /* set PAPI debug */
1243  if (opt_debug >= 1) {
1244  MSG0(stderr, "setting PAPI debug!");
1245  rval = PAPI_set_debug(PAPI_VERB_ECONT);
1246  if (rval != PAPI_OK) {
1247  DIEx("error: PAPI_set_debug (%d): %s.", rval, PAPI_strerror(rval));
1248  }
1249  }
1250 
1251  /* PAPI_set_domain(PAPI_DOM_ALL); */
1252  if (domain == 0) {
1253  domain = PAPI_DOM_USER;
1254  }
1255  if (opt_debug >= 1) {
1256  MSGx(stderr, "Setting PAPI domain to: %d", domain);
1257  }
1258  rval = PAPI_set_domain(domain);
1259  if (rval != PAPI_OK) {
1260  DIEx("error: PAPI_set_domain (%d): %s.", rval, PAPI_strerror(rval));
1261  }
1262 
1263 
1264 #ifndef HAVE_MONITOR
1266 #endif
1267 }
1268 
1269 
1270 static void
1272  int profidx, char* eventnm, uint64_t period)
1273 {
1274  /* Note on hpcpapi_profile_desc_t and PAPI_sprofil() scaling factor
1275  cf. man profil() or sprofil()
1276 
1277  The scale factor describes how the histogram buffer and each
1278  histogram counter correlates with the region to be profiled.
1279 
1280  The region to be profiled can be thought of as being divided into
1281  n equally sized blocks, each b bytes long. For historical
1282  reasons, we introduce a term, bh, representing the size in bytes
1283  of each histogram counter. The value of the scale factor is the
1284  reciprocal of (b / bh):
1285  scale = reciprocal( b / bh )
1286  Note that now bh is *fixed* at 2.
1287 
1288  Since this scheme was devised when a memory word was 16-bits or
1289  2-bytes, the scale factor was represented as a 16-bit fixed-point
1290  fraction with the decimal point implied on the *left*. Under
1291  this representation, the maximum value of the scale was 0xffff
1292  (essentially 1, 0x10000); this is *no longer* the case.
1293 
1294  Alternatively, and perhaps more conveniently, the scale can be
1295  thought of as a ratio between an unsigned integer scaleval and
1296  65536:
1297  scale = ( scaleval / 65536 ) = ( bh / b )
1298 
1299  Some sample scale values, given that bh is fixed at 2.
1300 
1301  scaleval bytes_per_code_block (b)
1302  ----------------------------------------
1303  0x20000 1 (x86 insns may begin at any byte)
1304  0x10000 (or 0xffff) 2
1305  0x8000 4 (size of many RISC instructions)
1306  0x4000 8
1307  0x2000 16 (size of Itanium instruction packet)
1308 
1309 
1310  Using this second notation, we can show the relation between the
1311  histogram counters and the region to profile. The histogram
1312  counter that will be incremented for an interrupt at program
1313  counter pc is:
1314  histogram[ ((pc - load_offset)/bh) * (scaleval/65536) ]
1315 
1316  The number of counters in the histogram should equal the number
1317  of blocks in the region to be profiled. */
1318 
1319  int rval;
1320  hpcpapi_profile_desc_t* prof = NULL;
1321 
1322  if (!profdescs) {
1323  DIE0("error: internal programming error.");
1324  }
1325 
1326  if (profidx >= profdescs->size) {
1327  MSGx(stderr, "warning: Ignoring event '%s:%"PRIu64"'.", eventnm, period);
1328  return;
1329  }
1330 
1331  prof = &(profdescs->vec[profidx]);
1332 
1333  /* Find event info, ensuring it is available. Note: it is
1334  necessary to do a query_event *and* get_event_info. Sometimes
1335  the latter will return info on an event that does not exist. */
1336  rval = PAPI_event_name_to_code(eventnm, &prof->ecode);
1337  if (rval != PAPI_OK) {
1338  DIEx("error: Event '%s' is not recognized.\n"
1339  "\tCheck the list of supported events with `"HPCRUN_NAME" -L'.",
1340  eventnm);
1341  }
1342  rval = PAPI_query_event(prof->ecode);
1343  if (rval != PAPI_OK) {
1344  DIEx("error: Event '%s' is not supported on this platform.\n"
1345  "\tCheck the list of supported events with `"HPCRUN_NAME" -L'.",
1346  eventnm);
1347  }
1348  rval = PAPI_get_event_info(prof->ecode, &prof->einfo);
1349  if (rval != PAPI_OK) {
1350  DIEx("error: PAPI_get_event_info (%d): %s.", rval, PAPI_strerror(rval));
1351  }
1352 
1353  /* NOTE: Although clumsy, this test has official sanction. */
1354  if ((prof->ecode & PAPI_PRESET_MASK) && (prof->einfo.count > 1) &&
1355  strcmp(prof->einfo.derived, "DERIVED_CMPD") != 0) {
1356  DIEx("error: '%s' is a PAPI derived event.\n"
1357  "\tSampling of derived events is not supported by PAPI.\n"
1358  "\tUse `"HPCRUN_NAME" -L' to find the component native events of '%s' that you can monitor separately.", eventnm, eventnm);
1359  }
1360 
1361  rval = PAPI_add_event(profdescs->eset, prof->ecode);
1362  if (rval != PAPI_OK) {
1363  DIEx("error: (%d) Unable to add event '%s' to event set.\n"
1364  "\tPAPI_add_event %s.", rval, eventnm, PAPI_strerror(rval));
1365  }
1366 
1367  /* Profiling period */
1368  if (period == 0) {
1369  DIEx("error: Invalid period %"PRIu64" for event '%s'.",
1370  period, eventnm);
1371  }
1372  prof->period = period;
1373 
1374  /* Profiling flags */
1375  prof->flags = opt_flagscode;
1376  prof->flags |= PAPI_PROFIL_BUCKET_32; /* hpc_hist_bucket */
1377 
1378  prof->bytesPerCntr = sizeof(hpc_hist_bucket); /* 4 */
1379  prof->bytesPerCodeBlk = 4;
1380  prof->scale = 0x8000;
1381 
1382  if ( (prof->scale * prof->bytesPerCodeBlk) != (65536 * 2) ) {
1383  DIE0("error: internal programming error - invalid profiling scale.");
1384  }
1385 }
1386 
1387 
1388 static void
1390 {
1391  int rval;
1392  int i;
1393 
1394  if (!profdescs) { return; }
1395 
1396  /* Note: PAPI_sprofil() can profile only one event in an event set,
1397  though this function may be called on other events in the *same*
1398  event set to profile multiple events simultaneously. The event
1399  set must be shared since PAPI will run only one event set at a
1400  time (PAPI_start()). */
1401 
1402  /* 1. Prepare PAPI subsystem for profiling */
1403  for (i = 0; i < profdescs->size; ++i) {
1404  hpcpapi_profile_desc_t* prof = &profdescs->vec[i];
1405 
1406  if (opt_debug >= 1) {
1407  MSGx(stderr, "Calling PAPI_sprofil(): %s", prof->einfo.symbol);
1408  }
1409 
1410  rval = PAPI_sprofil(prof->sprofs, prof->numsprofs, profdescs->eset,
1411  prof->ecode, prof->period, prof->flags);
1412  if (rval != PAPI_OK) {
1413  DIEx("error: PAPI_sprofil (%d): %s.", rval, PAPI_strerror(rval));
1414  }
1415  }
1416 
1417  /* 2. Launch PAPI */
1418  rval = PAPI_start(profdescs->eset);
1419  if (rval != PAPI_OK) {
1420  DIEx("error: PAPI_start (%d): %s.", rval, PAPI_strerror(rval));
1421  }
1422 }
1423 
1424 
1425 static void init_sighandler(int sig);
1426 
1427 static void
1429 {
1430  init_sighandler(SIGINT); /* Ctrl-C */
1431  init_sighandler(SIGABRT); /* abort() */
1432 }
1433 
1434 
1435 static void
1437 {
1438  if (signal(sig, SIG_IGN) != SIG_IGN) {
1439  signal(sig, hpcrun_sighandler);
1440  }
1441  else {
1442  MSGx(stderr, "warning: Signal %d already has a handler.", sig);
1443  }
1444 }
1445 
1446 
1447 /****************************************************************************
1448  * Finalize profiling
1449  ****************************************************************************/
1450 
1451 static void write_all_profiles(hpcrun_profiles_desc_t* profdesc,
1452  rtloadmap_t* rtmap);
1453 
1454 static void fini_papi_for_thread(hpcpapi_profile_desc_vec_t* profdescs);
1455 static void fini_papi_for_process();
1456 
1457 static void fini_profdesc(hpcrun_profiles_desc_t** profdesc,
1458  int sharedprofdesc);
1459 
1460 
1461 /*
1462  * Finalize profiling for this process. Since this routine can be
1463  * called more than once per process, ensure that it is idempotent.
1464  */
1465 extern void
1467 {
1468  static int is_finalized = 0;
1469 
1470  if (is_finalized) {
1471  if (opt_debug >= 1) { MSG0(stderr, "*** fini_process (skip) ***"); }
1472  return;
1473  }
1474 
1475  is_finalized = 1;
1476  if (opt_debug >= 1) { MSG0(stderr, "*** fini_process ***"); }
1477 
1478  fini_thread(&hpc_profdesc, 0 /*is_thread*/);
1479 
1480  if (numPAPIEvents > 0) {
1482  }
1483 }
1484 
1485 
1486 /*
1487  * Finalize profiling for this thread and free profiling data. See
1488  * init_thread() for meaning of 'is_thread'.
1489  */
1490 extern void
1491 fini_thread(hpcrun_profiles_desc_t** profdesc, int is_thread)
1492 {
1493  int sharedprofdesc = 0;
1494 
1495  if (opt_debug >= 1) { MSG0(stderr, "*** fini_thread ***"); }
1496 
1497  /* Stop profiling */
1498  if (HPC_GET_PAPIPROFS(*profdesc)) {
1500  if (opt_debug >= 3) {
1502  }
1503  }
1504  if (HPC_GET_SYSPROFS(*profdesc)) {
1505  stop_sysprof(HPC_GET_SYSPROFS(*profdesc));
1506  }
1507 
1508 
1509  if (is_thread && opt_thread == HPCRUN_THREADPROF_ALL) {
1510  sharedprofdesc = 1; /* histogram buffers are shared */
1511  }
1512 
1513  /* Write data (if necessary) */
1514 #if (!OPEN_OUTPUTFILE_AT_BEG)
1515  MSG0(stderr, "*** TST ***\n");
1516  init_profdesc_ofile(*profdesc, sharedprofdesc);
1517  notify_ofile(*profdesc, hpc_profdesc);
1518 #endif
1519  write_all_profiles(*profdesc, rtloadmap);
1520 
1521  /* Finalize profiling subsystems and uninit descriptor */
1522  if (HPC_GET_PAPIPROFS(*profdesc)) {
1524  }
1525 
1526  fini_profdesc(profdesc, sharedprofdesc);
1527 }
1528 
1529 
1530 static void
1532 {
1533  int ecode;
1534 
1535  /* Each call to sprofil will disable any profiling enabled by
1536  previous sprofil calls. */
1537  if ((ecode = sprofil(NULL, 0, NULL, 0)) != 0) {
1538 #if 0
1539  DIEx("error: sprofil() error. %s.", strerror(errno));
1540 #endif
1541  }
1542 }
1543 
1544 
1545 static void
1547 {
1548  int rval, i;
1549  long_long* values = NULL; // array the size of the eventset
1550 
1551  rval = PAPI_stop(profdescs->eset, values);
1552  if (rval != PAPI_OK) {
1553  //DIEx("error: PAPI_stop (%d): %s.", rval, PAPI_strerror(rval));
1554  }
1555 
1556  /* Call PAPI_sprofil() with a 0 threshold to cleanup internal memory */
1557  for (i = 0; i < profdescs->size; ++i) {
1558  hpcpapi_profile_desc_t* prof = &profdescs->vec[i];
1559 
1560  rval = PAPI_sprofil(prof->sprofs, prof->numsprofs, profdescs->eset,
1561  prof->ecode, 0, prof->flags);
1562  if (rval != PAPI_OK) {
1563  //DIEx("error: PAPI_sprofil (%d): %s.", rval, PAPI_strerror(rval));
1564  }
1565  }
1566 }
1567 
1568 
1569 static void
1571 {
1572  int rval;
1573  /* Error need not be fatal -- we've already got the goods! */
1574  rval = PAPI_cleanup_eventset(profdescs->eset);
1575  if (rval != PAPI_OK) {
1576  MSGx(stderr, "warning: PAPI_cleanup_eventset (%d): %s.", rval, PAPI_strerror(rval));
1577  }
1578 
1579  rval = PAPI_destroy_eventset(&profdescs->eset);
1580  if (rval != PAPI_OK) {
1581  MSGx(stderr, "warning: PAPI_destroy_eventset (%d): %s.", rval, PAPI_strerror(rval));
1582  }
1583  profdescs->eset = PAPI_NULL;
1584 
1585  /* Call PAPI_stop, PAPI_cleanup_eventset and PAPI_destroy_eventset
1586  before PAPI_unregister_thread */
1587  rval = PAPI_unregister_thread();
1588  if (rval != PAPI_OK) {
1589  MSGx(stderr, "warning: PAPI_unregister_thread (%d): %s.", rval, PAPI_strerror(rval));
1590  }
1591 }
1592 
1593 
1594 static void
1596 {
1597  PAPI_shutdown();
1598 }
1599 
1600 
1601 static void
1602 fini_profdesc(hpcrun_profiles_desc_t** profdesc, int sharedprofdesc)
1603 {
1604  int i, j;
1605  uint numSysEv = 0, numPapiEv = 0;
1606 
1607  if (!profdesc || !*profdesc) { return; }
1608 
1609  if (HPC_GET_SYSPROFS(*profdesc)) {
1610  numSysEv = HPC_GET_SYSPROFS(*profdesc)->size;
1611  }
1612  if (HPC_GET_PAPIPROFS(*profdesc)) {
1613  numPapiEv = HPC_GET_PAPIPROFS(*profdesc)->size;
1614  }
1615 
1616  /* 1a. Uninitialize system profdescs */
1617  for (i = 0; i < numSysEv; ++i) {
1618  hpcsys_profile_desc_t* prof = &HPC_GET_SYSPROFS(*profdesc)->vec[i];
1619  if (!sharedprofdesc) {
1620  for (j = 0; j < prof->numsprofs; ++j) {
1621  free(prof->sprofs[j].pr_base);
1622  }
1623  free(prof->sprofs);
1624  }
1625  prof->sprofs = NULL;
1626  }
1627 
1628  if (numSysEv > 0) {
1629  free(HPC_GET_SYSPROFS(*profdesc)->vec);
1630  free(HPC_GET_SYSPROFS(*profdesc));
1631  }
1632 
1633  /* 1b. Uninitialize papi profdescs */
1634  for (i = 0; i < numPapiEv; ++i) {
1635  hpcpapi_profile_desc_t* prof = &HPC_GET_PAPIPROFS(*profdesc)->vec[i];
1636  if (!sharedprofdesc) {
1637  for (j = 0; j < prof->numsprofs; ++j) {
1638  free(prof->sprofs[j].pr_base);
1639  }
1640  free(prof->sprofs);
1641  }
1642  prof->sprofs = NULL;
1643  }
1644 
1645  if (numPapiEv > 0) {
1646  free(HPC_GET_PAPIPROFS(*profdesc)->vec);
1647  free(HPC_GET_PAPIPROFS(*profdesc));
1648  }
1649 
1650  /* 1c. Uninitialize ofile */
1651  free((*profdesc)->ofile.fname);
1652  (*profdesc)->ofile.fname = NULL;
1653 
1654  /* 1d. Uninitialize profdesc */
1655  free(*profdesc);
1656  *profdesc = NULL;
1657 }
1658 
1659 
1660 /****************************************************************************
1661  * Write profile data
1662  ****************************************************************************/
1663 
1664 static void write_module_profile(FILE* fp, rtloadmod_desc_t* mod,
1665  hpcrun_profiles_desc_t* profdesc,
1666  int sprofidx);
1667 
1668 static void write_event_hdr(FILE *fs, char* name, char* desc,
1669  uint64_t period);
1670 static void write_sysevent_data(FILE *fs, hpcsys_profile_desc_t* prof,
1671  int sprofidx);
1672 static void write_papievent_data(FILE *fp, hpcpapi_profile_desc_t* prof,
1673  int sprofidx);
1674 static void write_event_data(FILE *fs, char* ename, hpc_hist_bucket* histo,
1675  uint64_t ncounters, uint bytesPerCodeBlk);
1676 
1677 static void write_string(FILE *fp, char *str);
1678 
1679 
1680 /*
1681  * Write profile data for this process. See hpcrun.h for file format info.
1682  */
1683 static void
1685 {
1686  int i;
1687  FILE* fs;
1688 
1689  if (opt_debug >= 1) { MSG0(stderr, "*** write_all_profiles: begin ***"); }
1690 
1691  if (!profdesc->ofile.fname) {
1692  return;
1693  }
1694 
1695  /* open the data file (wait if too many files are already open) */
1696  do {
1697  if (opt_debug >= 1 && (errno == ENFILE || errno == EMFILE)) {
1698  MSG0(stderr, "* waiting for file descriptors to write data!");
1699  }
1700  errno = 0;
1701  fs = fopen(profdesc->ofile.fname, "w");
1702  }
1703  while (errno == ENFILE || errno == EMFILE /* too many open files */);
1704 
1705  if (fs == NULL) {
1706  DIEx("error: Could not open file '%s': %s", profdesc->ofile.fname,
1707  strerror(errno));
1708  }
1709 
1710  /* <header> */
1713  fputc(HPCRUNFLAT_FMT_Endian, fs);
1714 
1715  if (opt_debug >= 1) { MSGx(stderr, "rtmap count: %d", rtmap->count); }
1716 
1717  /* <loadmodule_list> */
1718  hpcio_le4_fwrite(&(rtmap->count), fs);
1719  for (i = 0; i < rtmap->count; ++i) {
1720  write_module_profile(fs, &(rtmap->module[i]), profdesc, i);
1721  }
1722 
1723  fclose(fs);
1724 
1725  if (opt_debug >= 1) { MSG0(stderr, "*** write_all_profiles: end ***"); }
1726 }
1727 
1728 
1729 static void
1731  hpcrun_profiles_desc_t* profdesc, int sprofidx)
1732 {
1733  int i;
1734  uint numEv = 0;
1735  uint numSysEv = 0, numPapiEv = 0;
1736 
1737  if (opt_debug >= 2) {
1738  MSGx(stderr, "writing module %s (at offset %#"PRIx64")",
1739  mod->name, mod->offset);
1740  }
1741 
1742  /* <loadmodule_name>, <loadmodule_loadoffset> */
1743  write_string(fs, mod->name);
1744  hpcio_le8_fwrite(&(mod->offset), fs);
1745 
1746  /* <loadmodule_eventcount> */
1747  if (HPC_GET_SYSPROFS(profdesc)) {
1748  numSysEv = HPC_GET_SYSPROFS(profdesc)->size;
1749  numEv += numSysEv;
1750  }
1751  if (HPC_GET_PAPIPROFS(profdesc)) {
1752  numPapiEv = HPC_GET_PAPIPROFS(profdesc)->size;
1753  numEv += numPapiEv;
1754  }
1755  hpcio_le4_fwrite(&numEv, fs);
1756 
1757  /* Event data */
1758  /* <event_x_name> <event_x_description> <event_x_period> */
1759  /* <event_x_data> */
1760  for (i = 0; i < numSysEv; ++i) {
1761  hpcsys_profile_desc_t* prof = &HPC_GET_SYSPROFS(profdesc)->vec[i];
1762  write_event_hdr(fs, prof->ename, prof->ename, prof->period);
1763  write_sysevent_data(fs, prof, sprofidx);
1764  }
1765  for (i = 0; i < numPapiEv; ++i) {
1766  hpcpapi_profile_desc_t* prof = &HPC_GET_PAPIPROFS(profdesc)->vec[i];
1767  write_event_hdr(fs, prof->einfo.symbol, prof->einfo.long_descr,
1768  prof->period);
1769  write_papievent_data(fs, prof, sprofidx);
1770  }
1771 }
1772 
1773 
1774 static void
1775 write_event_hdr(FILE *fs, char* name, char* desc, uint64_t period)
1776 {
1777  /* <event_x_name> <event_x_description> <event_x_period> */
1778  write_string(fs, name);
1779  write_string(fs, desc);
1780  hpcio_le8_fwrite(&period, fs);
1781 }
1782 
1783 
1784 static void
1785 write_sysevent_data(FILE *fs, hpcsys_profile_desc_t* prof, int sprofidx)
1786 {
1787  char* ename = prof->ename;
1788  struct prof* sprof = &(prof->sprofs[sprofidx]);
1789  hpc_hist_bucket* histo = (hpc_hist_bucket*)sprof->pr_base;
1790  uint64_t ncounters = (sprof->pr_size / prof->bytesPerCntr);
1791 
1792  write_event_data(fs, ename, histo, ncounters, prof->bytesPerCodeBlk);
1793 }
1794 
1795 
1796 static void
1797 write_papievent_data(FILE *fs, hpcpapi_profile_desc_t* prof, int sprofidx)
1798 {
1799  char* ename = prof->einfo.symbol;
1800  PAPI_sprofil_t* sprof = &(prof->sprofs[sprofidx]);
1801  hpc_hist_bucket* histo = (hpc_hist_bucket*)sprof->pr_base;
1802  uint64_t ncounters = (sprof->pr_size / prof->bytesPerCntr);
1803 
1804  if (opt_debug >= 4) {
1805  MSGx(stderr, " writing %p[%d] = %p for %s with buf (%p):",
1806  prof, sprofidx, sprof, ename, histo);
1807  }
1808 
1809  write_event_data(fs, ename, histo, ncounters, prof->bytesPerCodeBlk);
1810 }
1811 
1812 
1813 static void
1814 write_event_data(FILE *fs, char* ename, hpc_hist_bucket* histo,
1815  uint64_t ncounters, uint bytesPerCodeBlk)
1816 {
1817  uint64_t count = 0, offset = 0, i = 0, inz = 0;
1818 
1819  /* <histogram_non_zero_bucket_count> */
1820  count = 0;
1821  for (i = 0; i < ncounters; ++i) {
1822  if (histo[i] != 0) { count++; inz = i; }
1823  }
1824  hpcio_le8_fwrite(&count, fs);
1825 
1826  if (opt_debug >= 3) {
1827  MSGx(stderr, " buffer (%p) for %s has %"PRIu64" of %"PRIu64" non-zero counters (last non-zero counter: %"PRIu64")",
1828  histo, ename, count, ncounters, inz);
1829  }
1830 
1831  /* <histogram_non_zero_bucket_x_value>
1832  <histogram_non_zero_bucket_x_offset> */
1833  for (i = 0; i < ncounters; ++i) {
1834  if (histo[i] != 0) {
1835  uint32_t cnt = histo[i];
1836  hpcio_le4_fwrite(&cnt, fs); /* count */
1837 
1838  offset = i * bytesPerCodeBlk;
1839  hpcio_le8_fwrite(&offset, fs); /* offset (in bytes) from load addr */
1840 
1841  if (opt_debug >= 3) {
1842  MSGx(stderr, " (cnt,offset)=(%d,%"PRIx64")", cnt, offset);
1843  }
1844  }
1845  }
1846 }
1847 
1848 
1849 static void
1850 write_string(FILE *fs, char *str)
1851 {
1852  /* <string_length> <string_without_terminator> */
1853  uint len = strlen(str);
1854  hpcio_le4_fwrite(&len, fs);
1855  fwrite(str, 1, len, fs);
1856 }
1857 
1858 
1859 /****************************************************************************/
1860 
1861 /* hpcrun_gettid: return a thread id */
1862 /* FIXME: return size_t or intptr_t */
1863 extern long
1865 {
1866 #ifdef HAVE_MONITOR
1867  return (long)(monitor_gettid());
1868 #else
1869  return hpcrun_gettid_SPECIALIZED();
1870 #endif
1871 }
1872 
1873 extern void
1874 hpcrun_parse_execl(const char*** argv, const char* const** envp,
1875  const char* arg, va_list arglist)
1876 {
1877  /* argv & envp are pointers to arrays of char* */
1878  /* va_start has already been called */
1879 
1880  const char* argp;
1881  int argvSz = 32, argc = 1;
1882 
1883  *argv = malloc((argvSz+1) * sizeof(const char*));
1884  if (!*argv) { DIE0("error: malloc() failed!"); }
1885 
1886  (*argv)[0] = arg;
1887  while ((argp = va_arg(arglist, const char*)) != NULL) {
1888  if (argc > argvSz) {
1889  argvSz *= 2;
1890  *argv = realloc(*argv, (argvSz+1) * sizeof(const char*));
1891  if (!*argv) { DIE0("error: realloc() failed!"); }
1892  }
1893  (*argv)[argc] = argp;
1894  argc++;
1895  }
1896  (*argv)[argc] = NULL;
1897 
1898  if (envp != NULL) {
1899  *envp = va_arg(arglist, const char* const*);
1900  }
1901 
1902 #if 0
1903  if (opt_debug >= 2) {
1904  int i;
1905  for (i = 0; i < argc; ++i) {
1906  MSGx(stderr, " execl arg%d: %s", i, (*argv)[i]);
1907  }
1908  if (envp) {
1909  MSG0(stderr, " execl envp found");
1910  }
1911  }
1912 #endif
1913 
1914  /* user calls va_end */
1915 }
int opt_flagscode
Definition: monitor.c:133
static rtloadmap_t * rtloadmap
Definition: monitor.c:139
static void init_sysprofdesc_buffer(hpcsys_profile_desc_vec_t *profdesc, uint numEv, rtloadmap_t *rtmap, hpcsys_profile_desc_vec_t *sharedprofdesc)
Definition: monitor.c:761
unsigned int scale
Definition: monitor.h:157
unsigned int bytesPerCntr
Definition: monitor.h:156
#define HPCRUN_EVENT_WALLCLK_STR
Definition: hpcrun.h:109
#define HPC_GET_PAPIPROFS(x)
Definition: monitor.h:197
static void init_sighandler(int sig)
Definition: monitor.c:1436
size_t hpcio_le4_fwrite(uint32_t *val, FILE *fs)
Definition: hpcio.c:243
static void write_event_data(FILE *fs, char *ename, hpc_hist_bucket *histo, uint64_t ncounters, uint bytesPerCodeBlk)
Definition: monitor.c:1814
void init_papi_for_process_SPECIALIZED()
void init_library()
Definition: monitor.c:164
static void stop_sysprof(hpcsys_profile_desc_vec_t *profdescs)
Definition: monitor.c:1531
void MONITOR_EXT_WRAP_NAME() free(void *ptr)
unsigned int numsprofs
Definition: monitor.h:160
static char * tmp
Definition: tokenize.c:63
void handle_dlopen()
Definition: monitor.c:455
unsigned int bytesPerCodeBlk
Definition: hpcpapi.h:134
#define HPCRUN_EVENT_WALLCLK_STRLN
Definition: hpcrun.h:110
static void write_all_profiles(hpcrun_profiles_desc_t *profdesc, rtloadmap_t *rtmap)
Definition: monitor.c:1684
static void write_string(FILE *fp, char *str)
Definition: monitor.c:1850
const hpcpapi_flagdesc_t * hpcpapi_flag_by_name(const char *name)
Definition: hpcpapi.c:126
static int get_next_gen(const char *path)
Definition: monitor.c:1021
static void count_events(uint *sysEvents, uint *papiEvents)
Definition: monitor.c:548
unsigned int flags
Definition: monitor.h:153
static const uint64_t default_period
Definition: monitor.c:113
#define HPC_GET_SYSPROFS(x)
Definition: monitor.h:193
static void hpcrun_sighandler(int sig)
Definition: monitor.c:327
void dump_hpcpapi_profile_desc_vec(hpcpapi_profile_desc_vec_t *descvec)
Definition: hpcpapi.c:139
static void init_papi_for_process()
Definition: monitor.c:1232
static void append_papiprofdesc_buffer(hpcpapi_profile_desc_vec_t *profdesc, uint numEv, rtloadmap_t *rtmap, hpcpapi_profile_desc_vec_t *sharedprofdesc)
Definition: monitor.c:953
#define HPCRUN_NAME
Definition: hpcrun.h:93
void init_library_SPECIALIZED()
#define HPCRUNFLAT_FMT_Endian
void fini_thread(hpcrun_profiles_desc_t **profdesc, int is_thread)
Definition: monitor.c:1491
static void init_papiprofdesc_buffer(hpcpapi_profile_desc_vec_t *profdesc, uint numEv, rtloadmap_t *rtmap, hpcpapi_profile_desc_vec_t *sharedprofdesc)
Definition: monitor.c:886
static void init_profdesc(hpcrun_profiles_desc_t **profdesc, uint numSysEv, uint numPapiEv, rtloadmap_t *rtmap, hpcrun_profiles_desc_t *sharedprofdesc)
Definition: monitor.c:576
abort
Definition: names.cpp:1
#define MIN(a, b)
Definition: min-max.h:76
static uint numPAPIEvents
Definition: monitor.c:141
rtloadmap_t * hpcrun_get_rtloadmap(int dbglvl)
Definition: rtmap.c:118
static void add_sysevent(hpcsys_profile_desc_vec_t *profdescs, rtloadmap_t *rtmap, int profidx, char *eventnm, uint64_t period)
Definition: monitor.c:1151
const char * hpcrun_cmd
Definition: monitor.c:136
PAPI_sprofil_t * sprofs
Definition: hpcpapi.h:138
static void fini_papi_for_thread(hpcpapi_profile_desc_vec_t *profdescs)
Definition: monitor.c:1570
unsigned int bytesPerCntr
Definition: hpcpapi.h:135
long hpcrun_gettid_SPECIALIZED()
#define HPCRUNFLAT_FMT_Magic
static void write_sysevent_data(FILE *fs, hpcsys_profile_desc_t *prof, int sprofidx)
Definition: monitor.c:1785
void fini_process()
Definition: monitor.c:1466
unsigned int count
Definition: rtmap.h:81
enum enum_hpc_threadprof_t hpc_threadprof_t
static hpcrun_profiles_desc_t * hpc_profdesc
Definition: monitor.c:146
exit
Definition: names.cpp:1
unsigned int uint
Definition: uint.h:124
static void init_options()
Definition: monitor.c:206
#define HPCRUN_EVENT_FWALLCLK_STRLN
Definition: hpcrun.h:113
static void init_profdesc_ofile(hpcrun_profiles_desc_t *profdesc, int sharedprofdesc)
Definition: monitor.c:1039
static void write_module_profile(FILE *fp, rtloadmod_desc_t *mod, hpcrun_profiles_desc_t *profdesc, int sprofidx)
Definition: monitor.c:1730
unsigned long length
Definition: rtmap.h:76
#define DIEx(fmt,...)
Definition: monitor.h:139
int hpc_init_papi_force(int(*init)(int))
Definition: hpcpapi.c:91
static BAnal::Struct::Options opts
Definition: Struct.cpp:160
static void notify_ofile(hpcrun_profiles_desc_t *profdesc, hpcrun_profiles_desc_t *sharedprofdesc)
Definition: monitor.c:1135
rtloadmod_desc_t * module
Definition: rtmap.h:82
static void fini_papi_for_process()
Definition: monitor.c:1595
unsigned int scale
Definition: hpcpapi.h:136
volatile int DEBUGGER_WAIT
Definition: monitor.c:424
static void start_sysprof(hpcsys_profile_desc_vec_t *profdescs)
Definition: monitor.c:1215
static void fini_profdesc(hpcrun_profiles_desc_t **profdesc, int sharedprofdesc)
Definition: monitor.c:1602
#define HPC_GETL_SYSPROFS(x)
Definition: monitor.h:192
void *MONITOR_EXT_WRAP_NAME() realloc(void *ptr, size_t bytes)
#define MSGx(x, fmt,...)
Definition: monitor.h:109
void fini_library()
Definition: monitor.c:183
char opt_outpath[PATH_MAX]
Definition: monitor.c:130
int mkdir(const char *dir)
Definition: FileUtil.cpp:289
#define MSG0(x, fmt)
Definition: monitor.h:106
hpcpapi_profile_desc_t * vec
Definition: hpcpapi.h:155
#define HPC_GETL_PAPIPROFS(x)
Definition: monitor.h:196
unsigned int bytesPerCodeBlk
Definition: monitor.h:155
hpcrun_ofile_desc_t ofile
Definition: monitor.h:186
struct prof * sprofs
Definition: monitor.h:159
long hpcrun_gettid()
Definition: monitor.c:1864
hpcrun_profiles_desc_t * init_thread(int is_thread)
Definition: monitor.c:510
void *MONITOR_EXT_WRAP_NAME() malloc(size_t bytes)
unsigned int numsprofs
Definition: hpcpapi.h:139
static void start_papi_for_thread(hpcpapi_profile_desc_vec_t *profdescs)
Definition: monitor.c:1389
#define NULL
Definition: ElfHelper.cpp:85
void init_process()
Definition: monitor.c:430
size_t hpcio_le8_fwrite(uint64_t *val, FILE *fs)
Definition: hpcio.c:258
#define HPCRUNFLAT_FMT_MagicLen
static uint numSysEvents
Definition: monitor.c:140
int opt_recursive
Definition: monitor.c:127
size_t MONITOR_EXT_WRAP_NAME() fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
Definition: io-over.c:260
#define HPCRUNFLAT_Version
char * opt_eventlist
Definition: monitor.c:129
hpc_threadprof_t opt_thread
Definition: monitor.c:128
void hpcrun_parse_execl(const char ***argv, const char *const **envp, const char *arg, va_list arglist)
Definition: monitor.c:1874
#define DIE0(fmt)
Definition: monitor.h:137
static void append_sysprofdesc_buffer(hpcsys_profile_desc_vec_t *profdesc, uint numEv, rtloadmap_t *rtmap, hpcsys_profile_desc_vec_t *sharedprofdesc)
Definition: monitor.c:825
static void stop_papi_for_thread(hpcpapi_profile_desc_vec_t *profdescs)
Definition: monitor.c:1546
#define HPCRUN_EVENT_FWALLCLK_STR
Definition: hpcrun.h:112
uint64_t offset
Definition: rtmap.h:75
PAPI_event_info_t einfo
Definition: hpcpapi.h:129
static void init_option_debug()
Definition: monitor.c:197
char opt_prefix[PATH_MAX]
Definition: monitor.c:131
uint32_t hpc_hist_bucket
Definition: monitor.c:111
static void write_papievent_data(FILE *fp, hpcpapi_profile_desc_t *prof, int sprofidx)
Definition: monitor.c:1797
static void add_papievent(hpcpapi_profile_desc_vec_t *profdescs, rtloadmap_t *rtmap, int profidx, char *eventnm, uint64_t period)
Definition: monitor.c:1271
int opt_debug
Definition: monitor.c:126
char opt_file[PATH_MAX]
Definition: monitor.c:132
hpcsys_profile_desc_t * vec
Definition: monitor.h:166
#define HPCRUNFLAT_VersionLen
static long period
Definition: itimer.c:194
static void init_sighandlers()
Definition: monitor.c:1428
char * name
Definition: rtmap.h:74
static int domain
Definition: monitor.c:149
static void write_event_hdr(FILE *fs, char *name, char *desc, uint64_t period)
Definition: monitor.c:1775