blob: 9b6ab076ca27f3b5fbb47ee492b9f7a0ff41d8bd [file] [log] [blame]
Andrey Churbanove5f44922015-04-29 16:22:07 +00001/*****************************************************************************
2 * system include files
3 ****************************************************************************/
4
5#include <assert.h>
6
7#include <stdint.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12
13
14/*****************************************************************************
15 * ompt include files
16 ****************************************************************************/
17
18#include "ompt-internal.h"
19#include "ompt-specific.c"
20
21
22
23/*****************************************************************************
24 * macros
25 ****************************************************************************/
26
27#define ompt_get_callback_success 1
28#define ompt_get_callback_failure 0
29
30#define no_tool_present 0
31
32#define OMPT_API_ROUTINE static
33
Jonathan Peyton69e596a2015-10-29 20:56:24 +000034#ifndef OMPT_STR_MATCH
35#define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))
36#endif
Andrey Churbanove5f44922015-04-29 16:22:07 +000037
38
39/*****************************************************************************
40 * types
41 ****************************************************************************/
42
43typedef struct {
44 const char *state_name;
45 ompt_state_t state_id;
46} ompt_state_info_t;
47
48
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000049enum tool_setting_e {
50 omp_tool_error,
51 omp_tool_unset,
52 omp_tool_disabled,
53 omp_tool_enabled
54};
55
56
57typedef void (*ompt_initialize_t) (
58 ompt_function_lookup_t ompt_fn_lookup,
59 const char *version,
60 unsigned int ompt_version
61);
62
63
Andrey Churbanove5f44922015-04-29 16:22:07 +000064
65/*****************************************************************************
66 * global variables
67 ****************************************************************************/
68
Jonathan Peytonb68a85d2015-09-21 18:11:22 +000069int ompt_enabled = 0;
Andrey Churbanove5f44922015-04-29 16:22:07 +000070
71ompt_state_info_t ompt_state_info[] = {
72#define ompt_state_macro(state, code) { # state, state },
73 FOREACH_OMPT_STATE(ompt_state_macro)
74#undef ompt_state_macro
75};
76
Andrey Churbanove5f44922015-04-29 16:22:07 +000077ompt_callbacks_t ompt_callbacks;
78
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000079static ompt_initialize_t ompt_initialize_fn = NULL;
80
Andrey Churbanove5f44922015-04-29 16:22:07 +000081
82
83/*****************************************************************************
84 * forward declarations
85 ****************************************************************************/
86
87static ompt_interface_fn_t ompt_fn_lookup(const char *s);
88
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000089OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void);
90
91
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000092/*****************************************************************************
93 * initialization and finalization (private operations)
94 ****************************************************************************/
95
Jonathan Peyton69e596a2015-10-29 20:56:24 +000096/* On Unix-like systems that support weak symbols the following implementation
97 * of ompt_tool() will be used in case no tool-supplied implementation of
98 * this function is present in the address space of a process.
99 *
100 * On Windows, the ompt_tool_windows function is used to find the
101 * ompt_tool symbol across all modules loaded by a process. If ompt_tool is
102 * found, ompt_tool's return value is used to initialize the tool. Otherwise,
103 * NULL is returned and OMPT won't be enabled */
104#if OMPT_HAVE_WEAK_ATTRIBUTE
105_OMP_EXTERN
106__attribute__ (( weak ))
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000107ompt_initialize_t ompt_tool()
108{
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000109#if OMPT_DEBUG
110 printf("ompt_tool() is called from the RTL\n");
111#endif
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000112 return NULL;
113}
114
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000115#elif OMPT_HAVE_PSAPI
116
117#include <psapi.h>
118#pragma comment(lib, "psapi.lib")
119#define ompt_tool ompt_tool_windows
120
121// The number of loaded modules to start enumeration with EnumProcessModules()
122#define NUM_MODULES 128
123
124static
125ompt_initialize_t ompt_tool_windows()
126{
127 int i;
128 DWORD needed, new_size;
129 HMODULE *modules;
130 HANDLE process = GetCurrentProcess();
131 modules = (HMODULE*)malloc( NUM_MODULES * sizeof(HMODULE) );
132 ompt_initialize_t (*ompt_tool_p)() = NULL;
133
134#if OMPT_DEBUG
135 printf("ompt_tool_windows(): looking for ompt_tool\n");
136#endif
137 if( !EnumProcessModules( process, modules, NUM_MODULES * sizeof(HMODULE),
138 &needed ) ) {
139 // Regardless of the error reason use the stub initialization function
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000140 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000141 return NULL;
142 }
143 // Check if NUM_MODULES is enough to list all modules
144 new_size = needed / sizeof(HMODULE);
145 if( new_size > NUM_MODULES ) {
146#if OMPT_DEBUG
147 printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);
148#endif
149 modules = (HMODULE*)realloc( modules, needed );
150 // If resizing failed use the stub function.
151 if( !EnumProcessModules( process, modules, needed, &needed ) ) {
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000152 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000153 return NULL;
154 }
155 }
156 for( i = 0; i < new_size; ++i ) {
157 (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_tool");
158 if( ompt_tool_p ) {
159#if OMPT_DEBUG
160 TCHAR modName[MAX_PATH];
161 if( GetModuleFileName(modules[i], modName, MAX_PATH))
162 printf("ompt_tool_windows(): ompt_tool found in module %s\n",
163 modName);
164#endif
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000165 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000166 return ompt_tool_p();
167 }
168#if OMPT_DEBUG
169 else {
170 TCHAR modName[MAX_PATH];
171 if( GetModuleFileName(modules[i], modName, MAX_PATH) )
172 printf("ompt_tool_windows(): ompt_tool not found in module %s\n",
173 modName);
174 }
175#endif
176 }
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000177 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000178 return NULL;
179}
180#else
181# error Either __attribute__((weak)) or psapi.dll are required for OMPT support
182#endif // OMPT_HAVE_WEAK_ATTRIBUTE
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000183
184void ompt_pre_init()
185{
186 //--------------------------------------------------
187 // Execute the pre-initialization logic only once.
188 //--------------------------------------------------
189 static int ompt_pre_initialized = 0;
190
191 if (ompt_pre_initialized) return;
192
193 ompt_pre_initialized = 1;
194
195 //--------------------------------------------------
196 // Use a tool iff a tool is enabled and available.
197 //--------------------------------------------------
198 const char *ompt_env_var = getenv("OMP_TOOL");
199 tool_setting_e tool_setting = omp_tool_error;
200
201 if (!ompt_env_var || !strcmp(ompt_env_var, ""))
202 tool_setting = omp_tool_unset;
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000203 else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000204 tool_setting = omp_tool_disabled;
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000205 else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000206 tool_setting = omp_tool_enabled;
207
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000208#if OMPT_DEBUG
209 printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);
210#endif
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000211 switch(tool_setting) {
212 case omp_tool_disabled:
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000213 break;
214
215 case omp_tool_unset:
216 case omp_tool_enabled:
217 ompt_initialize_fn = ompt_tool();
218 if (ompt_initialize_fn) {
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000219 ompt_enabled = 1;
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000220 }
221 break;
222
223 case omp_tool_error:
224 fprintf(stderr,
225 "Warning: OMP_TOOL has invalid value \"%s\".\n"
226 " legal values are (NULL,\"\",\"disabled\","
227 "\"enabled\").\n", ompt_env_var);
228 break;
229 }
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000230#if OMPT_DEBUG
231 printf("ompt_pre_init():ompt_enabled = %d\n", ompt_enabled);
232#endif
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000233}
234
235
236void ompt_post_init()
237{
238 //--------------------------------------------------
239 // Execute the post-initialization logic only once.
240 //--------------------------------------------------
241 static int ompt_post_initialized = 0;
242
243 if (ompt_post_initialized) return;
244
245 ompt_post_initialized = 1;
246
247 //--------------------------------------------------
248 // Initialize the tool if so indicated.
249 //--------------------------------------------------
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000250 if (ompt_enabled) {
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000251 ompt_initialize_fn(ompt_fn_lookup, ompt_get_runtime_version(),
252 OMPT_VERSION);
253
254 ompt_thread_t *root_thread = ompt_get_thread();
255
256 ompt_set_thread_state(root_thread, ompt_state_overhead);
257
258 if (ompt_callbacks.ompt_callback(ompt_event_thread_begin)) {
259 ompt_callbacks.ompt_callback(ompt_event_thread_begin)
260 (ompt_thread_initial, ompt_get_thread_id());
261 }
262
263 ompt_set_thread_state(root_thread, ompt_state_work_serial);
264 }
265}
266
267
268void ompt_fini()
269{
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000270 if (ompt_enabled) {
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000271 if (ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)) {
272 ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)();
273 }
274 }
275
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000276 ompt_enabled = 0;
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000277}
278
279
280/*****************************************************************************
281 * interface operations
282 ****************************************************************************/
Andrey Churbanove5f44922015-04-29 16:22:07 +0000283
284/*****************************************************************************
285 * state
286 ****************************************************************************/
287
288OMPT_API_ROUTINE int ompt_enumerate_state(int current_state, int *next_state,
289 const char **next_state_name)
290{
291 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);
292 int i = 0;
293
294 for (i = 0; i < len - 1; i++) {
295 if (ompt_state_info[i].state_id == current_state) {
296 *next_state = ompt_state_info[i+1].state_id;
297 *next_state_name = ompt_state_info[i+1].state_name;
298 return 1;
299 }
300 }
301
302 return 0;
303}
304
305
306
307/*****************************************************************************
308 * callbacks
309 ****************************************************************************/
310
311OMPT_API_ROUTINE int ompt_set_callback(ompt_event_t evid, ompt_callback_t cb)
312{
313 switch (evid) {
314
315#define ompt_event_macro(event_name, callback_type, event_id) \
316 case event_name: \
317 if (ompt_event_implementation_status(event_name)) { \
318 ompt_callbacks.ompt_callback(event_name) = (callback_type) cb; \
319 } \
320 return ompt_event_implementation_status(event_name);
321
322 FOREACH_OMPT_EVENT(ompt_event_macro)
323
324#undef ompt_event_macro
325
326 default: return ompt_set_result_registration_error;
327 }
328}
329
330
331OMPT_API_ROUTINE int ompt_get_callback(ompt_event_t evid, ompt_callback_t *cb)
332{
333 switch (evid) {
334
335#define ompt_event_macro(event_name, callback_type, event_id) \
336 case event_name: \
337 if (ompt_event_implementation_status(event_name)) { \
338 ompt_callback_t mycb = \
339 (ompt_callback_t) ompt_callbacks.ompt_callback(event_name); \
340 if (mycb) { \
341 *cb = mycb; \
342 return ompt_get_callback_success; \
343 } \
344 } \
345 return ompt_get_callback_failure;
346
347 FOREACH_OMPT_EVENT(ompt_event_macro)
348
349#undef ompt_event_macro
350
351 default: return ompt_get_callback_failure;
352 }
353}
354
355
Andrey Churbanove5f44922015-04-29 16:22:07 +0000356/*****************************************************************************
357 * parallel regions
358 ****************************************************************************/
359
360OMPT_API_ROUTINE ompt_parallel_id_t ompt_get_parallel_id(int ancestor_level)
361{
362 return __ompt_get_parallel_id_internal(ancestor_level);
363}
364
365
366OMPT_API_ROUTINE int ompt_get_parallel_team_size(int ancestor_level)
367{
368 return __ompt_get_parallel_team_size_internal(ancestor_level);
369}
370
371
372OMPT_API_ROUTINE void *ompt_get_parallel_function(int ancestor_level)
373{
374 return __ompt_get_parallel_function_internal(ancestor_level);
375}
376
377
378OMPT_API_ROUTINE ompt_state_t ompt_get_state(ompt_wait_id_t *ompt_wait_id)
379{
380 ompt_state_t thread_state = __ompt_get_state_internal(ompt_wait_id);
381
382 if (thread_state == ompt_state_undefined) {
383 thread_state = ompt_state_work_serial;
384 }
385
386 return thread_state;
387}
388
389
390
391/*****************************************************************************
392 * threads
393 ****************************************************************************/
394
395
396OMPT_API_ROUTINE void *ompt_get_idle_frame()
397{
398 return __ompt_get_idle_frame_internal();
399}
400
401
402
403/*****************************************************************************
404 * tasks
405 ****************************************************************************/
406
407
408OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void)
409{
410 return __ompt_get_thread_id_internal();
411}
412
413OMPT_API_ROUTINE ompt_task_id_t ompt_get_task_id(int depth)
414{
415 return __ompt_get_task_id_internal(depth);
416}
417
418
419OMPT_API_ROUTINE ompt_frame_t *ompt_get_task_frame(int depth)
420{
421 return __ompt_get_task_frame_internal(depth);
422}
423
424
425OMPT_API_ROUTINE void *ompt_get_task_function(int depth)
426{
427 return __ompt_get_task_function_internal(depth);
428}
429
430
431/*****************************************************************************
432 * placeholders
433 ****************************************************************************/
434
Jonathan Peyton122dd762015-07-13 18:55:45 +0000435// Don't define this as static. The loader may choose to eliminate the symbol
436// even though it is needed by tools.
437#define OMPT_API_PLACEHOLDER
Andrey Churbanove5f44922015-04-29 16:22:07 +0000438
Jonathan Peyton122dd762015-07-13 18:55:45 +0000439// Ensure that placeholders don't have mangled names in the symbol table.
440#ifdef __cplusplus
441extern "C" {
442#endif
443
444
445OMPT_API_PLACEHOLDER void ompt_idle(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000446{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000447 // This function is a placeholder used to represent the calling context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000448 // idle OpenMP worker threads. It is not meant to be invoked.
449 assert(0);
450}
451
452
Jonathan Peyton122dd762015-07-13 18:55:45 +0000453OMPT_API_PLACEHOLDER void ompt_overhead(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000454{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000455 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000456 // threads working in the OpenMP runtime. It is not meant to be invoked.
457 assert(0);
458}
459
460
Jonathan Peyton122dd762015-07-13 18:55:45 +0000461OMPT_API_PLACEHOLDER void ompt_barrier_wait(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000462{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000463 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000464 // threads waiting for a barrier in the OpenMP runtime. It is not meant
465 // to be invoked.
466 assert(0);
467}
468
469
Jonathan Peyton122dd762015-07-13 18:55:45 +0000470OMPT_API_PLACEHOLDER void ompt_task_wait(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000471{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000472 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000473 // threads waiting for a task in the OpenMP runtime. It is not meant
474 // to be invoked.
475 assert(0);
476}
477
478
Jonathan Peyton122dd762015-07-13 18:55:45 +0000479OMPT_API_PLACEHOLDER void ompt_mutex_wait(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000480{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000481 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000482 // threads waiting for a mutex in the OpenMP runtime. It is not meant
483 // to be invoked.
484 assert(0);
485}
486
Jonathan Peyton122dd762015-07-13 18:55:45 +0000487#ifdef __cplusplus
488};
489#endif
490
Andrey Churbanove5f44922015-04-29 16:22:07 +0000491
492/*****************************************************************************
493 * compatability
494 ****************************************************************************/
495
496OMPT_API_ROUTINE int ompt_get_ompt_version()
497{
498 return OMPT_VERSION;
499}
500
501
502
503/*****************************************************************************
504 * application-facing API
505 ****************************************************************************/
506
507
508/*----------------------------------------------------------------------------
509 | control
510 ---------------------------------------------------------------------------*/
511
512_OMP_EXTERN void ompt_control(uint64_t command, uint64_t modifier)
513{
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000514 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_control)) {
Andrey Churbanove5f44922015-04-29 16:22:07 +0000515 ompt_callbacks.ompt_callback(ompt_event_control)(command, modifier);
516 }
517}
518
519
520
521/*****************************************************************************
522 * API inquiry for tool
523 ****************************************************************************/
524
525static ompt_interface_fn_t ompt_fn_lookup(const char *s)
526{
527
528#define ompt_interface_fn(fn) \
529 if (strcmp(s, #fn) == 0) return (ompt_interface_fn_t) fn;
530
531 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
532
533 FOREACH_OMPT_PLACEHOLDER_FN(ompt_interface_fn)
534
535 return (ompt_interface_fn_t) 0;
536}