blob: 34f1073b3a9c1f9d480e6ee83342a9a3923e9ad1 [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
Andrey Churbanove5f44922015-04-29 16:22:07 +000018#include "ompt-specific.c"
19
20
21
22/*****************************************************************************
23 * macros
24 ****************************************************************************/
25
26#define ompt_get_callback_success 1
27#define ompt_get_callback_failure 0
28
29#define no_tool_present 0
30
31#define OMPT_API_ROUTINE static
32
Jonathan Peyton69e596a2015-10-29 20:56:24 +000033#ifndef OMPT_STR_MATCH
34#define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))
35#endif
Andrey Churbanove5f44922015-04-29 16:22:07 +000036
37
38/*****************************************************************************
39 * types
40 ****************************************************************************/
41
42typedef struct {
43 const char *state_name;
44 ompt_state_t state_id;
45} ompt_state_info_t;
46
47
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000048enum tool_setting_e {
49 omp_tool_error,
50 omp_tool_unset,
51 omp_tool_disabled,
52 omp_tool_enabled
53};
54
55
56typedef void (*ompt_initialize_t) (
Jonathan Peyton61118492016-05-20 19:03:38 +000057 ompt_function_lookup_t ompt_fn_lookup,
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000058 const char *version,
59 unsigned int ompt_version
60);
61
62
Andrey Churbanove5f44922015-04-29 16:22:07 +000063
64/*****************************************************************************
65 * global variables
66 ****************************************************************************/
67
Jonathan Peytonb68a85d2015-09-21 18:11:22 +000068int ompt_enabled = 0;
Andrey Churbanove5f44922015-04-29 16:22:07 +000069
70ompt_state_info_t ompt_state_info[] = {
71#define ompt_state_macro(state, code) { # state, state },
72 FOREACH_OMPT_STATE(ompt_state_macro)
73#undef ompt_state_macro
74};
75
Andrey Churbanove5f44922015-04-29 16:22:07 +000076ompt_callbacks_t ompt_callbacks;
77
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000078static ompt_initialize_t ompt_initialize_fn = NULL;
79
Andrey Churbanove5f44922015-04-29 16:22:07 +000080
81
82/*****************************************************************************
83 * forward declarations
84 ****************************************************************************/
85
86static ompt_interface_fn_t ompt_fn_lookup(const char *s);
87
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000088OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void);
89
90
Jonathan Peyton82a13bf2015-09-21 18:01:02 +000091/*****************************************************************************
92 * initialization and finalization (private operations)
93 ****************************************************************************/
94
Jonathan Peyton69e596a2015-10-29 20:56:24 +000095/* On Unix-like systems that support weak symbols the following implementation
96 * of ompt_tool() will be used in case no tool-supplied implementation of
97 * this function is present in the address space of a process.
98 *
99 * On Windows, the ompt_tool_windows function is used to find the
100 * ompt_tool symbol across all modules loaded by a process. If ompt_tool is
101 * found, ompt_tool's return value is used to initialize the tool. Otherwise,
102 * NULL is returned and OMPT won't be enabled */
103#if OMPT_HAVE_WEAK_ATTRIBUTE
Jonathan Peyton61118492016-05-20 19:03:38 +0000104_OMP_EXTERN
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000105__attribute__ (( weak ))
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000106ompt_initialize_t ompt_tool()
107{
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000108#if OMPT_DEBUG
109 printf("ompt_tool() is called from the RTL\n");
110#endif
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000111 return NULL;
112}
113
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000114#elif OMPT_HAVE_PSAPI
115
116#include <psapi.h>
117#pragma comment(lib, "psapi.lib")
118#define ompt_tool ompt_tool_windows
119
120// The number of loaded modules to start enumeration with EnumProcessModules()
121#define NUM_MODULES 128
122
123static
124ompt_initialize_t ompt_tool_windows()
125{
126 int i;
127 DWORD needed, new_size;
128 HMODULE *modules;
129 HANDLE process = GetCurrentProcess();
130 modules = (HMODULE*)malloc( NUM_MODULES * sizeof(HMODULE) );
131 ompt_initialize_t (*ompt_tool_p)() = NULL;
132
133#if OMPT_DEBUG
134 printf("ompt_tool_windows(): looking for ompt_tool\n");
135#endif
Jonathan Peyton95246e72015-11-05 16:54:55 +0000136 if (!EnumProcessModules( process, modules, NUM_MODULES * sizeof(HMODULE),
137 &needed)) {
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000138 // Regardless of the error reason use the stub initialization function
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000139 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000140 return NULL;
141 }
142 // Check if NUM_MODULES is enough to list all modules
143 new_size = needed / sizeof(HMODULE);
Jonathan Peyton95246e72015-11-05 16:54:55 +0000144 if (new_size > NUM_MODULES) {
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000145#if OMPT_DEBUG
146 printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);
147#endif
148 modules = (HMODULE*)realloc( modules, needed );
149 // If resizing failed use the stub function.
Jonathan Peyton95246e72015-11-05 16:54:55 +0000150 if (!EnumProcessModules(process, modules, needed, &needed)) {
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000151 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000152 return NULL;
153 }
154 }
Jonathan Peyton95246e72015-11-05 16:54:55 +0000155 for (i = 0; i < new_size; ++i) {
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000156 (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_tool");
Jonathan Peyton95246e72015-11-05 16:54:55 +0000157 if (ompt_tool_p) {
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000158#if OMPT_DEBUG
159 TCHAR modName[MAX_PATH];
Jonathan Peyton95246e72015-11-05 16:54:55 +0000160 if (GetModuleFileName(modules[i], modName, MAX_PATH))
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000161 printf("ompt_tool_windows(): ompt_tool found in module %s\n",
162 modName);
163#endif
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000164 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000165 return ompt_tool_p();
166 }
167#if OMPT_DEBUG
168 else {
169 TCHAR modName[MAX_PATH];
Jonathan Peyton95246e72015-11-05 16:54:55 +0000170 if (GetModuleFileName(modules[i], modName, MAX_PATH))
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000171 printf("ompt_tool_windows(): ompt_tool not found in module %s\n",
172 modName);
173 }
174#endif
175 }
Jonathan Peyton57d171c2015-10-30 20:24:25 +0000176 free(modules);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000177 return NULL;
178}
179#else
180# error Either __attribute__((weak)) or psapi.dll are required for OMPT support
181#endif // OMPT_HAVE_WEAK_ATTRIBUTE
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000182
183void ompt_pre_init()
184{
185 //--------------------------------------------------
186 // Execute the pre-initialization logic only once.
187 //--------------------------------------------------
188 static int ompt_pre_initialized = 0;
189
190 if (ompt_pre_initialized) return;
191
192 ompt_pre_initialized = 1;
193
194 //--------------------------------------------------
195 // Use a tool iff a tool is enabled and available.
196 //--------------------------------------------------
197 const char *ompt_env_var = getenv("OMP_TOOL");
198 tool_setting_e tool_setting = omp_tool_error;
199
200 if (!ompt_env_var || !strcmp(ompt_env_var, ""))
201 tool_setting = omp_tool_unset;
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000202 else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000203 tool_setting = omp_tool_disabled;
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000204 else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000205 tool_setting = omp_tool_enabled;
206
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000207#if OMPT_DEBUG
208 printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);
209#endif
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000210 switch(tool_setting) {
211 case omp_tool_disabled:
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000212 break;
213
214 case omp_tool_unset:
215 case omp_tool_enabled:
216 ompt_initialize_fn = ompt_tool();
217 if (ompt_initialize_fn) {
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000218 ompt_enabled = 1;
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000219 }
220 break;
221
222 case omp_tool_error:
223 fprintf(stderr,
224 "Warning: OMP_TOOL has invalid value \"%s\".\n"
225 " legal values are (NULL,\"\",\"disabled\","
226 "\"enabled\").\n", ompt_env_var);
227 break;
228 }
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000229#if OMPT_DEBUG
Jonathan Peyton95246e72015-11-05 16:54:55 +0000230 printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled);
Jonathan Peyton69e596a2015-10-29 20:56:24 +0000231#endif
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000232}
233
234
235void ompt_post_init()
236{
237 //--------------------------------------------------
238 // Execute the post-initialization logic only once.
239 //--------------------------------------------------
240 static int ompt_post_initialized = 0;
241
242 if (ompt_post_initialized) return;
243
244 ompt_post_initialized = 1;
245
246 //--------------------------------------------------
247 // Initialize the tool if so indicated.
248 //--------------------------------------------------
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000249 if (ompt_enabled) {
Jonathan Peyton61118492016-05-20 19:03:38 +0000250 ompt_initialize_fn(ompt_fn_lookup, ompt_get_runtime_version(),
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000251 OMPT_VERSION);
252
253 ompt_thread_t *root_thread = ompt_get_thread();
254
255 ompt_set_thread_state(root_thread, ompt_state_overhead);
256
257 if (ompt_callbacks.ompt_callback(ompt_event_thread_begin)) {
258 ompt_callbacks.ompt_callback(ompt_event_thread_begin)
259 (ompt_thread_initial, ompt_get_thread_id());
260 }
261
262 ompt_set_thread_state(root_thread, ompt_state_work_serial);
263 }
264}
265
266
267void ompt_fini()
268{
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000269 if (ompt_enabled) {
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000270 if (ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)) {
271 ompt_callbacks.ompt_callback(ompt_event_runtime_shutdown)();
272 }
273 }
274
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000275 ompt_enabled = 0;
Jonathan Peyton82a13bf2015-09-21 18:01:02 +0000276}
277
278
279/*****************************************************************************
280 * interface operations
281 ****************************************************************************/
Andrey Churbanove5f44922015-04-29 16:22:07 +0000282
283/*****************************************************************************
284 * state
285 ****************************************************************************/
286
287OMPT_API_ROUTINE int ompt_enumerate_state(int current_state, int *next_state,
288 const char **next_state_name)
289{
290 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);
291 int i = 0;
292
293 for (i = 0; i < len - 1; i++) {
294 if (ompt_state_info[i].state_id == current_state) {
295 *next_state = ompt_state_info[i+1].state_id;
296 *next_state_name = ompt_state_info[i+1].state_name;
297 return 1;
298 }
299 }
300
301 return 0;
302}
303
304
305
306/*****************************************************************************
307 * callbacks
308 ****************************************************************************/
309
310OMPT_API_ROUTINE int ompt_set_callback(ompt_event_t evid, ompt_callback_t cb)
311{
312 switch (evid) {
313
314#define ompt_event_macro(event_name, callback_type, event_id) \
315 case event_name: \
316 if (ompt_event_implementation_status(event_name)) { \
317 ompt_callbacks.ompt_callback(event_name) = (callback_type) cb; \
318 } \
319 return ompt_event_implementation_status(event_name);
320
321 FOREACH_OMPT_EVENT(ompt_event_macro)
322
323#undef ompt_event_macro
324
325 default: return ompt_set_result_registration_error;
326 }
327}
328
329
330OMPT_API_ROUTINE int ompt_get_callback(ompt_event_t evid, ompt_callback_t *cb)
331{
332 switch (evid) {
333
334#define ompt_event_macro(event_name, callback_type, event_id) \
335 case event_name: \
336 if (ompt_event_implementation_status(event_name)) { \
337 ompt_callback_t mycb = \
338 (ompt_callback_t) ompt_callbacks.ompt_callback(event_name); \
339 if (mycb) { \
340 *cb = mycb; \
341 return ompt_get_callback_success; \
342 } \
343 } \
344 return ompt_get_callback_failure;
345
346 FOREACH_OMPT_EVENT(ompt_event_macro)
347
348#undef ompt_event_macro
349
350 default: return ompt_get_callback_failure;
351 }
352}
353
354
Andrey Churbanove5f44922015-04-29 16:22:07 +0000355/*****************************************************************************
356 * parallel regions
357 ****************************************************************************/
358
359OMPT_API_ROUTINE ompt_parallel_id_t ompt_get_parallel_id(int ancestor_level)
360{
361 return __ompt_get_parallel_id_internal(ancestor_level);
362}
363
364
365OMPT_API_ROUTINE int ompt_get_parallel_team_size(int ancestor_level)
366{
367 return __ompt_get_parallel_team_size_internal(ancestor_level);
368}
369
370
371OMPT_API_ROUTINE void *ompt_get_parallel_function(int ancestor_level)
372{
373 return __ompt_get_parallel_function_internal(ancestor_level);
374}
375
376
377OMPT_API_ROUTINE ompt_state_t ompt_get_state(ompt_wait_id_t *ompt_wait_id)
378{
379 ompt_state_t thread_state = __ompt_get_state_internal(ompt_wait_id);
380
381 if (thread_state == ompt_state_undefined) {
382 thread_state = ompt_state_work_serial;
383 }
384
385 return thread_state;
386}
387
388
389
390/*****************************************************************************
391 * threads
392 ****************************************************************************/
393
394
395OMPT_API_ROUTINE void *ompt_get_idle_frame()
396{
397 return __ompt_get_idle_frame_internal();
398}
399
400
401
402/*****************************************************************************
403 * tasks
404 ****************************************************************************/
405
406
407OMPT_API_ROUTINE ompt_thread_id_t ompt_get_thread_id(void)
408{
409 return __ompt_get_thread_id_internal();
410}
411
412OMPT_API_ROUTINE ompt_task_id_t ompt_get_task_id(int depth)
413{
414 return __ompt_get_task_id_internal(depth);
415}
416
417
418OMPT_API_ROUTINE ompt_frame_t *ompt_get_task_frame(int depth)
419{
420 return __ompt_get_task_frame_internal(depth);
421}
422
423
424OMPT_API_ROUTINE void *ompt_get_task_function(int depth)
425{
426 return __ompt_get_task_function_internal(depth);
427}
428
429
430/*****************************************************************************
431 * placeholders
432 ****************************************************************************/
433
Jonathan Peyton122dd762015-07-13 18:55:45 +0000434// Don't define this as static. The loader may choose to eliminate the symbol
Jonathan Peyton61118492016-05-20 19:03:38 +0000435// even though it is needed by tools.
436#define OMPT_API_PLACEHOLDER
Andrey Churbanove5f44922015-04-29 16:22:07 +0000437
Jonathan Peyton122dd762015-07-13 18:55:45 +0000438// Ensure that placeholders don't have mangled names in the symbol table.
439#ifdef __cplusplus
440extern "C" {
441#endif
442
443
Jonathan Peyton61118492016-05-20 19:03:38 +0000444OMPT_API_PLACEHOLDER void ompt_idle(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000445{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000446 // This function is a placeholder used to represent the calling context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000447 // idle OpenMP worker threads. It is not meant to be invoked.
448 assert(0);
449}
450
451
Jonathan Peyton122dd762015-07-13 18:55:45 +0000452OMPT_API_PLACEHOLDER void ompt_overhead(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000453{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000454 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000455 // threads working in the OpenMP runtime. It is not meant to be invoked.
456 assert(0);
457}
458
459
Jonathan Peyton122dd762015-07-13 18:55:45 +0000460OMPT_API_PLACEHOLDER void ompt_barrier_wait(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000461{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000462 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000463 // threads waiting for a barrier in the OpenMP runtime. It is not meant
464 // to be invoked.
465 assert(0);
466}
467
468
Jonathan Peyton122dd762015-07-13 18:55:45 +0000469OMPT_API_PLACEHOLDER void ompt_task_wait(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000470{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000471 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000472 // threads waiting for a task in the OpenMP runtime. It is not meant
473 // to be invoked.
474 assert(0);
475}
476
477
Jonathan Peyton122dd762015-07-13 18:55:45 +0000478OMPT_API_PLACEHOLDER void ompt_mutex_wait(void)
Andrey Churbanove5f44922015-04-29 16:22:07 +0000479{
Jonathan Peyton122dd762015-07-13 18:55:45 +0000480 // This function is a placeholder used to represent the OpenMP context of
Andrey Churbanove5f44922015-04-29 16:22:07 +0000481 // threads waiting for a mutex in the OpenMP runtime. It is not meant
482 // to be invoked.
483 assert(0);
484}
485
Jonathan Peyton122dd762015-07-13 18:55:45 +0000486#ifdef __cplusplus
487};
488#endif
489
Andrey Churbanove5f44922015-04-29 16:22:07 +0000490
491/*****************************************************************************
492 * compatability
493 ****************************************************************************/
494
495OMPT_API_ROUTINE int ompt_get_ompt_version()
496{
497 return OMPT_VERSION;
498}
499
500
501
502/*****************************************************************************
503 * application-facing API
504 ****************************************************************************/
505
506
507/*----------------------------------------------------------------------------
508 | control
509 ---------------------------------------------------------------------------*/
510
511_OMP_EXTERN void ompt_control(uint64_t command, uint64_t modifier)
512{
Jonathan Peytonb68a85d2015-09-21 18:11:22 +0000513 if (ompt_enabled && ompt_callbacks.ompt_callback(ompt_event_control)) {
Andrey Churbanove5f44922015-04-29 16:22:07 +0000514 ompt_callbacks.ompt_callback(ompt_event_control)(command, modifier);
515 }
516}
517
518
519
520/*****************************************************************************
521 * API inquiry for tool
522 ****************************************************************************/
523
524static ompt_interface_fn_t ompt_fn_lookup(const char *s)
525{
526
527#define ompt_interface_fn(fn) \
528 if (strcmp(s, #fn) == 0) return (ompt_interface_fn_t) fn;
529
530 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
531
532 FOREACH_OMPT_PLACEHOLDER_FN(ompt_interface_fn)
533
534 return (ompt_interface_fn_t) 0;
535}