HPCToolkit
main.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 // system include files
49 //***************************************************************************
50 
51 #include <sys/types.h>
52 #include <pthread.h>
53 #include <unistd.h>
54 #include <setjmp.h>
55 #include <stdbool.h>
56 #include <stdint.h>
57 #include <inttypes.h>
58 #include <dlfcn.h>
59 #include <stdlib.h>
60 #include <string.h>
61 
62 #ifdef LINUX
63 #include <linux/unistd.h>
64 #include <linux/limits.h>
65 #endif
66 
67 //***************************************************************************
68 // libmonitor include files
69 //***************************************************************************
70 
71 #include <monitor.h>
72 
73 
74 //***************************************************************************
75 // user include files
76 //***************************************************************************
77 
78 #include <include/uint.h>
79 
80 #include <include/hpctoolkit-config.h>
81 
82 #include "main.h"
83 
84 #include "disabled.h"
85 #include "env.h"
86 #include "loadmap.h"
87 #include "files.h"
88 #include "fnbounds_interface.h"
90 #include "hpcrun_dlfns.h"
91 #include "hpcrun_options.h"
92 #include "hpcrun_return_codes.h"
93 #include "hpcrun_stats.h"
94 #include "name.h"
95 #include "start-stop.h"
96 #include "custom-init.h"
97 #include "cct_insert_backtrace.h"
98 #include "safe-sampling.h"
99 
100 #include "metrics.h"
101 
102 #include "sample_event.h"
103 #include <sample-sources/none.h>
104 #include <sample-sources/itimer.h>
105 
107 #include "sample_sources_all.h"
108 #include "segv_handler.h"
109 #include "sample_prob.h"
110 #include "term_handler.h"
111 
112 #include "epoch.h"
113 #include "thread_data.h"
114 #include "threadmgr.h"
115 #include "thread_use.h"
116 #include "trace.h"
117 #include "write_data.h"
118 #include <utilities/token-iter.h>
119 
120 #include <memory/hpcrun-malloc.h>
121 #include <memory/mmap.h>
122 
124 
125 #include <cct/cct.h>
126 
127 #include <unwind/common/backtrace.h>
128 #include <unwind/common/unwind.h>
129 
131 
132 #include <lush/lush-backtrace.h>
133 #include <lush/lush-pthread.h>
134 
136 #include <lib/prof-lean/hpcio.h>
137 
138 #include <messages/messages.h>
139 #include <messages/debug-flag.h>
140 
141 extern void hpcrun_set_retain_recursion_mode(bool mode);
142 #ifndef USE_LIBUNW
143 extern void hpcrun_dump_intervals(void* addr);
144 #endif // ! USE_LIBUNW
145 
146 //***************************************************************************
147 // local data types. Primarily for passing data between pre_PHASE, PHASE, and post_PHASE
148 //***************************************************************************
149 
150 typedef struct local_thread_data_t {
153 
154 typedef struct fork_data_t {
155  int flag;
156  bool is_child;
157 } fork_data_t;
158 
159 
160 //***************************************************************************
161 // constants
162 //***************************************************************************
163 
166 };
167 
168 //***************************** concrete data structure definition **********
170  void (* func) (void *); // function to invoke on cleanup
171  void * arg; // argument to pass to func
174 };
175 
176 //***************************************************************************
177 // forward declarations
178 //***************************************************************************
179 
180 static int
181 dump_interval_handler(int sig, siginfo_t* info, void* ctxt)
182 __attribute__ ((unused));
183 
184 //***************************************************************************
185 // global variables
186 //***************************************************************************
187 
188 int lush_metrics = 0; // FIXME: global variable for now
189 
190 /******************************************************************************
191  * (public declaration) thread-local variables
192  *****************************************************************************/
193  __thread bool hpcrun_thread_suppress_sample = true;
194 
195 
196 //***************************************************************************
197 // local variables
198 //***************************************************************************
199 
201 static bool hpcrun_is_initialized_private = false;
202 static bool safe_to_sync_sample = false;
203 static void* main_addr = NULL;
204 static void* main_lower = NULL;
205 static void* main_upper = (void*) (intptr_t) -1;
206 #ifndef HPCRUN_STATIC_LINK
207 static void* main_addr_dl = NULL;
208 static void* main_lower_dl = NULL;
209 static void* main_upper_dl = (void*) (intptr_t) -1;
210 #endif
214 static char execname[PATH_MAX] = {'\0'};
215 
216 //
217 // Local functions
218 //
219 static void
220 setup_main_bounds_check(void* main_addr)
221 {
222  // record bound information for the symbol main statically linked
223  // into an executable, or a PLT stub named main and the function
224  // to which it will be dynamically bound. these function bounds will
225  // later be used to validate unwinds in the main thread by the function
226  // hpcrun_inbounds_main.
227 
228  load_module_t* lm = NULL;
229 
230  // record bound information about the function bounds of the 'main'
231  // function passed into libc_start_main as real_main. this might be
232  // a trampoline in the PLT.
233  if (main_addr) {
234 #if defined(__PPC64__) || defined(HOST_CPU_IA64)
235  main_addr = *((void**) main_addr);
236 #endif
237  fnbounds_enclosing_addr(main_addr, &main_lower, &main_upper, &lm);
238  }
239 
240 #ifndef HPCRUN_STATIC_LINK
241  // record bound information about the function bounds of a global
242  // dynamic symbol named 'main' (if any).
243  // passed into libc_start_main as real_main. this might be a
244  // trampoline in the PLT.
245  dlerror();
246  main_addr_dl = dlsym(RTLD_NEXT,"main");
247  if (main_addr_dl) {
248  fnbounds_enclosing_addr(main_addr_dl, &main_lower_dl, &main_upper_dl, &lm);
249  }
250 #endif
251 }
252 
253 //
254 // Derive the full executable name from the
255 // process name. Store in a local variable.
256 //
257 static void
258 copy_execname(char* process_name)
259 {
260  char tmp[PATH_MAX] = {'\0'};
261  char* rpath = realpath(process_name, tmp);
262  char* src = (rpath != NULL) ? rpath : process_name;
263 
264  strncpy(execname, src, sizeof(execname));
265 }
266 
267 //
268 // *** Accessor functions ****
269 //
270 
271 bool
273 {
275 }
276 
277 void*
279 {
280  return main_addr;
281 }
282 
283 bool
285 {
286  // address is in a main routine statically linked into the executable
287  int in_static_main = (main_lower <= addr) & (addr <= main_upper);
288  int in_main = in_static_main;
289 
290 #ifndef HPCRUN_STATIC_LINK
291  // address is in a main routine dynamically linked into the executable
292  int in_dynamic_main = (main_lower_dl <= addr) & (addr <= main_upper_dl);
293  in_main |= in_dynamic_main;
294 #endif
295 
296  return in_main;
297 }
298 
299 //
300 // fetch the execname
301 // note: execname has no value before main().
302 //
303 char*
305 {
306  return execname;
307 }
308 
309 //
310 // the char* fn argument is for debugging:
311 // It has no effect in this incarnation
312 //
313 bool
314 hpcrun_is_safe_to_sync(const char* fn)
315 {
316  return safe_to_sync_sample;
317 }
318 
319 void
321 {
322  safe_to_sync_sample = true;
323 }
324 
325 //***************************************************************************
326 // *** Important note about libmonitor callbacks ***
327 //
328 // In libmonitor callbacks, block two things:
329 //
330 // 1. Skip the callback if hpcrun is not yet initialized.
331 // 2. Block async reentry for the duration of the callback.
332 //
333 // Init-process and init-thread are where we do the initialization, so
334 // they're special. Also, libmonitor promises that init and fini process
335 // and thread are run in sequence, but dlopen, fork, pthread-create
336 // can occur out of sequence (in init constructor).
337 //***************************************************************************
338 
339 //***************************************************************************
340 // internal operations
341 //***************************************************************************
342 
343 static int
344 abort_timeout_handler(int sig, siginfo_t* siginfo, void* context)
345 {
346  EEMSG("hpcrun: abort timeout activated - context pc %p",
347  hpcrun_context_pc(context));
349 
350  return 0; /* keep compiler happy, but can't get here */
351 }
352 
353 
354 static void
356 {
357  char *error_timeout = getenv("HPCRUN_ABORT_TIMEOUT");
358  if (error_timeout) {
359  int seconds = atoi(error_timeout);
360  if (seconds != 0) {
361  EEMSG("hpcrun: abort timeout armed");
362  monitor_sigaction(SIGALRM, &abort_timeout_handler, 0, NULL);
363  alarm(seconds);
364  }
365  }
366 }
367 
368 //------------------------------------
369 // ** local routines & data to support interval dumping **
370 //------------------------------------
371 
372 static sigjmp_buf ivd_jb;
373 
375 
376 static int
377 dump_interval_handler(int sig, siginfo_t* info, void* ctxt)
378 {
379  (*hpcrun_get_real_siglongjmp())(ivd_jb, 9);
380  return 0;
381 }
382 
383 //------------------------------------
384 // process level
385 //------------------------------------
386 
387 void
388 hpcrun_init_internal(bool is_child)
389 {
391 
395 
396  // must initialize unwind recipe map before initializing fnbounds
397  // because mapping of load modules affects the recipe map.
398  hpcrun_unw_init();
399 
400  // WARNING: a perfmon bug requires us to fork off the fnbounds
401  // server before we call PAPI_init, which is done in argument
402  // processing below. Also, fnbounds_init must be done after the
403  // memory allocator is initialized.
404  fnbounds_init();
405 
406  main_addr = monitor_get_addr_main();
407  setup_main_bounds_check(main_addr);
408  TMSG(MAIN_BOUNDS, "main addr %p ==> lower %p, upper %p", main_addr, main_lower, main_upper);
409 
410  hpcrun_options__init(&opts);
412 
413  hpcrun_trace_init(); // this must go after thread initialization
414  hpcrun_trace_open(&(TD_GET(core_profile_trace_data)));
415 
416  // Decide whether to retain full single recursion, or collapse recursive calls to
417  // first instance of recursive call
418  hpcrun_set_retain_recursion_mode(getenv("HPCRUN_RETAIN_RECURSION") != NULL);
419 
420  // Initialize logical unwinding agents (LUSH)
421  if (opts.lush_agent_paths[0] != '\0') {
422  epoch_t* epoch = TD_GET(core_profile_trace_data.epoch);
423  TMSG(MALLOC," -init_internal-: lush allocation");
425  hpcrun_logicalUnwind(true);
427  EMSG("Logical Unwinding Agent: %s (%p / %p)", opts.lush_agent_paths,
428  epoch, lush_agents);
429  }
430 
431  lush_metrics = (lush_agents) ? 1 : 0;
432 
433  // tallent: this is harmless, but should really only occur for pthread agent
435 
437 
438 
439 #ifndef USE_LIBUNW
440  if (getenv("HPCRUN_ONLY_DUMP_INTERVALS")) {
442  TMSG(INTERVALS_PRINT, "table data = %p", table.table);
443  TMSG(INTERVALS_PRINT, "table length = %d", table.len);
444 
445  if (monitor_sigaction(SIGSEGV, &dump_interval_handler, 0, NULL)) {
446  fprintf(stderr, "Could not install dump interval segv handler\n");
447  monitor_real_exit(1);
448  }
449 
450  for (void** e = table.table; e < table.table + table.len - 1; e++) {
451  fprintf(stderr, "======== %p Intervals ========\n", *e);
452  if (e > table.table || ! sigsetjmp(ivd_jb, 1))
454  else
455  fprintf(stderr, "--Error: skipped--\n");
456  fprintf(stderr, "\n");
457  fflush(stderr);
458  }
459  exit(0);
460  }
461 #endif // ! USE_LIBUNW
462 
465 
466  // sample source setup
467 
468  TMSG(PROCESS, "Sample source setup");
469  //
470  // NOTE: init step no longer necessary.
471  // -all- possible (e.g. registered) sample sources call their own init method
472  // no need to do it twice.
473  //
474  if (! is_child) {
475  SAMPLE_SOURCES(process_event_list, lush_metrics);
476  }
477  SAMPLE_SOURCES(gen_event_set, lush_metrics);
478 
479  // set up initial 'epoch'
480 
481  TMSG(EPOCH,"process init setting up initial epoch/loadmap");
483 
484 #ifdef SPECIAL_DUMP_INTERVALS
485  {
486  // temporary debugging code for x86 / ppc64
487 
488  extern void hpcrun_dump_intervals(void* addr2);
489  char* addr1 = getenv("ADDR1");
490  char* addr2 = getenv("ADDR2");
491 
492  if (addr1 != NULL) {
493  addr1 = (void*) (uintptr_t) strtol(addr1, NULL, 0);
494  fprintf(stderr,"address 1 = %p\n", addr1);
495  hpcrun_dump_intervals(addr1);
496  fflush(NULL);
497  }
498 
499  if (addr2 != NULL) {
500  addr2 = (void*) (uintptr_t) strtol(addr2, NULL, 0);
501  fprintf(stderr,"address 2 = %p\n", addr2);
502  hpcrun_dump_intervals(addr2);
503  fflush(NULL);
504  }
505  if (addr1 || addr2) monitor_real_exit(0);
506  }
507 #endif
508 
509  // start the sampling process
510 
513 
514  // release the wallclock handler -for this thread-
516 
517  // NOTE: hack to ensure that sample source start can be delayed until mpi_init
518  if (hpctoolkit_sampling_is_active() && ! getenv("HPCRUN_MPI_ONLY")) {
519  SAMPLE_SOURCES(start);
520  }
521  hpcrun_is_initialized_private = true;
522 }
523 
524 #define GET_NEW_AUX_CLEANUP_NODE(node_ptr) do { \
525 if (hpcrun_aux_cleanup_free_list_head) { \
526 node_ptr = hpcrun_aux_cleanup_free_list_head; \
527 hpcrun_aux_cleanup_free_list_head = hpcrun_aux_cleanup_free_list_head->next; \
528 } else { \
529 node_ptr = (hpcrun_aux_cleanup_t *) hpcrun_malloc(sizeof(hpcrun_aux_cleanup_t)); \
530 } \
531 } while(0)
532 
533 #define ADD_TO_FREE_AUX_CLEANUP_LIST(node_ptr) do { (node_ptr)->next = hpcrun_aux_cleanup_free_list_head; \
534 hpcrun_aux_cleanup_free_list_head = (node_ptr); }while(0)
535 
536 // Add a callback function and its argument to a doubly-linked list of things to cleanup at process termination.
537 // Don't rely on sample source data in the implementation of the callback.
538 // Caller needs to ensure that the entry is safe.
539 
541 {
542  spinlock_lock(&hpcrun_aux_cleanup_lock);
545  node->func = func;
546  node->arg = arg;
547 
548  node->prev = NULL;
550  if (hpcrun_aux_cleanup_list_head) {
551  hpcrun_aux_cleanup_list_head->prev = node;
552  }
553  hpcrun_aux_cleanup_list_head = node;
554  spinlock_unlock(&hpcrun_aux_cleanup_lock);
555  return node;
556 }
557 
558 // Delete a node from cleanup list.
559 // Caller needs to ensure that the entry is safe.
561 {
562  assert (node != NULL);
563  spinlock_lock(&hpcrun_aux_cleanup_lock);
564  if (node->prev) {
565  if (node->next) {
566  node->next->prev = node->prev;
567  }
568  node->prev->next = node->next;
569  } else {
570  if (node->next) {
571  node->next->prev = NULL;
572  }
573  hpcrun_aux_cleanup_list_head = node->next;
574  }
576  spinlock_unlock(&hpcrun_aux_cleanup_lock);
577 }
578 
579 // This will be called after sample sources have been shutdown.
580 // Don't rely on sample source data in the implementation of the callback.
582 {
583  // Assumed to be single threaded and hence not taking any locks here
586  while (p) {
587  p->func(p->arg);
588  q = p;
589  p = p->next;
591  }
592  hpcrun_aux_cleanup_list_head = NULL;
593 }
594 
595 /***
596  * This routine is called at the end of the program to:
597  * call sample-sources to stop and shutdown
598  * clean hpcrun action
599  * clean thread manager (write profile data and closing resources)
600  * terminate hpcfnbounds
601  ***/
602 void
604 {
606 
607  TMSG(FINI, "process");
608 
610 
611  if (hpcrun_is_initialized()) {
612  hpcrun_is_initialized_private = false;
613 
614  TMSG(FINI, "process attempting sample shutdown");
615 
616  SAMPLE_SOURCES(stop);
617  SAMPLE_SOURCES(shutdown);
618 
619  // shutdown LUSH agents
620  if (lush_agents) {
622  lush_agents = NULL;
623  }
624 
625  // N.B. short-circuit, if monitoring is disabled
626  if (hpcrun_get_disabled()) {
627  return;
628  }
629 
630  // Call all registered auxiliary functions before termination.
631  // This typically means flushing files that were not done by their creators.
632 
634 
635  // write all threads' profile data and close trace file
637 
638  fnbounds_fini();
640  messages_fini();
641  }
642 }
643 
644 
645 //------------------------------------
646 // thread level
647 //------------------------------------
648 
649 #ifdef USE_GCC_THREAD
650 extern __thread monitor_tid;
651 #endif // USE_GCC_THREAD
652 
653 void
655 {
659  SAMPLE_SOURCES(thread_init);
660 }
661 
662 // DEBUG support
663 static void
665 {
666  int iarg = (int) (intptr_t) arg;
667  TMSG(THREAD_CTXT, "thr %d -- %d: lm-id: %d lm-ip: %p",
668  iarg,
670  hpcrun_cct_addr(n)->ip_norm.lm_id,
671  hpcrun_cct_addr(n)->ip_norm.lm_ip);
672 }
673 
674 void*
675 hpcrun_thread_init(int id, local_thread_data_t* local_thread_data) // cct_ctxt_t* thr_ctxt)
676 {
677  cct_ctxt_t* thr_ctxt = local_thread_data ? local_thread_data->thr_ctxt : NULL;
678 
680 
681  // ----------------------------------------
682  // call thread manager to get a thread data. If there is unused thread data,
683  // we can recycle it, otherwise we need to allocate a new one.
684  // If we allocate a new one, we need to initialize the data and trace file.
685  // ----------------------------------------
686 
687  thread_data_t* td = NULL;
688  hpcrun_threadMgr_data_get(id, thr_ctxt, &td);
690 
691  td->inside_hpcrun = 1; // safe enter, disable signals
692 
693  if (! thr_ctxt) EMSG("Thread id %d passes null context", id);
694 
695  if (ENABLED(THREAD_CTXT))
696  hpcrun_walk_path(thr_ctxt->context, logit, (cct_op_arg_t) (intptr_t) id);
697 
698  epoch_t* epoch = TD_GET(core_profile_trace_data.epoch);
699 
700  // handle event sets for sample sources
701  SAMPLE_SOURCES(gen_event_set,lush_metrics);
702 
703  // sample sources take thread specific action prior to start (often is a 'registration' action);
704  SAMPLE_SOURCES(thread_init_action);
705 
706  // release the wallclock handler -for this thread-
708  // start the sample sources
709  if (! hpcrun_thread_suppress_sample)
710  SAMPLE_SOURCES(start);
711 
712  return (void*) epoch;
713 }
714 
721 void
723 {
724  TMSG(FINI,"thread fini");
725 
726  // take no action if this thread is suppressed
727  if (hpcrun_thread_suppress_sample) return;
728 
729  if (hpcrun_is_initialized()) {
730  TMSG(FINI,"thread finit stops sampling");
731  SAMPLE_SOURCES(stop);
732  SAMPLE_SOURCES(thread_fini_action);
733  lushPthr_thread_fini(&TD_GET(pthr_metrics));
734 
735  if (hpcrun_get_disabled()) {
736  return;
737  }
738 
739  // inform thread manager that we are terminating the thread
740  // thread manager may enqueue the thread_data (in compact mode)
741  // or flush the data into hpcrun file
742 
744  hpcrun_threadMgr_data_put(epoch, td);
745 
746  TMSG(PROCESS, "End of thread");
747  }
748 }
749 
750 
751 //***************************************************************************
752 // hpcrun debugging support
753 //***************************************************************************
754 
755 volatile int HPCRUN_DEBUGGER_WAIT = 1;
756 
757 void
759 {
760  HPCRUN_DEBUGGER_WAIT = 0;
761 }
762 
763 
764 void
766 {
767  const char* HPCRUN_WAIT = getenv("HPCRUN_WAIT");
768  if (HPCRUN_WAIT) {
769  while (HPCRUN_DEBUGGER_WAIT);
770 
771  // when the user program forks, we don't want to wait to have a debugger
772  // attached for each exec along a chain of fork/exec. if that is what
773  // you want when debugging, make your own arrangements.
774  unsetenv("HPCRUN_WAIT");
775  }
776 }
777 
778 
779 
780 //***************************************************************************
781 // process control (via libmonitor)
782 //***************************************************************************
783 
784 void*
785 monitor_init_process(int *argc, char **argv, void* data)
786 {
787  char* process_name;
788  char buf[PROC_NAME_LEN];
789 
790  hpcrun_thread_suppress_sample = false;
791 
792  fork_data_t* fork_data = (fork_data_t*) data;
793  bool is_child = data && fork_data->is_child;
794 
795  hpcrun_wait();
796 
797 #if 0
798  // temporary patch to avoid deadlock within PAMI's optimized implementation
799  // of all-to-all. a problem was observed when PAMI's optimized all-to-all
800  // implementation was invoked on behalf of darshan_shutdown
801  putenv("PAMID_COLLECTIVES=0");
802 #endif // defined(HOST_SYSTEM_IBM_BLUEGENE)
803 
805 
806  // FIXME: if the process fork()s before main, then argc and argv
807  // will be NULL in the child here. MPT on CNL does this.
808  process_name = "unknown";
809  if (argv != NULL && argv[0] != NULL) {
810  process_name = argv[0];
811  }
812  else {
813  int len = readlink("/proc/self/exe", buf, PROC_NAME_LEN - 1);
814  if (len > 1) {
815  buf[len] = 0;
816  process_name = buf;
817  }
818  }
819 
821 
822  copy_execname(process_name);
823  hpcrun_files_set_executable(process_name);
824 
826 
827  messages_init();
828 
830 
831  // for debugging, limit the life of the execution with an alarm.
832  char* life = getenv("HPCRUN_LIFETIME");
833  if (life != NULL){
834  int seconds = atoi(life);
835  if (seconds > 0) alarm((unsigned int) seconds);
836  }
837 
838  char* s = getenv(HPCRUN_EVENT_LIST);
839 
840  if (! is_child) {
842  }
843 
845 
847 
848  if (!hpcrun_get_disabled()) {
850  }
851 
852  TMSG(PROCESS,"hpcrun_files_set_executable called w process name = %s", process_name);
853 
854  TMSG(PROCESS,"init");
855 
858 
859  TMSG(PROCESS, "I am a %s process", is_child ? "child" : "parent");
860 
861  hpcrun_init_internal(is_child);
862 
863  if (ENABLED(TST)){
864  EEMSG("TST debug ctl is active!");
865  STDERR_MSG("Std Err message appears");
866  }
867 
869 
870  return data;
871 }
872 
873 
874 void
875 monitor_fini_process(int how, void* data)
876 {
877  if (hpcrun_get_disabled()) {
878  return;
879  }
880 
882 
884 
886 }
887 
888 
890 
891 void*
893 {
894  if (! hpcrun_is_initialized()) {
895  return NULL;
896  }
898 
899  TMSG(PRE_FORK,"pre_fork call");
900 
901  if (SAMPLE_SOURCES(started)) {
902  TMSG(PRE_FORK,"sources shutdown");
903  SAMPLE_SOURCES(stop);
904  SAMPLE_SOURCES(shutdown);
905  }
906 
907  TMSG(PRE_FORK,"finished pre_fork call");
908  from_fork.is_child = true;
909 
911 
912  return (void *)(&from_fork);
913 }
914 
915 
916 void
917 monitor_post_fork(pid_t child, void* data)
918 {
919  if (! hpcrun_is_initialized()) {
920  return;
921  }
923 
924  TMSG(POST_FORK,"Post fork call");
925 
926  if (!SAMPLE_SOURCES(started)){
927  TMSG(POST_FORK,"sample sources re-init+re-start");
928  SAMPLE_SOURCES(init);
929  SAMPLE_SOURCES(gen_event_set,0); // FIXME: pass lush_metrics here somehow
930  SAMPLE_SOURCES(start);
931  }
932 
933  TMSG(POST_FORK,"Finished post fork");
935 }
936 
937 
938 //***************************************************************************
939 // MPI control (via libmonitor)
940 //***************************************************************************
941 
942 //
943 // On some systems, taking a signal inside MPI_Init breaks MPI_Init.
944 // So, turn off sampling (not just block) within MPI_Init, with the
945 // control variable MPI_RISKY to bypass this. This is a problem on
946 // IBM BlueGene and Cray XK6 (interlagos).
947 //
948 void
950 {
952 
953  TMSG(MPI, "Pre MPI_Init");
954  if (! ENABLED(MPI_RISKY)) {
955  // Turn sampling off.
956  TMSG(MPI, "Stopping Sample Sources");
957  SAMPLE_SOURCES(stop);
958  }
960 }
961 
962 
963 void
964 monitor_init_mpi(int *argc, char ***argv)
965 {
967 
968  TMSG(MPI, "Post MPI_Init");
969  if (! ENABLED(MPI_RISKY)) {
970  // Turn sampling back on.
971  TMSG(MPI, "Restart Sample Sources");
972  SAMPLE_SOURCES(start);
973  }
975 }
976 
977 
978 //***************************************************************************
979 // thread control (via libmonitor)
980 //***************************************************************************
981 
982 void
984 {
986 
987  TMSG(THREAD,"REALLY init_thread_support ---");
990  TMSG(THREAD,"Init thread support done");
991 
993 }
994 
995 void*
997 {
998  // N.B.: monitor_thread_pre_create() can be called before
999  // monitor_init_thread_support() or even monitor_init_process().
1001  return NULL;
1002  }
1005 
1006  // INVARIANTS at this point:
1007  // 1. init-process has occurred.
1008  // 2. current execution context is either the spawning process or thread.
1009  TMSG(THREAD,"pre create");
1010 
1011  // -------------------------------------------------------
1012  // Capture new thread's creation context, skipping 1 level of context
1013  // WARNING: Do not move the call to getcontext()
1014  // -------------------------------------------------------
1016 
1017  ucontext_t context;
1018  int ret = getcontext(&context);
1019  if (ret != 0) {
1020  EMSG("error: monitor_thread_pre_create: getcontext = %d", ret);
1021  goto fini;
1022  }
1023 
1024  cct_node_t* n = hpcrun_gen_thread_ctxt(&context);
1025 
1026  TMSG(THREAD,"before lush malloc");
1027  TMSG(MALLOC," -thread_precreate: lush malloc");
1028  epoch_t* epoch = hpcrun_get_thread_epoch();
1029  thr_ctxt = hpcrun_malloc(sizeof(cct_ctxt_t));
1030  TMSG(THREAD,"after lush malloc, thr_ctxt = %p",thr_ctxt);
1031  thr_ctxt->context = n;
1032  thr_ctxt->parent = epoch->csdata_ctxt;
1033  TMSG(THREAD_CTXT, "context = %d, parent = %d", hpcrun_cct_persistent_id(thr_ctxt->context),
1034  thr_ctxt->parent ? hpcrun_cct_persistent_id(thr_ctxt->parent->context) : -1);
1035  rv->thr_ctxt = thr_ctxt;
1036 
1037  fini:
1038 
1039  TMSG(THREAD,"->finish pre create");
1040  hpcrun_safe_exit();
1041 
1042  return rv;
1043 }
1044 
1045 
1046 void
1048 {
1049  if (! hpcrun_is_initialized()) {
1050  return;
1051  }
1053 
1054  TMSG(THREAD,"post create");
1055  TMSG(THREAD,"done post create");
1056 
1057  hpcrun_safe_exit();
1058 }
1059 
1060 void*
1061 monitor_init_thread(int tid, void* data)
1062 {
1063 #ifdef USE_GCC_THREAD
1064  monitor_tid = tid;
1065 #endif
1066 
1067  hpcrun_thread_suppress_sample = false;
1068  //
1069  // Do nothing if ignoring thread
1070  //
1071  Token_iterate(tok, getenv("HPCRUN_IGNORE_THREAD"), " ,",
1072  {
1073  if (atoi(tok) == tid) {
1074  hpcrun_thread_suppress_sample = true;
1075  }
1076  });
1077 
1078 
1079  TMSG(THREAD,"init thread %d",tid);
1080  void* thread_data = hpcrun_thread_init(tid, (local_thread_data_t*) data);
1081  TMSG(THREAD,"back from init thread %d",tid);
1082 
1084 
1085  hpcrun_safe_exit();
1086 
1087  return thread_data;
1088 }
1089 
1090 
1091 void
1092 monitor_fini_thread(void* init_thread_data)
1093 {
1095 
1096  if (hpcrun_get_disabled()) {
1097  return;
1098  }
1099 
1101 
1102  epoch_t *epoch = (epoch_t *)init_thread_data;
1103  hpcrun_thread_fini(epoch);
1104  hpcrun_safe_exit();
1105 }
1106 
1107 
1108 size_t
1109 monitor_reset_stacksize(size_t old_size)
1110 {
1111  static const size_t MEG = (1024 * 1024);
1112 
1113  size_t new_size = old_size + MEG;
1114 
1115  if (new_size < 2 * MEG)
1116  new_size = 2 * MEG;
1117 
1118  return new_size;
1119 }
1120 
1121 
1122 //***************************************************************************
1123 // (sig)longjmp for trampoline (via monitor extensions)
1124 //***************************************************************************
1125 
1126 // FIXME: Comment-out the overrides of longjmp() and siglongjmp() for
1127 // now. We currently don't use them and _FORTIFY_SOURCE in newer gnu
1128 // libc breaks this code.
1129 //
1130 // Before re-enabling, we need to better understand how gnu libc and
1131 // <bits/setjmp2.h> map longjmp() and siglongjmp() to __longjmp_chk()
1132 // and what is the right way to intercept them. Also, find a way
1133 // around the 3-1 name mapping.
1134 //
1135 // Note: be sure to reset 'monitor_wrap_names' in hpclink.
1136 
1137 #if 1
1138 
1140 
1143 {
1144  return real_siglongjmp;
1145 }
1146 
1147 void
1149 {
1150  MONITOR_EXT_GET_NAME(real_siglongjmp, siglongjmp);
1151 }
1152 
1153 #else
1154 
1155 typedef void longjmp_fcn(jmp_buf, int);
1156 
1157 #ifdef HPCRUN_STATIC_LINK
1158 extern longjmp_fcn __real_longjmp;
1159 extern siglongjmp_fcn __real_siglongjmp;
1160 #endif
1161 
1162 static longjmp_fcn *real_longjmp = NULL;
1163 static siglongjmp_fcn *real_siglongjmp = NULL;
1164 
1165 
1168 {
1169  return real_siglongjmp;
1170 }
1171 
1172 void
1174 {
1175  MONITOR_EXT_GET_NAME_WRAP(real_siglongjmp, siglongjmp);
1176 }
1177 
1178 void
1179 MONITOR_EXT_WRAP_NAME(longjmp)(jmp_buf buf, int val)
1180 {
1182  MONITOR_EXT_GET_NAME_WRAP(real_longjmp, longjmp);
1183 
1184  hpcrun_safe_exit();
1185  (*real_longjmp)(buf, val);
1186 
1187  // Never reached, but silence a compiler warning.
1188  EEMSG("return from real longjmp(), should never get here");
1189  _exit(1);
1190 }
1191 
1192 
1193 void
1194 MONITOR_EXT_WRAP_NAME(siglongjmp)(sigjmp_buf buf, int val)
1195 {
1198 
1199  hpcrun_safe_exit();
1200  (*real_siglongjmp)(buf, val);
1201 
1202  // Never reached, but silence a compiler warning.
1203  EEMSG("return from real siglongjmp(), should never get here");
1204  _exit(1);
1205 }
1206 #endif
1207 
1208 //***************************************************************************
1209 // thread control (via our monitoring extensions)
1210 //***************************************************************************
1211 
1212 // ---------------------------------------------------------
1213 // mutex_lock
1214 // ---------------------------------------------------------
1215 
1216 #ifdef LUSH_PTHREADS
1217 
1218 typedef int mutex_lock_fcn(pthread_mutex_t *);
1219 
1220 #ifdef HPCRUN_STATIC_LINK
1221 //extern mutex_lock_fcn __real_pthread_mutex_lock;
1222 extern mutex_lock_fcn __real_pthread_mutex_trylock;
1223 extern mutex_lock_fcn __real_pthread_mutex_unlock;
1224 #endif // HPCRUN_STATIC_LINK
1225 
1226 //static mutex_lock_fcn *real_mutex_lock = NULL;
1227 static mutex_lock_fcn *real_mutex_trylock = NULL;
1228 static mutex_lock_fcn *real_mutex_unlock = NULL;
1229 
1230 
1231 int
1233 {
1234  // N.B.: do not use dlsym() to obtain "real_pthread_mutex_lock"
1235  // because dlsym() indirectly calls calloc(), which can call
1236  // pthread_mutex_lock().
1237  extern int __pthread_mutex_lock(pthread_mutex_t* lock);
1238  //MONITOR_EXT_GET_NAME_WRAP(real_mutex_lock, pthread_mutex_lock);
1239 
1240  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1241 
1242  if (hpcrun_is_initialized()) {
1243  lushPthr_mutexLock_pre(&TD_GET(pthr_metrics), lock);
1244  }
1245 
1246  int ret = __pthread_mutex_lock(lock);
1247 
1248  if (hpcrun_is_initialized()) {
1249  lushPthr_mutexLock_post(&TD_GET(pthr_metrics), lock /*,ret*/);
1250  }
1251 
1252  return ret;
1253 }
1254 
1255 
1256 int
1257 MONITOR_EXT_WRAP_NAME(pthread_mutex_trylock)(pthread_mutex_t* lock)
1258 {
1259  MONITOR_EXT_GET_NAME_WRAP(real_mutex_trylock, pthread_mutex_trylock);
1260  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1261 
1262  int ret = (*real_mutex_trylock)(lock);
1263 
1264  if (hpcrun_is_initialized()) {
1265  lushPthr_mutexTrylock_post(&TD_GET(pthr_metrics), lock, ret);
1266  }
1267 
1268  return ret;
1269 }
1270 
1271 
1272 int
1274 {
1275  MONITOR_EXT_GET_NAME_WRAP(real_mutex_unlock, pthread_mutex_unlock);
1276  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1277 
1278  int ret = (*real_mutex_unlock)(lock);
1279 
1280  if (hpcrun_is_initialized()) {
1281  lushPthr_mutexUnlock_post(&TD_GET(pthr_metrics), lock /*,ret*/);
1282  }
1283 
1284  return ret;
1285 }
1286 
1287 #endif // LUSH_PTHREADS
1288 
1289 
1290 // ---------------------------------------------------------
1291 // spin_lock
1292 // ---------------------------------------------------------
1293 
1294 #ifdef LUSH_PTHREADS
1295 
1296 typedef int spinlock_fcn(pthread_spinlock_t *);
1297 
1298 #ifdef HPCRUN_STATIC_LINK
1299 extern spinlock_fcn __real_pthread_spin_lock;
1300 extern spinlock_fcn __real_pthread_spin_trylock;
1301 extern spinlock_fcn __real_pthread_spin_unlock;
1302 extern spinlock_fcn __real_pthread_spin_destroy;
1303 #endif // HPCRUN_STATIC_LINK
1304 
1305 static spinlock_fcn *real_spin_lock = NULL;
1306 static spinlock_fcn *real_spin_trylock = NULL;
1307 static spinlock_fcn *real_spin_unlock = NULL;
1308 static spinlock_fcn *real_spin_destroy = NULL;
1309 
1310 
1311 int
1312 MONITOR_EXT_WRAP_NAME(pthread_spin_lock)(pthread_spinlock_t* lock)
1313 {
1315  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1316 
1317  pthread_spinlock_t* real_lock = lock;
1318  if (hpcrun_is_initialized()) {
1319  real_lock = lushPthr_spinLock_pre(&TD_GET(pthr_metrics), lock);
1320  }
1321 
1322 #if (LUSH_PTHR_FN_TY == 3)
1323  int ret = lushPthr_spin_lock(lock);
1324 #else
1325  int ret = (*real_spin_lock)(real_lock);
1326 #endif
1327 
1328  if (hpcrun_is_initialized()) {
1329  lushPthr_spinLock_post(&TD_GET(pthr_metrics), lock /*,ret*/);
1330  }
1331 
1332  return ret;
1333 }
1334 
1335 
1336 int
1337 MONITOR_EXT_WRAP_NAME(pthread_spin_trylock)(pthread_spinlock_t* lock)
1338 {
1339  MONITOR_EXT_GET_NAME_WRAP(real_spin_trylock, pthread_spin_trylock);
1340  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1341 
1342  pthread_spinlock_t* real_lock = lock;
1343  if (hpcrun_is_initialized()) {
1344  real_lock = lushPthr_spinTrylock_pre(&TD_GET(pthr_metrics), lock);
1345  }
1346 
1347 #if (LUSH_PTHR_FN_TY == 3)
1348  int ret = lushPthr_spin_trylock(lock);
1349 #else
1350  int ret = (*real_spin_trylock)(real_lock);
1351 #endif
1352 
1353  if (hpcrun_is_initialized()) {
1354  lushPthr_spinTrylock_post(&TD_GET(pthr_metrics), lock, ret);
1355  }
1356 
1357  return ret;
1358 }
1359 
1360 
1361 int
1362 MONITOR_EXT_WRAP_NAME(pthread_spin_unlock)(pthread_spinlock_t* lock)
1363 {
1365  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1366 
1367  pthread_spinlock_t* real_lock = lock;
1368  if (hpcrun_is_initialized()) {
1369  real_lock = lushPthr_spinUnlock_pre(&TD_GET(pthr_metrics), lock);
1370  }
1371 
1372 #if (LUSH_PTHR_FN_TY == 3)
1373  int ret = lushPthr_spin_unlock(lock);
1374 #else
1375  int ret = (*real_spin_unlock)(real_lock);
1376 #endif
1377 
1378  if (hpcrun_is_initialized()) {
1379  lushPthr_spinUnlock_post(&TD_GET(pthr_metrics), lock /*,ret*/);
1380  }
1381 
1382  return ret;
1383 }
1384 
1385 
1386 int
1387 MONITOR_EXT_WRAP_NAME(pthread_spin_destroy)(pthread_spinlock_t* lock)
1388 {
1389  MONITOR_EXT_GET_NAME_WRAP(real_spin_destroy, pthread_spin_destroy);
1390  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1391 
1392  pthread_spinlock_t* real_lock = lock;
1393  if (hpcrun_is_initialized()) {
1394  real_lock = lushPthr_spinDestroy_pre(&TD_GET(pthr_metrics), lock);
1395  }
1396 
1397  int ret = (*real_spin_destroy)(real_lock);
1398 
1399  if (hpcrun_is_initialized()) {
1400  lushPthr_spinDestroy_post(&TD_GET(pthr_metrics), lock /*,ret*/);
1401  }
1402 
1403  return ret;
1404 }
1405 
1406 #endif // LUSH_PTHREADS
1407 
1408 
1409 // ---------------------------------------------------------
1410 // cond_wait
1411 // ---------------------------------------------------------
1412 
1413 #ifdef LUSH_PTHREADS
1414 
1415 typedef int cond_init_fcn(pthread_cond_t *, const pthread_condattr_t *);
1416 typedef int cond_destroy_fcn(pthread_cond_t *);
1417 typedef int cond_wait_fcn(pthread_cond_t *, pthread_mutex_t *);
1418 typedef int cond_timedwait_fcn(pthread_cond_t *, pthread_mutex_t *,
1419  const struct timespec *);
1420 typedef int cond_signal_fcn(pthread_cond_t *);
1421 
1422 #ifdef HPCRUN_STATIC_LINK
1423 extern cond_init_fcn __real_pthread_cond_init;
1424 extern cond_destroy_fcn __real_pthread_cond_destroy;
1425 extern cond_wait_fcn __real_pthread_cond_wait;
1426 extern cond_timedwait_fcn __real_pthread_cond_timedwait;
1427 extern cond_signal_fcn __real_pthread_cond_signal;
1428 extern cond_signal_fcn __real_pthread_cond_broadcast;
1429 #endif // HPCRUN_STATIC_LINK
1430 
1431 static cond_init_fcn *real_cond_init = NULL;
1432 static cond_destroy_fcn *real_cond_destroy = NULL;
1433 static cond_wait_fcn *real_cond_wait = NULL;
1434 static cond_timedwait_fcn *real_cond_timedwait = NULL;
1435 static cond_signal_fcn *real_cond_signal = NULL;
1436 static cond_signal_fcn *real_cond_broadcast = NULL;
1437 
1438 
1439 // N.B.: glibc defines multiple versions of the cond-wait functions.
1440 // For some reason, dlsym-ing any one routine does *not* necessarily
1441 // obtain the correct version. It turns out to be necessary to
1442 // override a 'covering set' of the cond-wait functions to obtain a
1443 // consistent set.
1444 
1445 int
1446 MONITOR_EXT_WRAP_NAME(pthread_cond_init)(pthread_cond_t* cond,
1447  const pthread_condattr_t* attr)
1448 {
1449  MONITOR_EXT_GET_NAME_WRAP(real_cond_init, pthread_cond_init);
1450  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1451  return (*real_cond_init)(cond, attr);
1452 }
1453 
1454 
1455 int
1456 MONITOR_EXT_WRAP_NAME(pthread_cond_destroy)(pthread_cond_t* cond)
1457 {
1458  MONITOR_EXT_GET_NAME_WRAP(real_cond_destroy, pthread_cond_destroy);
1459  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1460  return (*real_cond_destroy)(cond);
1461 }
1462 
1463 
1464 int
1465 MONITOR_EXT_WRAP_NAME(pthread_cond_wait)(pthread_cond_t* cond,
1466  pthread_mutex_t* mutex)
1467 {
1469  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1470 
1471  if (hpcrun_is_initialized()) {
1472  lushPthr_condwait_pre(&TD_GET(pthr_metrics));
1473  }
1474 
1475  int ret = (*real_cond_wait)(cond, mutex);
1476 
1477  if (hpcrun_is_initialized()) {
1478  lushPthr_condwait_post(&TD_GET(pthr_metrics) /*,ret*/);
1479  }
1480 
1481  return ret;
1482 }
1483 
1484 
1485 int
1486 MONITOR_EXT_WRAP_NAME(pthread_cond_timedwait)(pthread_cond_t* cond,
1487  pthread_mutex_t* mutex,
1488  const struct timespec* tspec)
1489 {
1490  MONITOR_EXT_GET_NAME_WRAP(real_cond_timedwait, pthread_cond_timedwait);
1491  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1492 
1493  if (hpcrun_is_initialized()) {
1494  lushPthr_condwait_pre(&TD_GET(pthr_metrics));
1495  }
1496 
1497  int ret = (*real_cond_timedwait)(cond, mutex, tspec);
1498 
1499  if (hpcrun_is_initialized()) {
1500  lushPthr_condwait_post(&TD_GET(pthr_metrics) /*,ret*/);
1501  }
1502 
1503  return ret;
1504 }
1505 
1506 
1507 int
1508 MONITOR_EXT_WRAP_NAME(pthread_cond_signal)(pthread_cond_t* cond)
1509 {
1511  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1512  return (*real_cond_signal)(cond);
1513 }
1514 
1515 
1516 int
1517 MONITOR_EXT_WRAP_NAME(pthread_cond_broadcast)(pthread_cond_t* cond)
1518 {
1519  MONITOR_EXT_GET_NAME_WRAP(real_cond_broadcast, pthread_cond_broadcast);
1520  if (0) { TMSG(MONITOR_EXTS, "%s", __func__); }
1521  return (*real_cond_broadcast)(cond);
1522 }
1523 
1524 #endif // LUSH_PTHREADS
1525 
1526 
1527 //***************************************************************************
1528 // dynamic linking control (via libmonitor)
1529 //***************************************************************************
1530 
1531 
1532 #ifndef HPCRUN_STATIC_LINK
1533 
1534 void
1535 monitor_pre_dlopen(const char* path, int flags)
1536 {
1537  if (! hpcrun_is_initialized()) {
1538  return;
1539  }
1540  if (! hpcrun_safe_enter()) {
1541  return;
1542  }
1543  hpcrun_pre_dlopen(path, flags);
1544  hpcrun_safe_exit();
1545 }
1546 
1547 
1548 void
1549 monitor_dlopen(const char *path, int flags, void* handle)
1550 {
1551  if (! hpcrun_is_initialized()) {
1552  return;
1553  }
1554  if (! hpcrun_safe_enter()) {
1555  return;
1556  }
1557  hpcrun_dlopen(path, flags, handle);
1558  hpcrun_safe_exit();
1559 }
1560 
1561 
1562 void
1563 monitor_dlclose(void* handle)
1564 {
1565  if (! hpcrun_is_initialized()) {
1566  return;
1567  }
1569  hpcrun_dlclose(handle);
1570  hpcrun_safe_exit();
1571 }
1572 
1573 
1574 void
1575 monitor_post_dlclose(void* handle, int ret)
1576 {
1577  if (! hpcrun_is_initialized()) {
1578  return;
1579  }
1581  hpcrun_post_dlclose(handle, ret);
1582  hpcrun_safe_exit();
1583 }
1584 
1585 #endif /* ! HPCRUN_STATIC_LINK */
#define Token_iterate(tok, s, delim, b)
Definition: token-iter.h:4
void monitor_fini_thread(void *init_thread_data)
Definition: main.c:1092
int OVERRIDE_NM() pthread_cond_broadcast(pthread_cond_t *cond)
int __real_pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
cct_ctxt_t * csdata_ctxt
Definition: epoch.h:66
#define STDERR_MSG(...)
Definition: messages.h:89
static void lushPthr_spinLock_post(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock)
void hpcrun_init_pthread_key(void)
Definition: thread_data.c:96
void hpcrun_files_set_executable(char *execname)
Definition: files.c:420
static fork_data_t from_fork
Definition: main.c:889
void monitor_fini_process(int how, void *data)
Definition: main.c:875
size_t monitor_reset_stacksize(size_t old_size)
Definition: main.c:1109
static void logit(cct_node_t *n, cct_op_arg_t arg, size_t l)
Definition: main.c:664
void hpcrun_set_thread0_data(void)
Definition: thread_data.c:108
void hpcrun_wait()
Definition: main.c:765
static void hpcrun_process_aux_cleanup_action()
Definition: main.c:581
#define SAMPLE_SOURCES(op,...)
void hpcrun_threadMgr_data_fini(thread_data_t *td)
Definition: threadmgr.c:354
void monitor_dlclose(void *handle)
Definition: main.c:1563
cct_ctxt_t * thr_ctxt
Definition: main.c:151
static int dump_interval_handler(int sig, siginfo_t *info, void *ctxt) __attribute__((unused))
Definition: main.c:377
static int lushPthr_spin_unlock(atomic_pthread_spinlock_t *lock)
Definition: lush-pthread.h:847
void hpcrun_set_thread_data(thread_data_t *td)
Definition: thread_data.c:116
int flag
Definition: main.c:155
cct_ctxt_t * parent
Definition: cct_ctxt.h:68
siglongjmp
Definition: names.cpp:1
static int abort_timeout_handler(int sig, siginfo_t *siginfo, void *context)
Definition: main.c:344
static char * tmp
Definition: tokenize.c:63
void hpcrun_process_sample_source_none(void)
Definition: none.c:200
void hpcrun_memory_reinit(void)
Definition: mem.c:212
void hpcrun_mmap_init(void)
Definition: mmap.c:94
void hpcrun_process_aux_cleanup_remove(hpcrun_aux_cleanup_t *node)
Definition: main.c:560
static void hpcrun_safe_exit(void)
int hpcrun_options__getopts(hpcrun_options_t *x)
static atomic_pthread_spinlock_t * lushPthr_spinLock_pre(lushPthr_t *restrict x, atomic_pthread_spinlock_t *lock)
void hpcrun_trace_open(core_profile_trace_data_t *cptd)
Definition: trace.c:124
void monitor_post_dlclose(void *handle, int ret)
Definition: main.c:1575
void messages_logfile_create()
void * hpcrun_get_addr_main(void)
Definition: main.c:278
void monitor_thread_post_create(void *data)
Definition: main.c:1047
int fnbounds_init()
static atomic_pthread_spinlock_t * lushPthr_spinUnlock_pre(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock)
void * monitor_init_thread(int tid, void *data)
Definition: main.c:1061
void hpcrun_files_set_directory()
Definition: files.c:383
void hpcrun_sample_sources_from_eventlist(char *evl)
void monitor_init_thread_support(void)
Definition: main.c:983
void hpcrun_threadmgr_thread_delete()
Definition: threadmgr.c:225
void hpcrun_init_internal(bool is_child)
Definition: main.c:388
static void lushPthr_mutexLock_pre(lushPthr_t *restrict x, pthread_mutex_t *restrict lock)
static void lushPthr_spinTrylock_post(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock, int result)
int hpcrun_setup_segv()
Definition: segv_handler.c:168
#define MONITOR_EXT_WRAP_NAME(name)
Definition: monitor_ext.h:92
static void spinlock_unlock(spinlock_t *l)
Definition: spinlock.h:96
void hpcrun_stats_reinit(void)
Definition: hpcrun_stats.c:87
const char * HPCRUN_EVENT_LIST
Definition: env.c:55
void hpcrun_threadMgr_data_put(epoch_t *epoch, thread_data_t *data)
Definition: threadmgr.c:310
void hpcrun_sample_prob_mesg(void)
Definition: sample_prob.c:209
bool hpcrun_is_initialized()
Definition: main.c:272
hpcrun_aux_cleanup_t * hpcrun_process_aux_cleanup_add(void(*func)(void *), void *arg)
Definition: main.c:540
size_t hpcrun_get_num_sample_sources(void)
void hpcrun_pre_dlopen(const char *path, int flags)
Definition: hpcrun_dlfns.c:179
void * monitor_init_process(int *argc, char **argv, void *data)
Definition: main.c:785
Definition: fmt.c:108
cct_node_t * node
Definition: cct.c:128
struct fork_data_t fork_data_t
static void * main_addr
Definition: main.c:203
static __thread u32 tid
void hpcrun_walk_path(cct_node_t *node, cct_op_t op, cct_op_arg_t arg)
Definition: cct.c:636
void * monitor_thread_pre_create(void)
Definition: main.c:996
void hpcrun_thread_data_init(int id, cct_ctxt_t *thr_ctxt, int is_child, size_t n_sources)
Definition: thread_data.c:265
static void lushPthr_spinDestroy_post(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock)
void hpcrun_do_custom_init(void)
static void lushPthr_condwait_pre(lushPthr_t *x)
char lush_agent_paths[CSPROF_PATH_SZ]
void hpcrun_itimer_wallclock_ok(bool flag)
Definition: itimer.c:215
mcs_lock_t lock
#define hpcrun_get_thread_epoch()
Definition: thread_data.h:278
void * cct_op_arg_t
Definition: cct.h:186
void hpcrun_stats_print_summary(void)
Definition: hpcrun_stats.c:339
void hpcrun_registered_sources_init(void)
static sigjmp_buf ivd_jb
Definition: main.c:372
bool hpcrun_is_safe_to_sync(const char *fn)
Definition: main.c:314
static spinlock_t hpcrun_aux_cleanup_lock
Definition: main.c:211
static void * main_upper_dl
Definition: main.c:209
int lush_agent_pool__fini(lush_agent_pool_t *x)
Definition: lush.c:203
void monitor_init_mpi(int *argc, char ***argv)
Definition: main.c:964
bool hpcrun_threadMgr_data_get(int id, cct_ctxt_t *thr_ctxt, thread_data_t **data)
Definition: threadmgr.c:275
static void lushPthr_mutexLock_post(lushPthr_t *restrict x, pthread_mutex_t *restrict lock)
void hpcrun_threadmgr_thread_new()
Definition: threadmgr.c:218
static siglongjmp_fcn * real_siglongjmp
Definition: main.c:1139
void hpcrun_dump_intervals(void *addr)
void hpcrun_epoch_init(cct_ctxt_t *ctxt)
Definition: epoch.c:72
fnbounds_table_t fnbounds_fetch_executable_table(void)
static void hpcrun_set_abort_timeout()
Definition: main.c:355
exit
Definition: names.cpp:1
struct local_thread_data_t local_thread_data_t
void hpcrun_threaded_data(void)
Definition: thread_data.c:195
#define MONITOR_EXT_GET_NAME_WRAP(var, name)
Definition: monitor_ext.h:94
static atomic_pthread_spinlock_t * lushPthr_spinDestroy_pre(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock)
#define EMSG
Definition: messages.h:70
void hpcrun_init_thread_support()
Definition: main.c:654
void hpcrun_post_dlclose(void *handle, int ret)
Definition: hpcrun_dlfns.c:225
int hpcrun_options__init(hpcrun_options_t *x)
void(* func)(void *)
Definition: main.c:170
void monitor_post_fork(pid_t child, void *data)
Definition: main.c:917
void hpcrun_set_real_siglongjmp(void)
Definition: main.c:1148
_local_const
Definition: main.c:164
void hpcrun_sample_prob_init(void)
Definition: sample_prob.c:168
int OVERRIDE_NM() pthread_spin_lock(pthread_spinlock_t *lock)
static hpcrun_aux_cleanup_t * hpcrun_aux_cleanup_list_head
Definition: main.c:212
static void setup_main_bounds_check(void *main_addr)
Definition: main.c:220
void hpcrun_set_retain_recursion_mode(bool mode)
#define RTLD_NEXT
Definition: monitor_ext.h:76
static char buf[32]
Definition: StrUtil.cpp:240
void __attribute__((weak))
Definition: hpctoolkit.c:64
int lush_metrics
Definition: main.c:188
#define GET_NEW_AUX_CLEANUP_NODE(node_ptr)
Definition: main.c:524
void lushPthr_processInit()
Definition: lush-pthread.c:147
bool is_child
Definition: main.c:156
void monitor_pre_dlopen(const char *path, int flags)
Definition: main.c:1535
Definition: epoch.h:64
void * hpcrun_malloc(size_t size)
Definition: mem.c:275
static void lushPthr_mutexUnlock_post(lushPthr_t *restrict x, pthread_mutex_t *restrict lock)
void messages_init()
void * monitor_pre_fork(void)
Definition: main.c:892
void hpcrun_fini_internal()
Definition: main.c:603
#define TD_GET(field)
Definition: thread_data.h:256
static int lushPthr_spin_lock(atomic_pthread_spinlock_t *lock)
Definition: lush-pthread.h:788
static void spinlock_lock(spinlock_t *l)
Definition: spinlock.h:111
static bool hpcrun_is_initialized_private
Definition: main.c:201
void hpcrun_start_stop_internal_init(void)
Definition: start-stop.c:84
struct hpcrun_aux_cleanup_t * next
Definition: main.c:172
void hpcrun_set_safe_to_sync(void)
Definition: main.c:320
int32_t hpcrun_cct_persistent_id(cct_node_t *x)
Definition: cct.c:363
void hpcrun_set_using_threads(bool flag)
Definition: thread_use.c:74
void fnbounds_fini()
void hpcrun_thread_fini(epoch_t *epoch)
Definition: main.c:722
void siglongjmp_fcn(sigjmp_buf, int)
Definition: main.h:63
static char execname[PATH_MAX]
Definition: main.c:214
int OVERRIDE_NM() pthread_spin_unlock(pthread_spinlock_t *lock)
static bool safe_to_sync_sample
Definition: main.c:202
void hpcrun_continue()
Definition: main.c:758
int OVERRIDE_NM() pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)
#define TMSG(f,...)
Definition: messages.h:93
static void * main_upper
Definition: main.c:205
void hpcrun_unw_init()
static void hpcrun_enable_sampling(void)
Definition: sample_event.h:86
static atomic_pthread_spinlock_t * lushPthr_spinTrylock_pre(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock)
int OVERRIDE_NM() pthread_mutex_lock(pthread_mutex_t *mutex)
void hpcrun_unthreaded_data(void)
Definition: thread_data.c:187
void hpcrun_trace_init()
Definition: trace.c:114
static void lushPthr_condwait_post(lushPthr_t *x)
#define EEMSG(...)
Definition: messages.h:90
#define NULL
Definition: ElfHelper.cpp:85
cct_node_t * hpcrun_gen_thread_ctxt(void *context)
Definition: sample_event.c:322
static hpcrun_options_t opts
Definition: main.c:200
longjmp
Definition: names.cpp:1
#define ADD_TO_FREE_AUX_CLEANUP_LIST(node_ptr)
Definition: main.c:533
void monitor_mpi_pre_init(void)
Definition: main.c:949
static int lushPthr_spin_trylock(atomic_pthread_spinlock_t *lock)
Definition: lush-pthread.h:819
char * hpcrun_get_execname(void)
Definition: main.c:304
static void lushPthr_mutexTrylock_post(lushPthr_t *restrict x, pthread_mutex_t *restrict lock, int result)
static void hpcrun_disable_sampling(void)
Definition: sample_event.h:79
static void lushPthr_thread_fini(lushPthr_t *x)
void * hpcrun_thread_init(int id, local_thread_data_t *local_thread_data)
Definition: main.c:675
Definition: cct.c:96
int hpctoolkit_sampling_is_active(void)
Definition: start-stop.c:100
static void * main_lower_dl
Definition: main.c:208
static void * main_lower
Definition: main.c:204
int OVERRIDE_NM() pthread_cond_signal(pthread_cond_t *cond)
static void * main_addr_dl
Definition: main.c:207
void monitor_dlopen(const char *path, int flags, void *handle)
Definition: main.c:1549
bool hpcrun_get_disabled(void)
Definition: disabled.c:80
_exit
Definition: names.cpp:1
cct_addr_t * addr
Definition: cct.c:130
void hpcrun_initLoadmap()
Definition: loadmap.c:489
siglongjmp_fcn * hpcrun_get_real_siglongjmp(void)
Definition: main.c:1142
cct_node_t * context
Definition: cct_ctxt.h:67
void messages_fini(void)
static void lushPthr_spinUnlock_post(lushPthr_t *restrict x, atomic_pthread_spinlock_t *restrict lock)
<!-- ********************************************************************--> n<!-- HPCToolkit Experiment DTD --> n<!-- Version 2.1 --> n<!-- ********************************************************************--> n<!ELEMENT HPCToolkitExperiment(Header,(SecCallPathProfile|SecFlatProfile) *)> n<!ATTLIST HPCToolkitExperiment\n version CDATA #REQUIRED > n n<!-- ******************************************************************--> n n<!-- Info/NV:flexible name-value pairs:(n) ame;(t) ype;(v) alue --> n<!ELEMENT Info(NV *)> n<!ATTLIST Info\n n CDATA #IMPLIED > n<!ELEMENT NV EMPTY > n<!ATTLIST NV\n n CDATA #REQUIRED\n t CDATA #IMPLIED\n v CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Header --> n<!-- ******************************************************************--> n<!ELEMENT Header(Info *)> n<!ATTLIST Header\n n CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Section Header --> n<!-- ******************************************************************--> n<!ELEMENT SecHeader(MetricTable?, MetricDBTable?, TraceDBTable?, LoadModuleTable?, FileTable?, ProcedureTable?, Info *)> n n<!-- MetricTable:--> n<!ELEMENT MetricTable(Metric) * > n n<!-- Metric:(i) d;(n) ame --> n<!--(v) alue-type:transient type of values --> n<!--(t) ype:persistent type of metric --> n<!-- fmt:format;show;--> n<!ELEMENT Metric(MetricFormula *, Info?)> n<!ATTLIST Metric\n i CDATA #REQUIRED\n n CDATA #REQUIRED\n es CDATA #IMPLIED\n em CDATA #IMPLIED\n ep CDATA #IMPLIED\n v(raw|final|derived-incr|derived) \"raw\\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ fmt CDATA #IMPLIED\ show (1|0) \1\\ show-percent (1|0) \1> n n<!-- MetricFormula represents derived metrics: (t)ype; (frm): formula --> n<!ELEMENT MetricFormula (Info?)> n<!ATTLIST MetricFormula\ t (combine|finalize) \finalize\\ i CDATA #IMPLIED\ frm CDATA #REQUIRED> n n<!-- Metric data, used in sections: (n)ame [from Metric]; (v)alue --> n<!ELEMENT M EMPTY> n<!ATTLIST M\ n CDATA #REQUIRED\ v CDATA #REQUIRED> n n<!-- MetricDBTable: --> n<!ELEMENT MetricDBTable (MetricDB)*> n n<!-- MetricDB: (i)d; (n)ame --> n<!-- (t)ype: persistent type of metric --> n<!-- db-glob: file glob describing files in metric db --> n<!-- db-id: id within metric db --> n<!-- db-num-metrics: number of metrics in db --> n<!-- db-header-sz: size (in bytes) of a db file header --> n<!ELEMENT MetricDB EMPTY> n<!ATTLIST MetricDB\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ db-glob CDATA #IMPLIED\ db-id CDATA #IMPLIED\ db-num-metrics CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- TraceDBTable: --> n<!ELEMENT TraceDBTable (TraceDB)> n n<!-- TraceDB: (i)d --> n<!-- db-min-time: min beginning time stamp (global) --> n<!-- db-max-time: max ending time stamp (global) --> n<!ELEMENT TraceDB EMPTY> n<!ATTLIST TraceDB\ i CDATA #REQUIRED\ db-glob CDATA #IMPLIED\ db-min-time CDATA #IMPLIED\ db-max-time CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- LoadModuleTable assigns a short name to a load module --> n<!ELEMENT LoadModuleTable (LoadModule)*> n n<!ELEMENT LoadModule (Info?)> n<!ATTLIST LoadModule\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- FileTable assigns a short name to a file --> n<!ELEMENT FileTable (File)*> n n<!ELEMENT File (Info?)> n<!ATTLIST File\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- ProcedureTable assigns a short name to a procedure --> n<!ELEMENT ProcedureTable (Procedure)*> n n<!-- Info/NV: flexible name-value pairs: (n)ame; (t)ype; (v)alue --> n<!-- f: family of the procedure (fake, root, ...)--> n<!ELEMENT Procedure (Info?)> n<!ATTLIST Procedure\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ f CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Call path profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecCallPathProfile (SecHeader, SecCallPathProfileData)> n<!ATTLIST SecCallPathProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecCallPathProfileData (PF|M)*> n<!-- Procedure frame --> n<!-- (i)d: unique identifier for cross referencing --> n<!-- (s)tatic scope id --> n<!-- (n)ame: a string or an id in ProcedureTable --> n<!-- (lm) load module: a string or an id in LoadModuleTable --> n<!-- (f)ile name: a string or an id in LoadModuleTable --> n<!-- (l)ine range: \beg-end\ (inclusive range) --> n<!-- (a)lien: whether frame is alien to enclosing P --> n<!-- (str)uct: hpcstruct node id --> n<!-- (t)ype: hpcrun node type: memory access, variable declaration, ... --> n<!-- (v)ma-range-set: \{[beg-end), [beg-end)...}\ --> n<!ELEMENT PF (PF|Pr|L|C|S|M)*> n<!ATTLIST PF\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Procedure (static): GOAL: replace with 'P' --> n<!ELEMENT Pr (Pr|L|C|S|M)*> n<!ATTLIST Pr\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ a (1|0) \0\\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Callsite (a special StatementRange) --> n<!ELEMENT C (PF|M)*> n<!ATTLIST C\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Flat profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecFlatProfile (SecHeader, SecFlatProfileData)> n<!ATTLIST SecFlatProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecFlatProfileData (LM|M)*> n<!-- Load module: (i)d; (n)ame; (v)ma-range-set --> n<!ELEMENT LM (F|P|M)*> n<!ATTLIST LM\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ v CDATA #IMPLIED> n<!-- File --> n<!ELEMENT F (P|L|S|M)*> n<!ATTLIST F\ i CDATA #IMPLIED\ n CDATA #REQUIRED> n<!-- Procedure (Note 1) --> n<!ELEMENT P (P|A|L|S|C|M)*> n<!ATTLIST P\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Alien (Note 1) --> n<!ELEMENT A (A|L|S|C|M)*> n<!ATTLIST A\ i CDATA #IMPLIED\ f CDATA #IMPLIED\ n CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Loop (Note 1,2) --> n<!ELEMENT L (A|Pr|L|S|C|M)*> n<!ATTLIST L\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ f CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Statement (Note 2) --> n<!-- (it): trace record identifier --> n<!ELEMENT S (S|M)*> n<!ATTLIST S\ i CDATA #IMPLIED\ it CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Note 1: Contained Cs may not contain PFs --> n<!-- Note 2: The 's' attribute is not used for flat profiles --> n
void monitor_real_abort(void)
void hpcrun_dlopen(const char *module_name, int flags, void *handle)
Definition: hpcrun_dlfns.c:193
static void copy_execname(char *process_name)
Definition: main.c:258
void * hpcrun_context_pc(void *context)
struct hpcrun_aux_cleanup_t * prev
Definition: main.c:173
static hpcrun_aux_cleanup_t * hpcrun_aux_cleanup_free_list_head
Definition: main.c:213
int lush_agent_pool__init(lush_agent_pool_t *x, const char *path)
Definition: lush.c:168
__thread bool hpcrun_thread_suppress_sample
Definition: main.c:193
#define SPINLOCK_UNLOCKED
Definition: spinlock.h:84
lush_agent_pool_t * lush_agents
bool fnbounds_enclosing_addr(void *ip, void **start, void **end, load_module_t **lm)
#define MONITOR_EXT_GET_NAME(var, name)
Definition: monitor_ext.h:93
static int hpcrun_safe_enter(void)
bool hpcrun_inbounds_main(void *addr)
Definition: main.c:284
int OVERRIDE_NM() pthread_mutex_unlock(pthread_mutex_t *mutex)
#define ENABLED(f)
Definition: debug-flag.h:76
void hpcrun_dlclose(void *handle)
Definition: hpcrun_dlfns.c:213
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition: thread_data.c:168
volatile int HPCRUN_DEBUGGER_WAIT
Definition: main.c:755
static void hpcrun_logicalUnwind(bool x)
cct_addr_t * hpcrun_cct_addr(cct_node_t *node)
Definition: cct.c:369