[SmallPtrSet] Remove SmallArray member (NFC) (#118099)
[llvm-project.git] / openmp / runtime / src / ompt-general.cpp
blobcd738f066fcfcfde0245b204aa284b2f83fc0b03
1 /*
2 * ompt-general.cpp -- OMPT implementation of interface functions
3 */
5 //===----------------------------------------------------------------------===//
6 //
7 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
8 // See https://llvm.org/LICENSE.txt for license information.
9 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
11 //===----------------------------------------------------------------------===//
13 #include "kmp_utils.h"
15 /*****************************************************************************
16 * system include files
17 ****************************************************************************/
18 #include <assert.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #if KMP_OS_UNIX
25 #include <dlfcn.h>
26 #endif
28 /*****************************************************************************
29 * ompt include files
30 ****************************************************************************/
32 #include "ompt-specific.cpp"
34 /*****************************************************************************
35 * macros
36 ****************************************************************************/
38 #define ompt_get_callback_success 1
39 #define ompt_get_callback_failure 0
41 #define no_tool_present 0
43 #define OMPT_API_ROUTINE static
45 #ifndef OMPT_STR_MATCH
46 #define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))
47 #endif
49 // prints for an enabled OMP_TOOL_VERBOSE_INIT.
50 // In the future a prefix could be added in the first define, the second define
51 // omits the prefix to allow for continued lines. Example: "PREFIX: Start
52 // tool... Success." instead of "PREFIX: Start tool... PREFIX: Success."
53 #define OMPT_VERBOSE_INIT_PRINT(...) \
54 if (verbose_init) \
55 fprintf(verbose_file, __VA_ARGS__)
56 #define OMPT_VERBOSE_INIT_CONTINUED_PRINT(...) \
57 if (verbose_init) \
58 fprintf(verbose_file, __VA_ARGS__)
60 static FILE *verbose_file;
61 static int verbose_init;
63 /*****************************************************************************
64 * types
65 ****************************************************************************/
67 typedef struct {
68 const char *state_name;
69 ompt_state_t state_id;
70 } ompt_state_info_t;
72 typedef struct {
73 const char *name;
74 kmp_mutex_impl_t id;
75 } kmp_mutex_impl_info_t;
77 enum tool_setting_e {
78 omp_tool_error,
79 omp_tool_unset,
80 omp_tool_disabled,
81 omp_tool_enabled
84 /*****************************************************************************
85 * global variables
86 ****************************************************************************/
88 ompt_callbacks_active_t ompt_enabled;
90 ompt_state_info_t ompt_state_info[] = {
91 #define ompt_state_macro(state, code) {#state, state},
92 FOREACH_OMPT_STATE(ompt_state_macro)
93 #undef ompt_state_macro
96 kmp_mutex_impl_info_t kmp_mutex_impl_info[] = {
97 #define kmp_mutex_impl_macro(name, id) {#name, name},
98 FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro)
99 #undef kmp_mutex_impl_macro
102 ompt_callbacks_internal_t ompt_callbacks;
104 static ompt_start_tool_result_t *ompt_start_tool_result = NULL;
106 #if KMP_OS_WINDOWS
107 static HMODULE ompt_tool_module = NULL;
108 static HMODULE ompt_archer_module = NULL;
109 #define OMPT_DLCLOSE(Lib) FreeLibrary(Lib)
110 #else
111 static void *ompt_tool_module = NULL;
112 static void *ompt_archer_module = NULL;
113 #define OMPT_DLCLOSE(Lib) dlclose(Lib)
114 #endif
116 /// Used to track the initializer and the finalizer provided by libomptarget
117 static ompt_start_tool_result_t *libomptarget_ompt_result = NULL;
119 /*****************************************************************************
120 * forward declarations
121 ****************************************************************************/
123 static ompt_interface_fn_t ompt_fn_lookup(const char *s);
125 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void);
127 /*****************************************************************************
128 * initialization and finalization (private operations)
129 ****************************************************************************/
131 typedef ompt_start_tool_result_t *(*ompt_start_tool_t)(unsigned int,
132 const char *);
134 #if KMP_OS_DARWIN
136 // While Darwin supports weak symbols, the library that wishes to provide a new
137 // implementation has to link against this runtime which defeats the purpose
138 // of having tools that are agnostic of the underlying runtime implementation.
140 // Fortunately, the linker includes all symbols of an executable in the global
141 // symbol table by default so dlsym() even finds static implementations of
142 // ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be
143 // passed when building the application which we don't want to rely on.
145 static ompt_start_tool_result_t *ompt_tool_darwin(unsigned int omp_version,
146 const char *runtime_version) {
147 ompt_start_tool_result_t *ret = NULL;
148 // Search symbol in the current address space.
149 ompt_start_tool_t start_tool =
150 (ompt_start_tool_t)dlsym(RTLD_DEFAULT, "ompt_start_tool");
151 if (start_tool) {
152 ret = start_tool(omp_version, runtime_version);
154 return ret;
157 #elif OMPT_HAVE_WEAK_ATTRIBUTE
159 // On Unix-like systems that support weak symbols the following implementation
160 // of ompt_start_tool() will be used in case no tool-supplied implementation of
161 // this function is present in the address space of a process.
163 _OMP_EXTERN OMPT_WEAK_ATTRIBUTE ompt_start_tool_result_t *
164 ompt_start_tool(unsigned int omp_version, const char *runtime_version) {
165 ompt_start_tool_result_t *ret = NULL;
166 // Search next symbol in the current address space. This can happen if the
167 // runtime library is linked before the tool. Since glibc 2.2 strong symbols
168 // don't override weak symbols that have been found before unless the user
169 // sets the environment variable LD_DYNAMIC_WEAK.
170 ompt_start_tool_t next_tool =
171 (ompt_start_tool_t)dlsym(RTLD_NEXT, "ompt_start_tool");
172 if (next_tool) {
173 ret = next_tool(omp_version, runtime_version);
175 return ret;
178 #elif OMPT_HAVE_PSAPI
180 // On Windows, the ompt_tool_windows function is used to find the
181 // ompt_start_tool symbol across all modules loaded by a process. If
182 // ompt_start_tool is found, ompt_start_tool's return value is used to
183 // initialize the tool. Otherwise, NULL is returned and OMPT won't be enabled.
185 #include <psapi.h>
186 #pragma comment(lib, "psapi.lib")
188 // The number of loaded modules to start enumeration with EnumProcessModules()
189 #define NUM_MODULES 128
191 static ompt_start_tool_result_t *
192 ompt_tool_windows(unsigned int omp_version, const char *runtime_version) {
193 int i;
194 DWORD needed, new_size;
195 HMODULE *modules;
196 HANDLE process = GetCurrentProcess();
197 modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE));
198 ompt_start_tool_t ompt_tool_p = NULL;
200 #if OMPT_DEBUG
201 printf("ompt_tool_windows(): looking for ompt_start_tool\n");
202 #endif
203 if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE),
204 &needed)) {
205 // Regardless of the error reason use the stub initialization function
206 free(modules);
207 return NULL;
209 // Check if NUM_MODULES is enough to list all modules
210 new_size = needed / sizeof(HMODULE);
211 if (new_size > NUM_MODULES) {
212 #if OMPT_DEBUG
213 printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);
214 #endif
215 modules = (HMODULE *)realloc(modules, needed);
216 // If resizing failed use the stub function.
217 if (!EnumProcessModules(process, modules, needed, &needed)) {
218 free(modules);
219 return NULL;
222 for (i = 0; i < new_size; ++i) {
223 (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_start_tool");
224 if (ompt_tool_p) {
225 #if OMPT_DEBUG
226 TCHAR modName[MAX_PATH];
227 if (GetModuleFileName(modules[i], modName, MAX_PATH))
228 printf("ompt_tool_windows(): ompt_start_tool found in module %s\n",
229 modName);
230 #endif
231 free(modules);
232 return (*ompt_tool_p)(omp_version, runtime_version);
234 #if OMPT_DEBUG
235 else {
236 TCHAR modName[MAX_PATH];
237 if (GetModuleFileName(modules[i], modName, MAX_PATH))
238 printf("ompt_tool_windows(): ompt_start_tool not found in module %s\n",
239 modName);
241 #endif
243 free(modules);
244 return NULL;
246 #else
247 #error Activation of OMPT is not supported on this platform.
248 #endif
250 static ompt_start_tool_result_t *
251 ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) {
252 ompt_start_tool_result_t *ret = NULL;
253 ompt_start_tool_t start_tool = NULL;
254 #if KMP_OS_WINDOWS
255 // Cannot use colon to describe a list of absolute paths on Windows
256 const char *sep = ";";
257 #else
258 const char *sep = ":";
259 #endif
261 OMPT_VERBOSE_INIT_PRINT("----- START LOGGING OF TOOL REGISTRATION -----\n");
262 OMPT_VERBOSE_INIT_PRINT("Search for OMP tool in current address space... ");
264 #if KMP_OS_DARWIN
265 // Try in the current address space
266 ret = ompt_tool_darwin(omp_version, runtime_version);
267 #elif OMPT_HAVE_WEAK_ATTRIBUTE
268 ret = ompt_start_tool(omp_version, runtime_version);
269 #elif OMPT_HAVE_PSAPI
270 ret = ompt_tool_windows(omp_version, runtime_version);
271 #else
272 #error Activation of OMPT is not supported on this platform.
273 #endif
274 if (ret) {
275 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
276 OMPT_VERBOSE_INIT_PRINT(
277 "Tool was started and is using the OMPT interface.\n");
278 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");
279 return ret;
282 // Try tool-libraries-var ICV
283 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed.\n");
284 const char *tool_libs = getenv("OMP_TOOL_LIBRARIES");
285 if (tool_libs) {
286 OMPT_VERBOSE_INIT_PRINT("Searching tool libraries...\n");
287 OMPT_VERBOSE_INIT_PRINT("OMP_TOOL_LIBRARIES = %s\n", tool_libs);
288 char *libs = __kmp_str_format("%s", tool_libs);
289 char *buf;
290 char *fname = __kmp_str_token(libs, sep, &buf);
291 // Reset dl-error
292 dlerror();
294 while (fname) {
295 #if KMP_OS_UNIX
296 OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);
297 void *h = dlopen(fname, RTLD_LAZY);
298 if (!h) {
299 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror());
300 } else {
301 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n");
302 OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ",
303 fname);
304 dlerror(); // Clear any existing error
305 start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");
306 if (!start_tool) {
307 char *error = dlerror();
308 if (error != NULL) {
309 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", error);
310 } else {
311 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n",
312 "ompt_start_tool = NULL");
314 } else
315 #elif KMP_OS_WINDOWS
316 OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);
317 HMODULE h = LoadLibrary(fname);
318 if (!h) {
319 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n",
320 (unsigned)GetLastError());
321 } else {
322 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n");
323 OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ",
324 fname);
325 start_tool = (ompt_start_tool_t)GetProcAddress(h, "ompt_start_tool");
326 if (!start_tool) {
327 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n",
328 (unsigned)GetLastError());
329 } else
330 #else
331 #error Activation of OMPT is not supported on this platform.
332 #endif
333 { // if (start_tool)
334 ret = (*start_tool)(omp_version, runtime_version);
335 if (ret) {
336 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
337 OMPT_VERBOSE_INIT_PRINT(
338 "Tool was started and is using the OMPT interface.\n");
339 ompt_tool_module = h;
340 break;
342 OMPT_VERBOSE_INIT_CONTINUED_PRINT(
343 "Found but not using the OMPT interface.\n");
344 OMPT_VERBOSE_INIT_PRINT("Continuing search...\n");
346 OMPT_DLCLOSE(h);
348 fname = __kmp_str_token(NULL, sep, &buf);
350 __kmp_str_free(&libs);
351 } else {
352 OMPT_VERBOSE_INIT_PRINT("No OMP_TOOL_LIBRARIES defined.\n");
355 // usable tool found in tool-libraries
356 if (ret) {
357 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");
358 return ret;
361 #if KMP_OS_UNIX
362 { // Non-standard: load archer tool if application is built with TSan
363 const char *fname = "libarcher.so";
364 OMPT_VERBOSE_INIT_PRINT(
365 "...searching tool libraries failed. Using archer tool.\n");
366 OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);
367 void *h = dlopen(fname, RTLD_LAZY);
368 if (h) {
369 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
370 OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ", fname);
371 start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");
372 if (start_tool) {
373 ret = (*start_tool)(omp_version, runtime_version);
374 if (ret) {
375 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
376 OMPT_VERBOSE_INIT_PRINT(
377 "Tool was started and is using the OMPT interface.\n");
378 OMPT_VERBOSE_INIT_PRINT(
379 "----- END LOGGING OF TOOL REGISTRATION -----\n");
380 ompt_archer_module = h;
381 return ret;
383 OMPT_VERBOSE_INIT_CONTINUED_PRINT(
384 "Found but not using the OMPT interface.\n");
385 } else {
386 OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror());
388 OMPT_DLCLOSE(h);
391 #endif
392 OMPT_VERBOSE_INIT_PRINT("No OMP tool loaded.\n");
393 OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");
394 return ret;
397 void ompt_pre_init() {
398 //--------------------------------------------------
399 // Execute the pre-initialization logic only once.
400 //--------------------------------------------------
401 static int ompt_pre_initialized = 0;
403 if (ompt_pre_initialized)
404 return;
406 ompt_pre_initialized = 1;
408 //--------------------------------------------------
409 // Use a tool iff a tool is enabled and available.
410 //--------------------------------------------------
411 const char *ompt_env_var = getenv("OMP_TOOL");
412 tool_setting_e tool_setting = omp_tool_error;
414 if (!ompt_env_var || !strcmp(ompt_env_var, ""))
415 tool_setting = omp_tool_unset;
416 else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))
417 tool_setting = omp_tool_disabled;
418 else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))
419 tool_setting = omp_tool_enabled;
421 const char *ompt_env_verbose_init = getenv("OMP_TOOL_VERBOSE_INIT");
422 // possible options: disabled | stdout | stderr | <filename>
423 // if set, not empty and not disabled -> prepare for logging
424 if (ompt_env_verbose_init && strcmp(ompt_env_verbose_init, "") &&
425 !OMPT_STR_MATCH(ompt_env_verbose_init, "disabled")) {
426 verbose_init = 1;
427 if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDERR"))
428 verbose_file = stderr;
429 else if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDOUT"))
430 verbose_file = stdout;
431 else
432 verbose_file = fopen(ompt_env_verbose_init, "w");
433 } else
434 verbose_init = 0;
436 #if OMPT_DEBUG
437 printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);
438 #endif
439 switch (tool_setting) {
440 case omp_tool_disabled:
441 OMPT_VERBOSE_INIT_PRINT("OMP tool disabled. \n");
442 break;
444 case omp_tool_unset:
445 case omp_tool_enabled:
447 //--------------------------------------------------
448 // Load tool iff specified in environment variable
449 //--------------------------------------------------
450 ompt_start_tool_result =
451 ompt_try_start_tool(__kmp_openmp_version, ompt_get_runtime_version());
453 memset(&ompt_enabled, 0, sizeof(ompt_enabled));
454 break;
456 case omp_tool_error:
457 fprintf(stderr,
458 "Warning: OMP_TOOL has invalid value \"%s\".\n"
459 " legal values are (NULL,\"\",\"disabled\","
460 "\"enabled\").\n",
461 ompt_env_var);
462 break;
464 if (verbose_init && verbose_file != stderr && verbose_file != stdout)
465 fclose(verbose_file);
466 #if OMPT_DEBUG
467 printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled.enabled);
468 #endif
471 extern "C" int omp_get_initial_device(void);
473 void ompt_post_init() {
474 //--------------------------------------------------
475 // Execute the post-initialization logic only once.
476 //--------------------------------------------------
477 static int ompt_post_initialized = 0;
479 if (ompt_post_initialized)
480 return;
482 ompt_post_initialized = 1;
484 //--------------------------------------------------
485 // Initialize the tool if so indicated.
486 //--------------------------------------------------
487 if (ompt_start_tool_result) {
488 ompt_enabled.enabled = !!ompt_start_tool_result->initialize(
489 ompt_fn_lookup, omp_get_initial_device(),
490 &(ompt_start_tool_result->tool_data));
492 if (!ompt_enabled.enabled) {
493 // tool not enabled, zero out the bitmap, and done
494 memset(&ompt_enabled, 0, sizeof(ompt_enabled));
495 return;
498 kmp_info_t *root_thread = ompt_get_thread();
500 ompt_set_thread_state(root_thread, ompt_state_overhead);
502 if (ompt_enabled.ompt_callback_thread_begin) {
503 ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
504 ompt_thread_initial, __ompt_get_thread_data_internal());
506 ompt_data_t *task_data = nullptr;
507 ompt_data_t *parallel_data = nullptr;
508 __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,
509 NULL);
510 if (ompt_enabled.ompt_callback_implicit_task) {
511 ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
512 ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial);
515 ompt_set_thread_state(root_thread, ompt_state_work_serial);
519 void ompt_fini() {
520 if (ompt_enabled.enabled) {
521 if (ompt_start_tool_result && ompt_start_tool_result->finalize) {
522 ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data));
524 if (libomptarget_ompt_result && libomptarget_ompt_result->finalize) {
525 libomptarget_ompt_result->finalize(NULL);
529 if (ompt_archer_module)
530 OMPT_DLCLOSE(ompt_archer_module);
531 if (ompt_tool_module)
532 OMPT_DLCLOSE(ompt_tool_module);
533 memset(&ompt_enabled, 0, sizeof(ompt_enabled));
536 /*****************************************************************************
537 * interface operations
538 ****************************************************************************/
540 /*****************************************************************************
541 * state
542 ****************************************************************************/
544 OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state,
545 const char **next_state_name) {
546 const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);
547 int i = 0;
549 for (i = 0; i < len - 1; i++) {
550 if (ompt_state_info[i].state_id == current_state) {
551 *next_state = ompt_state_info[i + 1].state_id;
552 *next_state_name = ompt_state_info[i + 1].state_name;
553 return 1;
557 return 0;
560 OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl,
561 int *next_impl,
562 const char **next_impl_name) {
563 const static int len =
564 sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t);
565 int i = 0;
566 for (i = 0; i < len - 1; i++) {
567 if (kmp_mutex_impl_info[i].id != current_impl)
568 continue;
569 *next_impl = kmp_mutex_impl_info[i + 1].id;
570 *next_impl_name = kmp_mutex_impl_info[i + 1].name;
571 return 1;
573 return 0;
576 /*****************************************************************************
577 * callbacks
578 ****************************************************************************/
580 OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which,
581 ompt_callback_t callback) {
582 switch (which) {
584 #define ompt_event_macro(event_name, callback_type, event_id) \
585 case event_name: \
586 ompt_callbacks.ompt_callback(event_name) = (callback_type)callback; \
587 ompt_enabled.event_name = (callback != 0); \
588 if (callback) \
589 return ompt_event_implementation_status(event_name); \
590 else \
591 return ompt_set_always;
593 FOREACH_OMPT_EVENT(ompt_event_macro)
595 #undef ompt_event_macro
597 default:
598 return ompt_set_error;
602 OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which,
603 ompt_callback_t *callback) {
604 if (!ompt_enabled.enabled)
605 return ompt_get_callback_failure;
607 switch (which) {
609 #define ompt_event_macro(event_name, callback_type, event_id) \
610 case event_name: { \
611 ompt_callback_t mycb = \
612 (ompt_callback_t)ompt_callbacks.ompt_callback(event_name); \
613 if (ompt_enabled.event_name && mycb) { \
614 *callback = mycb; \
615 return ompt_get_callback_success; \
617 return ompt_get_callback_failure; \
620 FOREACH_OMPT_EVENT(ompt_event_macro)
622 #undef ompt_event_macro
624 default:
625 return ompt_get_callback_failure;
629 /*****************************************************************************
630 * parallel regions
631 ****************************************************************************/
633 OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level,
634 ompt_data_t **parallel_data,
635 int *team_size) {
636 if (!ompt_enabled.enabled)
637 return 0;
638 return __ompt_get_parallel_info_internal(ancestor_level, parallel_data,
639 team_size);
642 OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) {
643 if (!ompt_enabled.enabled)
644 return ompt_state_work_serial;
645 int thread_state = __ompt_get_state_internal(wait_id);
647 if (thread_state == ompt_state_undefined) {
648 thread_state = ompt_state_work_serial;
651 return thread_state;
654 /*****************************************************************************
655 * tasks
656 ****************************************************************************/
658 OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) {
659 if (!ompt_enabled.enabled)
660 return NULL;
661 return __ompt_get_thread_data_internal();
664 OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type,
665 ompt_data_t **task_data,
666 ompt_frame_t **task_frame,
667 ompt_data_t **parallel_data,
668 int *thread_num) {
669 if (!ompt_enabled.enabled)
670 return 0;
671 return __ompt_get_task_info_internal(ancestor_level, type, task_data,
672 task_frame, parallel_data, thread_num);
675 OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size,
676 int block) {
677 return __ompt_get_task_memory_internal(addr, size, block);
680 /*****************************************************************************
681 * num_procs
682 ****************************************************************************/
684 OMPT_API_ROUTINE int ompt_get_num_procs(void) {
685 // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when
686 // runtime is initialized)
687 return __kmp_avail_proc;
690 /*****************************************************************************
691 * places
692 ****************************************************************************/
694 OMPT_API_ROUTINE int ompt_get_num_places(void) {
695 // copied from kmp_ftn_entry.h (but modified)
696 #if !KMP_AFFINITY_SUPPORTED
697 return 0;
698 #else
699 if (!KMP_AFFINITY_CAPABLE())
700 return 0;
701 return __kmp_affinity.num_masks;
702 #endif
705 OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size,
706 int *ids) {
707 // copied from kmp_ftn_entry.h (but modified)
708 #if !KMP_AFFINITY_SUPPORTED
709 return 0;
710 #else
711 int i, count;
712 SimpleVLA<int> tmp_ids(ids_size);
713 for (int j = 0; j < ids_size; j++)
714 tmp_ids[j] = 0;
715 if (!KMP_AFFINITY_CAPABLE())
716 return 0;
717 if (place_num < 0 || place_num >= (int)__kmp_affinity.num_masks)
718 return 0;
719 /* TODO: Is this safe for asynchronous call from signal handler during runtime
720 * shutdown? */
721 kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity.masks, place_num);
722 count = 0;
723 KMP_CPU_SET_ITERATE(i, mask) {
724 if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||
725 (!KMP_CPU_ISSET(i, mask))) {
726 continue;
728 if (count < ids_size)
729 tmp_ids[count] = i;
730 count++;
732 if (ids_size >= count) {
733 for (i = 0; i < count; i++) {
734 ids[i] = tmp_ids[i];
737 return count;
738 #endif
741 OMPT_API_ROUTINE int ompt_get_place_num(void) {
742 // copied from kmp_ftn_entry.h (but modified)
743 #if !KMP_AFFINITY_SUPPORTED
744 return -1;
745 #else
746 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
747 return -1;
749 int gtid;
750 kmp_info_t *thread;
751 if (!KMP_AFFINITY_CAPABLE())
752 return -1;
753 gtid = __kmp_entry_gtid();
754 thread = __kmp_thread_from_gtid(gtid);
755 if (thread == NULL || thread->th.th_current_place < 0)
756 return -1;
757 return thread->th.th_current_place;
758 #endif
761 OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size,
762 int *place_nums) {
763 // copied from kmp_ftn_entry.h (but modified)
764 #if !KMP_AFFINITY_SUPPORTED
765 return 0;
766 #else
767 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
768 return 0;
770 int i, gtid, place_num, first_place, last_place, start, end;
771 kmp_info_t *thread;
772 if (!KMP_AFFINITY_CAPABLE())
773 return 0;
774 gtid = __kmp_entry_gtid();
775 thread = __kmp_thread_from_gtid(gtid);
776 if (thread == NULL)
777 return 0;
778 first_place = thread->th.th_first_place;
779 last_place = thread->th.th_last_place;
780 if (first_place < 0 || last_place < 0)
781 return 0;
782 if (first_place <= last_place) {
783 start = first_place;
784 end = last_place;
785 } else {
786 start = last_place;
787 end = first_place;
789 if (end - start <= place_nums_size)
790 for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) {
791 place_nums[i] = place_num;
793 return end - start + 1;
794 #endif
797 /*****************************************************************************
798 * places
799 ****************************************************************************/
801 OMPT_API_ROUTINE int ompt_get_proc_id(void) {
802 if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
803 return -1;
804 #if KMP_HAVE_SCHED_GETCPU
805 return sched_getcpu();
806 #elif KMP_OS_WINDOWS
807 PROCESSOR_NUMBER pn;
808 GetCurrentProcessorNumberEx(&pn);
809 return 64 * pn.Group + pn.Number;
810 #else
811 return -1;
812 #endif
815 /*****************************************************************************
816 * compatability
817 ****************************************************************************/
820 * Currently unused function
821 OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; }
824 /*****************************************************************************
825 * application-facing API
826 ****************************************************************************/
828 /*----------------------------------------------------------------------------
829 | control
830 ---------------------------------------------------------------------------*/
832 int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) {
834 if (ompt_enabled.enabled) {
835 if (ompt_enabled.ompt_callback_control_tool) {
836 return ompt_callbacks.ompt_callback(ompt_callback_control_tool)(
837 command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid()));
838 } else {
839 return -1;
841 } else {
842 return -2;
846 /*****************************************************************************
847 * misc
848 ****************************************************************************/
850 OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) {
851 return __ompt_get_unique_id_internal();
854 OMPT_API_ROUTINE void ompt_finalize_tool(void) { __kmp_internal_end_atexit(); }
856 /*****************************************************************************
857 * Target
858 ****************************************************************************/
860 OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num,
861 ompt_id_t *target_id,
862 ompt_id_t *host_op_id) {
863 return 0; // thread is not in a target region
866 OMPT_API_ROUTINE int ompt_get_num_devices(void) {
867 return 1; // only one device (the current device) is available
870 /*****************************************************************************
871 * API inquiry for tool
872 ****************************************************************************/
874 static ompt_interface_fn_t ompt_fn_lookup(const char *s) {
876 #define ompt_interface_fn(fn) \
877 fn##_t fn##_f = fn; \
878 if (strcmp(s, #fn) == 0) \
879 return (ompt_interface_fn_t)fn##_f;
881 FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
883 #undef ompt_interface_fn
885 return NULL;
888 static ompt_data_t *ompt_get_task_data() { return __ompt_get_task_data(); }
890 static ompt_data_t *ompt_get_target_task_data() {
891 return __ompt_get_target_task_data();
894 /// Lookup function to query libomp callbacks registered by the tool
895 static ompt_interface_fn_t ompt_libomp_target_fn_lookup(const char *s) {
896 #define provide_fn(fn) \
897 if (strcmp(s, #fn) == 0) \
898 return (ompt_interface_fn_t)fn;
900 provide_fn(ompt_get_callback);
901 provide_fn(ompt_get_task_data);
902 provide_fn(ompt_get_target_task_data);
903 #undef provide_fn
905 #define ompt_interface_fn(fn, type, code) \
906 if (strcmp(s, #fn) == 0) \
907 return (ompt_interface_fn_t)ompt_callbacks.ompt_callback(fn);
909 FOREACH_OMPT_DEVICE_EVENT(ompt_interface_fn)
910 FOREACH_OMPT_EMI_EVENT(ompt_interface_fn)
911 FOREACH_OMPT_NOEMI_EVENT(ompt_interface_fn)
912 #undef ompt_interface_fn
914 return (ompt_interface_fn_t)0;
917 /// This function is called by the libomptarget connector to assign
918 /// callbacks already registered with libomp.
919 _OMP_EXTERN void ompt_libomp_connect(ompt_start_tool_result_t *result) {
920 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Enter ompt_libomp_connect\n");
922 // Ensure libomp callbacks have been added if not already
923 __ompt_force_initialization();
925 if (ompt_enabled.enabled && result) {
926 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Connecting with libomptarget\n");
927 // Pass in the libomp lookup function so that the already registered
928 // functions can be extracted and assigned to the callbacks in
929 // libomptarget
930 result->initialize(ompt_libomp_target_fn_lookup,
931 /* initial_device_num */ 0, /* tool_data */ nullptr);
932 // Track the object provided by libomptarget so that the finalizer can be
933 // called during OMPT finalization
934 libomptarget_ompt_result = result;
936 OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Exit ompt_libomp_connect\n");