HPCToolkit
itimer.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 // itimer sample source simple oo interface
49 //
50 
51 /******************************************************************************
52  * system includes
53  *****************************************************************************/
54 
55 #include <errno.h>
56 #include <stdbool.h>
57 #include <stddef.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <assert.h>
61 
62 #include <signal.h>
63 #include <sys/time.h> /* setitimer() */
64 #include <ucontext.h> /* struct ucontext */
65 #include <time.h>
66 #include <unistd.h>
67 
68 #include <include/hpctoolkit-config.h>
69 #ifdef ENABLE_CLOCK_REALTIME
70 #include <sys/syscall.h>
71 #endif
72 
73 
74 /******************************************************************************
75  * libmonitor
76  *****************************************************************************/
77 
78 #include <monitor.h>
79 
80 
81 /******************************************************************************
82  * local includes
83  *****************************************************************************/
84 
85 #include "sample_source_obj.h"
86 #include "common.h"
87 #include "ss-errno.h"
88 
89 #include <hpcrun/hpcrun_options.h>
90 #include <hpcrun/hpcrun_stats.h>
91 
92 #include <hpcrun/metrics.h>
93 #include <hpcrun/safe-sampling.h>
94 #include <hpcrun/sample_event.h>
96 #include <hpcrun/thread_data.h>
97 
98 #include <lush/lush-backtrace.h>
99 #include <messages/messages.h>
100 
101 #include <utilities/tokenize.h>
103 
104 #include <unwind/common/unwind.h>
105 
106 #include <lib/support-lean/timer.h>
107 
109 
110 
111 
112 /******************************************************************************
113  * macros
114  *****************************************************************************/
115 
116 // Note: it's not clear if CLOCK_THREAD_CPUTIME_ID or
117 // CLOCK_PROCESS_CPUTIME_ID is a better clock for CPUTIME. The docs
118 // would say THREAD, but experiments suggest that PROCESS plus
119 // SIGEV_THREAD_ID is also thread-specific and it seems that THREAD is
120 // limited by the kernel Hz rate.
121 
122 // Implement WALLCLOCK as CPUTIME where possible, except on Blue Gene
123 // where we need to use ITIMER.
124 
125 #define IDLE_METRIC_NAME "idleness (usec)"
126 
127 #define WALLCLOCK_EVENT_NAME "WALLCLOCK"
128 #define WALLCLOCK_METRIC_NAME "WALLCLOCK (usec)"
129 
130 #define ITIMER_EVENT_NAME "ITIMER"
131 #define ITIMER_METRIC_NAME "ITIMER (usec)"
132 #define ITIMER_SIGNAL SIGPROF
133 #define ITIMER_TYPE ITIMER_PROF
134 
135 #define REALTIME_EVENT_NAME "REALTIME"
136 #define REALTIME_METRIC_NAME "REALTIME (usec)"
137 #define REALTIME_SIGNAL (SIGRTMIN + 3)
138 
139 #define REALTIME_CLOCK_TYPE CLOCK_REALTIME
140 #define REALTIME_NOTIFY_METHOD SIGEV_THREAD_ID
141 
142 #define CPUTIME_EVENT_NAME "CPUTIME"
143 #define CPUTIME_METRIC_NAME "CPUTIME (usec)"
144 #define CPUTIME_CLOCK_TYPE CLOCK_THREAD_CPUTIME_ID
145 
146 // the man pages cite sigev_notify_thread_id in struct sigevent,
147 // but often the only name is a hidden union name.
148 #ifndef sigev_notify_thread_id
149 #define sigev_notify_thread_id _sigev_un._tid
150 #endif
151 
152 #if !defined(HOST_SYSTEM_IBM_BLUEGENE)
153 #define USE_ELAPSED_TIME_FOR_WALLCLOCK
154 #endif
155 
156 #ifdef USE_ELAPSED_TIME_FOR_WALLCLOCK
157 #define sample_period 1
158 #else
159 #define sample_period period
160 #endif
161 
162 #define DEFAULT_PERIOD 5000L
163 
164 
165 /******************************************************************************
166  * local constants
167  *****************************************************************************/
168 
170  ITIMER_EVENT = 0 // itimer has only 1 event
171 };
172 
173 
174 /******************************************************************************
175  * forward declarations
176  *****************************************************************************/
177 
178 static int
179 itimer_signal_handler(int sig, siginfo_t *siginfo, void *context);
180 
181 
182 /******************************************************************************
183  * local variables
184  *****************************************************************************/
185 
186 static bool use_itimer = false;
187 static bool use_realtime = false;
188 static bool use_cputime = false;
189 
190 static char *the_event_name = "unknown";
191 static char *the_metric_name = "unknown";
192 static int the_signal_num = 0;
193 
194 static long period = DEFAULT_PERIOD;
195 
196 static struct itimerval itval_start;
197 static struct itimerval itval_stop;
198 
199 static struct itimerspec itspec_start;
200 static struct itimerspec itspec_stop;
201 
202 static sigset_t timer_mask;
203 
204 static __thread bool wallclock_ok = false;
205 
206 /******************************************************************************
207  * external thread-local variables
208  *****************************************************************************/
209 extern __thread bool hpcrun_thread_suppress_sample;
210 
211 // ****************************************************************************
212 // * public helper function
213 // ****************************************************************************
214 
216 {
217  wallclock_ok = flag;
218 }
219 
220 /******************************************************************************
221  * internal helper functions
222  *****************************************************************************/
223 
224 // Helper functions return the result of the syscall, so 0 on success,
225 // or else -1 on failure. We handle errors in the caller.
226 
227 static int
229 {
230  int ret = 0;
231 
232 #ifdef ENABLE_CLOCK_REALTIME
233  if (! td->timer_init) {
234  memset(&td->sigev, 0, sizeof(td->sigev));
235  td->sigev.sigev_notify = REALTIME_NOTIFY_METHOD;
236  td->sigev.sigev_signo = REALTIME_SIGNAL;
237  td->sigev.sigev_value.sival_ptr = &td->timerid;
238  td->sigev.sigev_notify_thread_id = syscall(SYS_gettid);
239 
240  clockid_t clock = REALTIME_CLOCK_TYPE;
241 #ifdef ENABLE_CLOCK_CPUTIME
242  if (use_cputime) {
243  clock = CPUTIME_CLOCK_TYPE;
244  }
245 #endif
246  ret = timer_create(clock, &td->sigev, &td->timerid);
247  if (ret == 0) {
248  td->timer_init = true;
249  }
250  }
251 #endif
252 
253  return ret;
254 }
255 
256 static int
258 {
259  int ret = 0;
260 
261 #ifdef ENABLE_CLOCK_REALTIME
262  if (td->timer_init) {
263  ret = timer_delete(td->timerid);
264  td->timerid = NULL;
265  }
266  td->timer_init = false;
267 #endif
268 
269  return ret;
270 }
271 
272 // While handling a sample, the shutdown signal handler may asynchronously
273 // delete a thread's timer and set it to NULL. Calling timer_settime on a
274 // deleted timer will return an error. Calling timer_settime on a NULL
275 // timer will SEGV. For that reason, calling timer_settime(td->timerid, ...)
276 // is unsafe as td->timerid can be set to NULL immediately before it is
277 // loaded as an argument. To avoid a SEGV, copy the timer into a local
278 // variable, test it, and only call timer_settime with a non-NULL timer.
279 static int
280 hpcrun_settime(thread_data_t *td, struct itimerspec *spec)
281 {
282  if (!td->timer_init) return -1; // fail: timer not initialized
283 
284  timer_t mytimer = td->timerid;
285  if (mytimer == NULL) return -1; // fail: timer deleted
286 
287  return timer_settime(mytimer, 0, spec, NULL);
288 }
289 
290 static int
292 {
293 #ifdef ENABLE_CLOCK_REALTIME
294  if (use_realtime || use_cputime) {
295  return hpcrun_settime(td, &itspec_start);
296  }
297 #endif
298 
299  return setitimer(ITIMER_TYPE, &itval_start, NULL);
300 }
301 
302 static int
304 {
305 #ifdef ENABLE_CLOCK_REALTIME
306  if (use_realtime || use_cputime) {
307  int ret = hpcrun_settime(td, &itspec_stop);
308 
309  // If timer is invalid, it is not active; treat it as stopped
310  // and ignore any error code that may have been returned by
311  // hpcrun_settime
312  if ((!td->timer_init) || (!td->timerid)) return 0;
313 
314  return ret;
315  }
316 #endif
317 
318  return setitimer(ITIMER_TYPE, &itval_stop, NULL);
319 }
320 
321 // Factor out the body of the start method so we can restart itimer
322 // without messages in the case that we are interrupting our own code.
323 // safe = 1 if not inside our code, so ok to print debug messages
324 //
325 static void
327 {
328  int ret;
329 
330  // if thread data is unavailable, assume that all sample source ops
331  // are suspended.
332  if (! hpcrun_td_avail()) {
333  if (safe) {
334  TMSG(ITIMER_CTL, "Thread data unavailable ==> sampling suspended");
335  }
336  return;
337  }
339 
340  if (safe) {
341  TMSG(ITIMER_HANDLER, "starting %s: value = (%d,%d), interval = (%d,%d)",
343  itval_start.it_value.tv_sec,
344  itval_start.it_value.tv_usec,
345  itval_start.it_interval.tv_sec,
346  itval_start.it_interval.tv_usec);
347  }
348 
349  ret = hpcrun_start_timer(td);
350 
351  if (use_realtime || use_cputime) {
352  if ((!td->timer_init) || (!td->timerid)) {
353  // When multiple threads are present, a thread might receive a shutdown
354  // signal while handling a sample. When a shutdown signal is received,
355  // the thread's timer is deleted and set to uninitialized.
356  // In this circumstance, restarting the timer will fail and that
357  // is appropriate. Return without futher action or reporting an error.
358  return;
359  }
360  }
361 
362  if (ret != 0) {
363  if (safe) {
364  TMSG(ITIMER_CTL, "setitimer failed to start!!");
365  EMSG("setitimer failed (%d): %s", errno, strerror(errno));
366  }
367  hpcrun_ssfail_start("itimer");
368  }
369 
370 #ifdef USE_ELAPSED_TIME_FOR_WALLCLOCK
371  ret = time_getTimeReal(&TD_GET(last_time_us));
372  if (ret != 0) {
373  if (safe) {
374  EMSG("time_getTimeReal (clock_gettime) failed!");
375  }
377  }
378 #endif
379 
380  TD_GET(ss_state)[self->sel_idx] = START;
381 }
382 
383 
384 /******************************************************************************
385  * method definitions
386  *****************************************************************************/
387 
388 static void
390 {
391  TMSG(ITIMER_CTL, "init");
393  self->state = INIT;
394 }
395 
396 static void
397 METHOD_FN(thread_init)
398 {
399  TMSG(ITIMER_CTL, "thread init");
400 }
401 
402 static void
403 METHOD_FN(thread_init_action)
404 {
405  TMSG(ITIMER_CTL, "thread init action");
406 }
407 
408 static void
409 METHOD_FN(start)
410 {
411  TMSG(ITIMER_CTL, "start %s", the_event_name);
412 
413  // the realtime clock needs an extra step to create the timer
414  if (use_realtime || use_cputime) {
416  if (hpcrun_create_real_timer(td) != 0) {
417  EEMSG("Unable to create the timer for %s", the_event_name);
419  }
420  }
421 
422  // Since we block a thread's timer signal when stopping, we
423  // must unblock it when starting.
424  monitor_real_pthread_sigmask(SIG_UNBLOCK, &timer_mask, NULL);
425 
426  hpcrun_restart_timer(self, 1);
427 }
428 
429 static void
430 METHOD_FN(thread_fini_action)
431 {
432  TMSG(ITIMER_CTL, "thread fini action");
433 
434  // Delete the realtime timer to avoid a timer leak.
435  if (use_realtime || use_cputime) {
438  }
439 
440 }
441 
442 static void
444 {
445  TMSG(ITIMER_CTL, "stop %s", the_event_name);
446 
447  // We have observed thread-centric profiling signals
448  // (e.g., REALTIME) being delivered to a thread even after
449  // we have stopped the thread's timer. During thread
450  // finalization, this can cause a catastrophic error.
451  // For that reason, we always block the thread's timer
452  // signal when stopping.
453  monitor_real_pthread_sigmask(SIG_BLOCK, &timer_mask, NULL);
454 
456  int rc = hpcrun_stop_timer(td);
457  if (rc != 0) {
458  EMSG("stop %s failed, errno: %d", the_event_name, errno);
459  }
460 
461  TD_GET(ss_state)[self->sel_idx] = STOP;
462 }
463 
464 static void
465 METHOD_FN(shutdown)
466 {
467  METHOD_CALL(self, stop); // make sure stop has been called
468  TMSG(ITIMER_CTL, "shutdown %s", the_event_name);
469  self->state = UNINIT;
470 }
471 
472 static bool
473 METHOD_FN(supports_event, const char *ev_str)
474 {
475  return hpcrun_ev_is(ev_str, ITIMER_EVENT_NAME)
477  || hpcrun_ev_is(ev_str, CPUTIME_EVENT_NAME)
478  || hpcrun_ev_is(ev_str, REALTIME_EVENT_NAME);
479 }
480 
481 static void
482 METHOD_FN(process_event_list, int lush_metrics)
483 {
484  char name[1024]; // local buffer needed for extract_ev_threshold
485 
486  TMSG(ITIMER_CTL, "process event list, lush_metrics = %d", lush_metrics);
487 
488  // fetch the event string for the sample source
489  char* evlist = METHOD_CALL(self, get_event_str);
490  char* event = start_tok(evlist);
491 
492  TMSG(ITIMER_CTL,"checking event spec = %s",event);
493 
494  if (hpcrun_ev_is(event, WALLCLOCK_EVENT_NAME)) {
495 #ifdef HOST_SYSTEM_IBM_BLUEGENE
496  use_itimer = true;
500 #else
501 #ifdef ENABLE_CLOCK_CPUTIME
502  use_cputime = true;
506 #else
507  EEMSG("Event %s (%s) is not available on this system.",
509  hpcrun_ssfail_unknown(event);
510 #endif
511 #endif
512  }
513 
514  if (hpcrun_ev_is(event, REALTIME_EVENT_NAME)) {
515 #ifdef ENABLE_CLOCK_REALTIME
516  use_realtime = true;
520 #else
521  EEMSG("Event %s is not available on this system.", REALTIME_EVENT_NAME);
522  hpcrun_ssfail_unknown(event);
523 #endif
524  }
525 
526  if (hpcrun_ev_is(event, CPUTIME_EVENT_NAME)) {
527 #ifdef ENABLE_CLOCK_CPUTIME
528  use_cputime = true;
532 #else
533  EEMSG("Event %s is not available on this system.", CPUTIME_EVENT_NAME);
534  hpcrun_ssfail_unknown(event);
535 #endif
536  }
537 
538  if (hpcrun_ev_is(event, ITIMER_EVENT_NAME)) {
539  use_itimer = true;
543  }
544 
545  if (!use_itimer && !use_realtime && !use_cputime) {
546  // should never get here if supports_event is true
547  hpcrun_ssfail_unknown(event);
548  }
549 
550  // extract event threshold
551  hpcrun_extract_ev_thresh(event, sizeof(name), name, &period, DEFAULT_PERIOD);
552 
553  // store event threshold
554  METHOD_CALL(self, store_event, ITIMER_EVENT, period);
555  TMSG(OPTIONS,"wallclock period set to %ld",period);
556 
557  // set up file local variables for sample source control
558  int seconds = period / 1000000;
559  int microseconds = period % 1000000;
560 
561  TMSG(ITIMER_CTL, "init %s sample_period = %ld, seconds = %d, usec = %d",
562  the_event_name, period, seconds, microseconds);
563 
564  itval_start.it_value.tv_sec = seconds;
565  itval_start.it_value.tv_usec = microseconds;
566  itval_start.it_interval.tv_sec = 0;
567  itval_start.it_interval.tv_usec = 0;
568 
569  itspec_start.it_value.tv_sec = seconds;
570  itspec_start.it_value.tv_nsec = 1000 * microseconds;
571  itspec_start.it_interval.tv_sec = 0;
572  itspec_start.it_interval.tv_nsec = 0;
573 
574  // older versions of BG/P incorrectly delivered SIGALRM when
575  // interval is zero. I (krentel) believe this is no longer
576  // necessary, but it can't really hurt.
577 #ifdef HOST_SYSTEM_IBM_BLUEGENE
578  itval_start.it_interval.tv_sec = 3600;
579  itspec_start.it_interval.tv_sec = 3600;
580 #endif
581 
582  memset(&itval_stop, 0, sizeof(itval_stop));
583  memset(&itspec_stop, 0, sizeof(itspec_stop));
584 
585  sigemptyset(&timer_mask);
586  sigaddset(&timer_mask, the_signal_num);
587 
588  // handle metric allocation
589  hpcrun_pre_allocate_metrics(1 + lush_metrics);
590 
591  int metric_id = hpcrun_new_metric();
592  METHOD_CALL(self, store_metric_id, ITIMER_EVENT, metric_id);
593 
594  // set metric information in metric table
595  TMSG(ITIMER_CTL, "setting metric timer period = %ld", sample_period);
599  if (lush_metrics == 1) {
600  int mid_idleness = hpcrun_new_metric();
601  lush_agents->metric_time = metric_id;
602  lush_agents->metric_idleness = mid_idleness;
603 
607  }
608 
609  event = next_tok();
610  if (more_tok()) {
611  EEMSG("Can't use multiple timer events in the same run.");
612  hpcrun_ssfail_conflict("timer", event);
613  }
614 }
615 
616 //
617 // There is only 1 event for itimer, hence the event "set" is always the same.
618 // The signal setup, however, is done here.
619 //
620 static void
621 METHOD_FN(gen_event_set, int lush_metrics)
622 {
623  monitor_sigaction(the_signal_num, &itimer_signal_handler, 0, NULL);
624 }
625 
626 static void
627 METHOD_FN(display_events)
628 {
629  printf("===========================================================================\n");
630  printf("Available Timer events\n");
631  printf("===========================================================================\n");
632  printf("Name\t\tDescription\n");
633  printf("---------------------------------------------------------------------------\n");
634  printf("%s\tReal clock time used by the thread in microseconds.\n"
635  "\t\tBased on the CLOCK_REALTIME timer with the SIGEV_THREAD_ID\n"
636  "\t\textension. Includes time blocked in the kernel, but may\n"
637  "\t\tnot be available on all systems (eg, Blue Gene) and may\n"
638  "\t\tbreak some syscalls that are sensitive to EINTR.\n",
640 #ifndef ENABLE_CLOCK_REALTIME
641  printf("\t\tNot available on this system.\n");
642 #endif
643  printf("\n");
644  printf("%s \tCPU clock time used by the thread in microseconds. Based\n"
645  "\t\ton the CLOCK_THREAD_CPUTIME_ID timer with the SIGEV_THREAD_ID\n"
646  "\t\textension. May not be available on all systems (eg, Blue Gene).\n",
648 #ifndef ENABLE_CLOCK_CPUTIME
649  printf("\t\tNot available on this system.\n");
650 #endif
651  printf("\n");
652  printf("%s \tCPU clock time used by the thread in microseconds. Same\n"
653  "\t\tas %s except on Blue Gene, where it is implemented\n"
654  "\t\tby ITIMER_PROF.\n",
656  printf("\n");
657  printf("Note: do not use multiple timer events in the same run.\n");
658  printf("\n");
659 }
660 
661 
662 /***************************************************************************
663  * object
664  ***************************************************************************/
665 
666 #define ss_name itimer
667 #define ss_cls SS_HARDWARE
668 #define ss_sort_order 20
669 
670 #include "ss_obj.h"
671 
672 
673 /******************************************************************************
674  * private operations
675  *****************************************************************************/
676 
677 static int
678 itimer_signal_handler(int sig, siginfo_t* siginfo, void* context)
679 {
681 
682  static bool metrics_finalized = false;
683  sample_source_t *self = &_itimer_obj;
684 
685  // if sampling is suppressed for this thread, restart timer, & exit
687  TMSG(ITIMER_HANDLER, "thread sampling suppressed");
688  hpcrun_restart_timer(self, 1);
689 
691 
692  return 0; // tell monitor that the signal has been handled
693  }
694 
695  // If we got a wallclock signal not meant for our thread, then drop the sample
696  if (! wallclock_ok) {
697  EMSG("Received itimer signal, but thread not initialized");
698  }
699  // If the interrupt came from inside our code, then drop the sample
700  // and return and avoid any MSG.
701  void* pc = hpcrun_context_pc(context);
702  if (! hpcrun_safe_enter_async(pc)) {
704  if (! hpcrun_is_sampling_disabled()) {
705  hpcrun_restart_timer(self, 0);
706  }
707 
709 
710  return 0; // tell monitor that the signal has been handled
711  }
712 
713  // Ensure metrics are finalized.
714  if (!metrics_finalized) {
716  metrics_finalized = true;
717  }
718 
719  TMSG(ITIMER_HANDLER,"Itimer sample event");
720 
721  uint64_t metric_incr = 1; // default: one time unit
722 
723 #if defined (USE_ELAPSED_TIME_FOR_WALLCLOCK)
724  uint64_t cur_time_us = 0;
725  int ret = time_getTimeReal(&cur_time_us);
726  if (ret != 0) {
727  EMSG("time_getTimeReal (clock_gettime) failed!");
729  }
730  metric_incr = cur_time_us - TD_GET(last_time_us);
731 #endif
732  hpcrun_metricVal_t metric_delta = {.i = metric_incr};
733 
734  int metric_id = hpcrun_event2metric(self, ITIMER_EVENT);
735  sample_val_t sv = hpcrun_sample_callpath(context, metric_id,
736  metric_delta,
737  0/*skipInner*/, 0/*isSync*/, NULL);
738  blame_shift_apply(metric_id, sv.sample_node, metric_incr);
739 
741  TMSG(ITIMER_HANDLER, "No itimer restart, due to disabled sampling");
742  }
743  else {
744  hpcrun_restart_timer(self, 1);
745  }
746 
748 
750 
751  return 0; // tell monitor that the signal has been handled
752 }
#define DEFAULT_PERIOD
Definition: itimer.c:162
static int hpcrun_create_real_timer(thread_data_t *td)
Definition: itimer.c:228
static struct itimerspec itspec_stop
Definition: itimer.c:200
static int itimer_signal_handler(int sig, siginfo_t *siginfo, void *context)
Definition: itimer.c:678
static bool use_cputime
Definition: itimer.c:188
#define REALTIME_METRIC_NAME
Definition: itimer.c:136
static void hpcrun_safe_exit(void)
sample_val_t hpcrun_sample_callpath(void *context, int metricId, hpcrun_metricVal_t metricIncr, int skipInner, int isSync, sampling_info_t *data)
Definition: sample_event.c:160
#define CPUTIME_METRIC_NAME
Definition: itimer.c:143
#define HPCTOOLKIT_APPLICATION_ERRNO_RESTORE()
Definition: ss-errno.h:64
static char * the_metric_name
Definition: itimer.c:191
#define metric_property_time
Definition: hpcrun-fmt.h:200
static bool use_realtime
Definition: itimer.c:187
void blame_shift_source_register(bs_type bst)
Definition: blame-shift.c:25
struct sigevent sigev
Definition: thread_data.h:153
void hpcrun_ssfail_unknown(char *event)
Definition: common.c:220
#define REALTIME_SIGNAL
Definition: itimer.c:137
static bool hpcrun_is_sampling_disabled(void)
Definition: sample_event.h:73
static bool use_itimer
Definition: itimer.c:186
static void hpcrun_restart_timer(sample_source_t *self, int safe)
Definition: itimer.c:326
#define WALLCLOCK_EVENT_NAME
Definition: itimer.c:127
#define ITIMER_EVENT_NAME
Definition: itimer.c:130
static sigset_t timer_mask
Definition: itimer.c:202
cct_node_t * sample_node
Definition: sample_event.h:96
bool(* hpcrun_td_avail)(void)
Definition: thread_data.c:169
#define WALLCLOCK_METRIC_NAME
Definition: itimer.c:128
void hpcrun_itimer_wallclock_ok(bool flag)
Definition: itimer.c:215
void blame_shift_apply(int metric_id, cct_node_t *node, int metric_incr)
Definition: blame-shift.c:15
void hpcrun_stats_num_samples_blocked_async_inc(void)
Definition: hpcrun_stats.c:148
static int the_signal_num
Definition: itimer.c:192
char * next_tok(void)
Definition: tokenize.c:87
metric_desc_t * hpcrun_set_metric_info_and_period(int metric_id, const char *name, MetricFlags_ValFmt_t valFmt, size_t period, metric_desc_properties_t prop)
Definition: metrics.c:411
static int hpcrun_delete_real_timer(thread_data_t *td)
Definition: itimer.c:257
#define CPUTIME_EVENT_NAME
Definition: itimer.c:142
static struct itimerspec itspec_start
Definition: itimer.c:199
static int hpcrun_stop_timer(thread_data_t *td)
Definition: itimer.c:303
#define EMSG
Definition: messages.h:70
_local_const
Definition: main.c:164
char * start_tok(char *lst)
Definition: tokenize.c:70
int lush_metrics
Definition: main.c:188
void hpcrun_ssfail_start(char *source)
Definition: common.c:265
#define TD_GET(field)
Definition: thread_data.h:256
static struct itimerval itval_stop
Definition: itimer.c:197
#define REALTIME_NOTIFY_METHOD
Definition: itimer.c:140
#define sample_period
Definition: itimer.c:157
bool hpcrun_ev_is(const char *candidate, const char *event_name)
Definition: tokenize.c:194
static int time_getTimeReal(uint64_t *time)
Definition: timer.h:131
static int hpcrun_start_timer(thread_data_t *td)
Definition: itimer.c:291
static char * the_event_name
Definition: itimer.c:190
int metric_idleness
Definition: lush.h:96
#define IDLE_METRIC_NAME
Definition: itimer.c:125
#define TMSG(f,...)
Definition: messages.h:93
int hpcrun_extract_ev_thresh(const char *in, int evlen, char *ev, long *th, long def)
Definition: tokenize.c:157
static __thread bool wallclock_ok
Definition: itimer.c:204
static int hpcrun_safe_enter_async(void *pc)
#define CPUTIME_CLOCK_TYPE
Definition: itimer.c:144
int hpcrun_event2metric(sample_source_t *ss, int event_idx)
Definition: common.c:143
#define METHOD_CALL(obj, meth,...)
Definition: simple_oo.h:87
#define ITIMER_METRIC_NAME
Definition: itimer.c:131
static struct itimerval itval_start
Definition: itimer.c:196
#define REALTIME_CLOCK_TYPE
Definition: itimer.c:139
#define EEMSG(...)
Definition: messages.h:90
#define NULL
Definition: ElfHelper.cpp:85
timer_t timerid
Definition: thread_data.h:154
#define ITIMER_TYPE
Definition: itimer.c:133
int hpcrun_new_metric(void)
Definition: metrics.c:333
#define REALTIME_EVENT_NAME
Definition: itimer.c:135
__thread bool hpcrun_thread_suppress_sample
Definition: main.c:193
#define HPCTOOLKIT_APPLICATION_ERRNO_SAVE()
Definition: ss-errno.h:63
void hpcrun_finalize_metrics()
Definition: metrics.c:245
void monitor_real_abort(void)
void hpcrun_pre_allocate_metrics(size_t num)
Definition: metrics.c:190
void * hpcrun_context_pc(void *context)
lush_agent_pool_t * lush_agents
static void METHOD_FN(init)
Definition: itimer.c:389
int more_tok(void)
Definition: tokenize.c:78
static int hpcrun_settime(thread_data_t *td, struct itimerspec *spec)
Definition: itimer.c:280
static long period
Definition: itimer.c:194
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition: thread_data.c:168
#define ITIMER_SIGNAL
Definition: itimer.c:132
int metric_time
Definition: lush.h:95
void hpcrun_ssfail_conflict(char *source, char *event)
Definition: common.c:255