HPCToolkit
idle.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL: https://outreach.scidac.gov/svn/hpctoolkit/branches/hpctoolkit-omp/src/tool/hpcrun/sample-sources/idle.c $
6 // $Id: idle.c 3691 2012-03-05 21:21:08Z xl10 $
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  * system includes
50  *****************************************************************************/
51 
52 #include <pthread.h>
53 
54 
55 
56 /******************************************************************************
57  * libmonitor
58  *****************************************************************************/
59 
60 #include <monitor.h>
61 
62 
63 
64 /******************************************************************************
65  * local includes
66  *****************************************************************************/
67 
68 #include "simple_oo.h"
69 #include "sample_source_obj.h"
70 #include "common.h"
72 
73 #include <hpcrun/hpcrun_options.h>
74 
75 #include <hpcrun/metrics.h>
77 #include <hpcrun/safe-sampling.h>
78 #include <hpcrun/sample_event.h>
79 #include <hpcrun/thread_data.h>
80 #include <hpcrun/trace.h>
81 #include <messages/messages.h>
82 #include <utilities/tokenize.h>
83 
84 
85 /******************************************************************************
86  * macros
87  *****************************************************************************/
88 
89 // elide debugging support for performance
90 #undef TMSG
91 #define TMSG(...)
92 
93 
94 
95 /******************************************************************************
96  * forward declarations
97  *****************************************************************************/
98 
99 static void idle_metric_process_blame_for_sample(void* arg, int metric_id, cct_node_t *node, int metric_value);
100 
101 static void init_hack(void);
102 
103 
104 
105 /******************************************************************************
106  * local variables
107  *****************************************************************************/
108 static atomic_uintptr_t active_worker_count = ATOMIC_VAR_INIT(1);// by default is 1 (1 thread)
109 
110 static int idle_metric_id = -1;
111 static int work_metric_id = -1;
112 
114 static bool idleness_measurement_enabled = false;
116 
118 
119 
120 
121 /******************************************************************************
122  * sample source interface
123  *****************************************************************************/
124 
125 static void
127 {
128  self->state = INIT;
129 }
130 
131 
132 static void
133 METHOD_FN(thread_init)
134 {
135 }
136 
137 
138 static void
139 METHOD_FN(thread_init_action)
140 {
141 }
142 
143 
144 static void
145 METHOD_FN(start)
146 {
148  STDERR_MSG("HPCToolkit: IDLE metric needs either a REALTIME, CPUTIME, WALLCLOCK, or PAPI_TOT_CYC source.");
149  monitor_real_exit(1);
150  }
151 
153  STDERR_MSG("HPCToolkit: IDLE metric specified without a plugin that measures "
154  "idleness and work.\n"
155  "For dynamic binaries, specify an appropriate plugin with an argument to hpcrun.\n"
156  "For static binaries, specify an appropriate plugin with an argument to hpclink.\n");
157  monitor_real_exit(1);
158  }
159 }
160 
161 
162 static void
163 METHOD_FN(thread_fini_action)
164 {
165 }
166 
167 
168 static void
170 {
171 }
172 
173 
174 static void
175 METHOD_FN(shutdown)
176 {
177  self->state = UNINIT;
178 }
179 
180 
181 // Return true if IDLE recognizes the name
182 static bool
183 METHOD_FN(supports_event,const char *ev_str)
184 {
185  return hpcrun_ev_is(ev_str, "IDLE");
186 }
187 
188 static void
189 METHOD_FN(process_event_list, int lush_metrics)
190 {
191  TMSG(IDLE, "Process event list");
194  bs_entry.next = 0;
195 
196  blame_shift_register(&bs_entry);
197 
201 
205  TMSG(IDLE, "Metric ids = idle (%d), work(%d)",
207  init_hack();
208 
209 }
210 
211 
212 static void
213 METHOD_FN(gen_event_set,int lush_metrics)
214 {
215 }
216 
217 
218 static void
219 METHOD_FN(display_events)
220 {
221  printf("===========================================================================\n");
222  printf("NO Available IDLE preset events\n");
223  printf("===========================================================================\n");
224  printf("\n");
225 }
226 
227 
228 
229 /***************************************************************************
230  * object
231  ***************************************************************************/
232 
233 #define ss_name idle
234 #define ss_cls SS_SOFTWARE
235 
236 #include "ss_obj.h"
237 
238 
239 
240 /******************************************************************************
241  * private operations
242  *****************************************************************************/
243 
244 static void
245 idle_metric_process_blame_for_sample(void* arg, int metric_id, cct_node_t *node, int metric_incr)
246 {
247  metric_desc_t * metric_desc = hpcrun_id2metric(metric_id);
248 
249  // Only blame shift idleness for time and cycle metrics.
250  if ( ! (metric_desc->properties.time | metric_desc->properties.cycles) )
251  return;
252 
253  int metric_value = metric_desc->period * metric_incr;
255  if (td->idle == 0) { // if this thread is not idle
256  // capture active_worker_count into a local variable to make sure that the count doesn't change
257  // between the time we test it and the time we use the value
259  double working_threads = (workers > 0 ? workers : 1.0 );
260 
261  double idle_threads = (total_threads - working_threads);
262 
263  cct_metric_data_increment(idle_metric_id, node, (cct_metric_data_t){.r = (idle_threads / working_threads) * ((double) metric_value)});
264  cct_metric_data_increment(work_metric_id, node, (cct_metric_data_t){.i = metric_value});
265  }
266 }
267 
268 
269 static void
271 {
272  char * num_threads = getenv("OMP_NUM_THREADS");
273  if (!num_threads)
274  total_threads = 1;
275  else
276  total_threads = atoi(num_threads);
278 
279  TMSG(IDLE, "init_hack called, work = %d", total_threads);
280 }
281 
282 
283 
284 /******************************************************************************
285  * interface operations
286  *****************************************************************************/
287 
288 void
290 {
292 }
293 
294 
295 void
297 {
298  if (! idleness_measurement_enabled) return;
299 
301  if (td->idle++ > 0) return;
302 
303  TMSG(IDLE, "blame shift idle work BEFORE decr: %ld", atomic_load_explicit(&active_worker_count, memory_order_relaxed));
305  TMSG(IDLE, "blame shift idle after td->idle incr = %d", td->idle);
306 
307  // get a tracing sample out
308  if(hpcrun_trace_isactive()) {
309  if ( ! hpcrun_safe_enter()) return;
310  ucontext_t uc;
311  getcontext(&uc);
313  (hpcrun_metricVal_t) {.i=0}, 1, 1, NULL);
315  }
316 }
317 
318 
319 void
321 {
322  if (! idleness_measurement_enabled) return;
323 
325  TMSG(IDLE, "blame shift idle before td->idle decr = %d", td->idle);
326  if (--td->idle > 0) return;
327 
328  TMSG(IDLE, "blame shift work, work BEFORE incr: %ld", atomic_load_explicit(&active_worker_count, memory_order_relaxed));
330 
331  // get a tracing sample out
332  if(hpcrun_trace_isactive()) {
333  if ( ! hpcrun_safe_enter()) return;
334  ucontext_t uc;
335  getcontext(&uc);
337  (hpcrun_metricVal_t) {.i=0}, 1, 1, NULL);
339  }
340 }
341 
static int idle_metric_id
Definition: idle.c:110
#define STDERR_MSG(...)
Definition: messages.h:89
void idle_metric_register_blame_source()
Definition: idle.c:289
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 atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:366
#define ATOMIC_VAR_INIT(value)
Definition: stdatomic.h:132
struct bs_fn_entry_t * next
Definition: blame-shift.h:9
cct_node_t * node
Definition: cct.c:128
#define atomic_load_explicit(object, order)
Definition: stdatomic.h:378
Definition: blame-shift.h:8
static void cct_metric_data_increment(int metric_id, cct_node_t *x, cct_metric_data_t incr)
Definition: cct2metrics.h:86
#define atomic_store_explicit(object, desired, order)
Definition: stdatomic.h:380
static void idle_metric_process_blame_for_sample(void *arg, int metric_id, cct_node_t *node, int metric_value)
Definition: idle.c:245
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
void blame_shift_register(bs_fn_entry_t *entry)
Definition: blame-shift.c:8
int hpcrun_trace_isactive()
Definition: trace.c:107
static bool idleness_blame_information_source_present
Definition: idle.c:115
static int work_metric_id
Definition: idle.c:111
int lush_metrics
Definition: main.c:188
#define TMSG(...)
Definition: idle.c:91
static bs_fn_entry_t bs_entry
Definition: idle.c:113
double total_threads
Definition: idle.c:117
uint64_t period
Definition: hpcrun-fmt.h:374
bs_fn_t fn
Definition: blame-shift.h:10
static void METHOD_FN(init)
Definition: idle.c:126
void idle_metric_blame_shift_idle(void)
Definition: idle.c:296
bool hpcrun_ev_is(const char *candidate, const char *event_name)
Definition: tokenize.c:194
static void init_hack(void)
Definition: idle.c:270
#define NULL
Definition: ElfHelper.cpp:85
int blame_shift_source_available(bs_type bst)
Definition: blame-shift.c:32
unsigned char uc
Definition: amd-xop.c:3
Definition: cct.c:96
int hpcrun_new_metric(void)
Definition: metrics.c:333
void idle_metric_blame_shift_work(void)
Definition: idle.c:320
metric_desc_properties_t properties
Definition: hpcrun-fmt.h:376
static bool idleness_measurement_enabled
Definition: idle.c:114
static int hpcrun_safe_enter(void)
#define IDLE()
static atomic_uintptr_t active_worker_count
Definition: idle.c:108
metric_desc_t * hpcrun_id2metric(int metric_id)
Definition: metrics.c:251
thread_data_t *(* hpcrun_get_thread_data)(void)
Definition: thread_data.c:168
#define metric_property_none
Definition: hpcrun-fmt.h:202