xref: /freebsd/contrib/llvm-project/openmp/runtime/src/ompt-general.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric /*
20b57cec5SDimitry Andric  * ompt-general.cpp -- OMPT implementation of interface functions
30b57cec5SDimitry Andric  */
40b57cec5SDimitry Andric 
50b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
80b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
90b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric /*****************************************************************************
140b57cec5SDimitry Andric  * system include files
150b57cec5SDimitry Andric  ****************************************************************************/
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include <assert.h>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include <stdint.h>
200b57cec5SDimitry Andric #include <stdio.h>
210b57cec5SDimitry Andric #include <stdlib.h>
220b57cec5SDimitry Andric #include <string.h>
230b57cec5SDimitry Andric #if KMP_OS_UNIX
240b57cec5SDimitry Andric #include <dlfcn.h>
250b57cec5SDimitry Andric #endif
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric /*****************************************************************************
280b57cec5SDimitry Andric  * ompt include files
290b57cec5SDimitry Andric  ****************************************************************************/
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #include "ompt-specific.cpp"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric /*****************************************************************************
340b57cec5SDimitry Andric  * macros
350b57cec5SDimitry Andric  ****************************************************************************/
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric #define ompt_get_callback_success 1
380b57cec5SDimitry Andric #define ompt_get_callback_failure 0
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric #define no_tool_present 0
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric #define OMPT_API_ROUTINE static
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric #ifndef OMPT_STR_MATCH
450b57cec5SDimitry Andric #define OMPT_STR_MATCH(haystack, needle) (!strcasecmp(haystack, needle))
460b57cec5SDimitry Andric #endif
470b57cec5SDimitry Andric 
48e8d8bef9SDimitry Andric // prints for an enabled OMP_TOOL_VERBOSE_INIT.
49e8d8bef9SDimitry Andric // In the future a prefix could be added in the first define, the second define
50e8d8bef9SDimitry Andric // omits the prefix to allow for continued lines. Example: "PREFIX: Start
51e8d8bef9SDimitry Andric // tool... Success." instead of "PREFIX: Start tool... PREFIX: Success."
52e8d8bef9SDimitry Andric #define OMPT_VERBOSE_INIT_PRINT(...)                                           \
53e8d8bef9SDimitry Andric   if (verbose_init)                                                            \
54e8d8bef9SDimitry Andric   fprintf(verbose_file, __VA_ARGS__)
55e8d8bef9SDimitry Andric #define OMPT_VERBOSE_INIT_CONTINUED_PRINT(...)                                 \
56e8d8bef9SDimitry Andric   if (verbose_init)                                                            \
57e8d8bef9SDimitry Andric   fprintf(verbose_file, __VA_ARGS__)
58e8d8bef9SDimitry Andric 
59e8d8bef9SDimitry Andric static FILE *verbose_file;
60e8d8bef9SDimitry Andric static int verbose_init;
61e8d8bef9SDimitry Andric 
620b57cec5SDimitry Andric /*****************************************************************************
630b57cec5SDimitry Andric  * types
640b57cec5SDimitry Andric  ****************************************************************************/
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric typedef struct {
670b57cec5SDimitry Andric   const char *state_name;
680b57cec5SDimitry Andric   ompt_state_t state_id;
690b57cec5SDimitry Andric } ompt_state_info_t;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric typedef struct {
720b57cec5SDimitry Andric   const char *name;
730b57cec5SDimitry Andric   kmp_mutex_impl_t id;
740b57cec5SDimitry Andric } kmp_mutex_impl_info_t;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric enum tool_setting_e {
770b57cec5SDimitry Andric   omp_tool_error,
780b57cec5SDimitry Andric   omp_tool_unset,
790b57cec5SDimitry Andric   omp_tool_disabled,
800b57cec5SDimitry Andric   omp_tool_enabled
810b57cec5SDimitry Andric };
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric /*****************************************************************************
840b57cec5SDimitry Andric  * global variables
850b57cec5SDimitry Andric  ****************************************************************************/
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric ompt_callbacks_active_t ompt_enabled;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric ompt_state_info_t ompt_state_info[] = {
900b57cec5SDimitry Andric #define ompt_state_macro(state, code) {#state, state},
910b57cec5SDimitry Andric     FOREACH_OMPT_STATE(ompt_state_macro)
920b57cec5SDimitry Andric #undef ompt_state_macro
930b57cec5SDimitry Andric };
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric kmp_mutex_impl_info_t kmp_mutex_impl_info[] = {
960b57cec5SDimitry Andric #define kmp_mutex_impl_macro(name, id) {#name, name},
970b57cec5SDimitry Andric     FOREACH_KMP_MUTEX_IMPL(kmp_mutex_impl_macro)
980b57cec5SDimitry Andric #undef kmp_mutex_impl_macro
990b57cec5SDimitry Andric };
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric ompt_callbacks_internal_t ompt_callbacks;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric static ompt_start_tool_result_t *ompt_start_tool_result = NULL;
1040b57cec5SDimitry Andric 
105fe6060f1SDimitry Andric #if KMP_OS_WINDOWS
106fe6060f1SDimitry Andric static HMODULE ompt_tool_module = NULL;
107fe6060f1SDimitry Andric #define OMPT_DLCLOSE(Lib) FreeLibrary(Lib)
108fe6060f1SDimitry Andric #else
109fe6060f1SDimitry Andric static void *ompt_tool_module = NULL;
110fe6060f1SDimitry Andric #define OMPT_DLCLOSE(Lib) dlclose(Lib)
111fe6060f1SDimitry Andric #endif
112fe6060f1SDimitry Andric 
113bdd1243dSDimitry Andric /// Used to track the initializer and the finalizer provided by libomptarget
114bdd1243dSDimitry Andric static ompt_start_tool_result_t *libomptarget_ompt_result = NULL;
115bdd1243dSDimitry Andric 
1160b57cec5SDimitry Andric /*****************************************************************************
1170b57cec5SDimitry Andric  * forward declarations
1180b57cec5SDimitry Andric  ****************************************************************************/
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric static ompt_interface_fn_t ompt_fn_lookup(const char *s);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric /*****************************************************************************
1250b57cec5SDimitry Andric  * initialization and finalization (private operations)
1260b57cec5SDimitry Andric  ****************************************************************************/
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric typedef ompt_start_tool_result_t *(*ompt_start_tool_t)(unsigned int,
1290b57cec5SDimitry Andric                                                        const char *);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric #if KMP_OS_DARWIN
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric // While Darwin supports weak symbols, the library that wishes to provide a new
1340b57cec5SDimitry Andric // implementation has to link against this runtime which defeats the purpose
1350b57cec5SDimitry Andric // of having tools that are agnostic of the underlying runtime implementation.
1360b57cec5SDimitry Andric //
1370b57cec5SDimitry Andric // Fortunately, the linker includes all symbols of an executable in the global
1380b57cec5SDimitry Andric // symbol table by default so dlsym() even finds static implementations of
1390b57cec5SDimitry Andric // ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be
1400b57cec5SDimitry Andric // passed when building the application which we don't want to rely on.
1410b57cec5SDimitry Andric 
ompt_tool_darwin(unsigned int omp_version,const char * runtime_version)1420b57cec5SDimitry Andric static ompt_start_tool_result_t *ompt_tool_darwin(unsigned int omp_version,
1430b57cec5SDimitry Andric                                                   const char *runtime_version) {
1440b57cec5SDimitry Andric   ompt_start_tool_result_t *ret = NULL;
1450b57cec5SDimitry Andric   // Search symbol in the current address space.
1460b57cec5SDimitry Andric   ompt_start_tool_t start_tool =
1470b57cec5SDimitry Andric       (ompt_start_tool_t)dlsym(RTLD_DEFAULT, "ompt_start_tool");
1480b57cec5SDimitry Andric   if (start_tool) {
1490b57cec5SDimitry Andric     ret = start_tool(omp_version, runtime_version);
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric   return ret;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric #elif OMPT_HAVE_WEAK_ATTRIBUTE
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric // On Unix-like systems that support weak symbols the following implementation
1570b57cec5SDimitry Andric // of ompt_start_tool() will be used in case no tool-supplied implementation of
1580b57cec5SDimitry Andric // this function is present in the address space of a process.
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric _OMP_EXTERN OMPT_WEAK_ATTRIBUTE ompt_start_tool_result_t *
ompt_start_tool(unsigned int omp_version,const char * runtime_version)1610b57cec5SDimitry Andric ompt_start_tool(unsigned int omp_version, const char *runtime_version) {
1620b57cec5SDimitry Andric   ompt_start_tool_result_t *ret = NULL;
1630b57cec5SDimitry Andric   // Search next symbol in the current address space. This can happen if the
1640b57cec5SDimitry Andric   // runtime library is linked before the tool. Since glibc 2.2 strong symbols
1650b57cec5SDimitry Andric   // don't override weak symbols that have been found before unless the user
1660b57cec5SDimitry Andric   // sets the environment variable LD_DYNAMIC_WEAK.
1670b57cec5SDimitry Andric   ompt_start_tool_t next_tool =
1680b57cec5SDimitry Andric       (ompt_start_tool_t)dlsym(RTLD_NEXT, "ompt_start_tool");
1690b57cec5SDimitry Andric   if (next_tool) {
1700b57cec5SDimitry Andric     ret = next_tool(omp_version, runtime_version);
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric   return ret;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric #elif OMPT_HAVE_PSAPI
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric // On Windows, the ompt_tool_windows function is used to find the
1780b57cec5SDimitry Andric // ompt_start_tool symbol across all modules loaded by a process. If
1790b57cec5SDimitry Andric // ompt_start_tool is found, ompt_start_tool's return value is used to
1800b57cec5SDimitry Andric // initialize the tool. Otherwise, NULL is returned and OMPT won't be enabled.
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric #include <psapi.h>
1830b57cec5SDimitry Andric #pragma comment(lib, "psapi.lib")
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric // The number of loaded modules to start enumeration with EnumProcessModules()
1860b57cec5SDimitry Andric #define NUM_MODULES 128
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric static ompt_start_tool_result_t *
ompt_tool_windows(unsigned int omp_version,const char * runtime_version)1890b57cec5SDimitry Andric ompt_tool_windows(unsigned int omp_version, const char *runtime_version) {
1900b57cec5SDimitry Andric   int i;
1910b57cec5SDimitry Andric   DWORD needed, new_size;
1920b57cec5SDimitry Andric   HMODULE *modules;
1930b57cec5SDimitry Andric   HANDLE process = GetCurrentProcess();
1940b57cec5SDimitry Andric   modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE));
1950b57cec5SDimitry Andric   ompt_start_tool_t ompt_tool_p = NULL;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric #if OMPT_DEBUG
1980b57cec5SDimitry Andric   printf("ompt_tool_windows(): looking for ompt_start_tool\n");
1990b57cec5SDimitry Andric #endif
2000b57cec5SDimitry Andric   if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE),
2010b57cec5SDimitry Andric                           &needed)) {
2020b57cec5SDimitry Andric     // Regardless of the error reason use the stub initialization function
2030b57cec5SDimitry Andric     free(modules);
2040b57cec5SDimitry Andric     return NULL;
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric   // Check if NUM_MODULES is enough to list all modules
2070b57cec5SDimitry Andric   new_size = needed / sizeof(HMODULE);
2080b57cec5SDimitry Andric   if (new_size > NUM_MODULES) {
2090b57cec5SDimitry Andric #if OMPT_DEBUG
2100b57cec5SDimitry Andric     printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed);
2110b57cec5SDimitry Andric #endif
2120b57cec5SDimitry Andric     modules = (HMODULE *)realloc(modules, needed);
2130b57cec5SDimitry Andric     // If resizing failed use the stub function.
2140b57cec5SDimitry Andric     if (!EnumProcessModules(process, modules, needed, &needed)) {
2150b57cec5SDimitry Andric       free(modules);
2160b57cec5SDimitry Andric       return NULL;
2170b57cec5SDimitry Andric     }
2180b57cec5SDimitry Andric   }
2190b57cec5SDimitry Andric   for (i = 0; i < new_size; ++i) {
2200b57cec5SDimitry Andric     (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_start_tool");
2210b57cec5SDimitry Andric     if (ompt_tool_p) {
2220b57cec5SDimitry Andric #if OMPT_DEBUG
2230b57cec5SDimitry Andric       TCHAR modName[MAX_PATH];
2240b57cec5SDimitry Andric       if (GetModuleFileName(modules[i], modName, MAX_PATH))
2250b57cec5SDimitry Andric         printf("ompt_tool_windows(): ompt_start_tool found in module %s\n",
2260b57cec5SDimitry Andric                modName);
2270b57cec5SDimitry Andric #endif
2280b57cec5SDimitry Andric       free(modules);
2290b57cec5SDimitry Andric       return (*ompt_tool_p)(omp_version, runtime_version);
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric #if OMPT_DEBUG
2320b57cec5SDimitry Andric     else {
2330b57cec5SDimitry Andric       TCHAR modName[MAX_PATH];
2340b57cec5SDimitry Andric       if (GetModuleFileName(modules[i], modName, MAX_PATH))
2350b57cec5SDimitry Andric         printf("ompt_tool_windows(): ompt_start_tool not found in module %s\n",
2360b57cec5SDimitry Andric                modName);
2370b57cec5SDimitry Andric     }
2380b57cec5SDimitry Andric #endif
2390b57cec5SDimitry Andric   }
2400b57cec5SDimitry Andric   free(modules);
2410b57cec5SDimitry Andric   return NULL;
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric #else
2440b57cec5SDimitry Andric #error Activation of OMPT is not supported on this platform.
2450b57cec5SDimitry Andric #endif
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric static ompt_start_tool_result_t *
ompt_try_start_tool(unsigned int omp_version,const char * runtime_version)2480b57cec5SDimitry Andric ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) {
2490b57cec5SDimitry Andric   ompt_start_tool_result_t *ret = NULL;
2500b57cec5SDimitry Andric   ompt_start_tool_t start_tool = NULL;
2510b57cec5SDimitry Andric #if KMP_OS_WINDOWS
2520b57cec5SDimitry Andric   // Cannot use colon to describe a list of absolute paths on Windows
2530b57cec5SDimitry Andric   const char *sep = ";";
2540b57cec5SDimitry Andric #else
2550b57cec5SDimitry Andric   const char *sep = ":";
2560b57cec5SDimitry Andric #endif
2570b57cec5SDimitry Andric 
258e8d8bef9SDimitry Andric   OMPT_VERBOSE_INIT_PRINT("----- START LOGGING OF TOOL REGISTRATION -----\n");
259e8d8bef9SDimitry Andric   OMPT_VERBOSE_INIT_PRINT("Search for OMP tool in current address space... ");
260e8d8bef9SDimitry Andric 
2610b57cec5SDimitry Andric #if KMP_OS_DARWIN
2620b57cec5SDimitry Andric   // Try in the current address space
2630b57cec5SDimitry Andric   ret = ompt_tool_darwin(omp_version, runtime_version);
2640b57cec5SDimitry Andric #elif OMPT_HAVE_WEAK_ATTRIBUTE
2650b57cec5SDimitry Andric   ret = ompt_start_tool(omp_version, runtime_version);
2660b57cec5SDimitry Andric #elif OMPT_HAVE_PSAPI
2670b57cec5SDimitry Andric   ret = ompt_tool_windows(omp_version, runtime_version);
2680b57cec5SDimitry Andric #else
2690b57cec5SDimitry Andric #error Activation of OMPT is not supported on this platform.
2700b57cec5SDimitry Andric #endif
271e8d8bef9SDimitry Andric   if (ret) {
272fe6060f1SDimitry Andric     OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
273e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT(
274e8d8bef9SDimitry Andric         "Tool was started and is using the OMPT interface.\n");
275e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");
2760b57cec5SDimitry Andric     return ret;
277e8d8bef9SDimitry Andric   }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // Try tool-libraries-var ICV
280e8d8bef9SDimitry Andric   OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed.\n");
2810b57cec5SDimitry Andric   const char *tool_libs = getenv("OMP_TOOL_LIBRARIES");
2820b57cec5SDimitry Andric   if (tool_libs) {
283e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("Searching tool libraries...\n");
284e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("OMP_TOOL_LIBRARIES = %s\n", tool_libs);
2850b57cec5SDimitry Andric     char *libs = __kmp_str_format("%s", tool_libs);
2860b57cec5SDimitry Andric     char *buf;
2870b57cec5SDimitry Andric     char *fname = __kmp_str_token(libs, sep, &buf);
288e8d8bef9SDimitry Andric     // Reset dl-error
289e8d8bef9SDimitry Andric     dlerror();
290e8d8bef9SDimitry Andric 
2910b57cec5SDimitry Andric     while (fname) {
2920b57cec5SDimitry Andric #if KMP_OS_UNIX
293e8d8bef9SDimitry Andric       OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);
2940b57cec5SDimitry Andric       void *h = dlopen(fname, RTLD_LAZY);
295e8d8bef9SDimitry Andric       if (!h) {
296e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror());
297e8d8bef9SDimitry Andric       } else {
298e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n");
299e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ",
300e8d8bef9SDimitry Andric                                 fname);
301349cc55cSDimitry Andric         dlerror(); // Clear any existing error
3020b57cec5SDimitry Andric         start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");
303e8d8bef9SDimitry Andric         if (!start_tool) {
304349cc55cSDimitry Andric           char *error = dlerror();
305349cc55cSDimitry Andric           if (error != NULL) {
306349cc55cSDimitry Andric             OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", error);
307349cc55cSDimitry Andric           } else {
308349cc55cSDimitry Andric             OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n",
309349cc55cSDimitry Andric                                               "ompt_start_tool = NULL");
310349cc55cSDimitry Andric           }
311e8d8bef9SDimitry Andric         } else
3120b57cec5SDimitry Andric #elif KMP_OS_WINDOWS
313e8d8bef9SDimitry Andric       OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);
3140b57cec5SDimitry Andric       HMODULE h = LoadLibrary(fname);
315e8d8bef9SDimitry Andric       if (!h) {
31681ad6265SDimitry Andric         OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n",
31781ad6265SDimitry Andric                                           (unsigned)GetLastError());
318e8d8bef9SDimitry Andric       } else {
319e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success. \n");
320e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ",
321e8d8bef9SDimitry Andric                                 fname);
3220b57cec5SDimitry Andric         start_tool = (ompt_start_tool_t)GetProcAddress(h, "ompt_start_tool");
323e8d8bef9SDimitry Andric         if (!start_tool) {
324fe6060f1SDimitry Andric           OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: Error %u\n",
32581ad6265SDimitry Andric                                             (unsigned)GetLastError());
326e8d8bef9SDimitry Andric         } else
3270b57cec5SDimitry Andric #else
3280b57cec5SDimitry Andric #error Activation of OMPT is not supported on this platform.
3290b57cec5SDimitry Andric #endif
330e8d8bef9SDimitry Andric         { // if (start_tool)
331e8d8bef9SDimitry Andric           ret = (*start_tool)(omp_version, runtime_version);
332e8d8bef9SDimitry Andric           if (ret) {
333e8d8bef9SDimitry Andric             OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
334e8d8bef9SDimitry Andric             OMPT_VERBOSE_INIT_PRINT(
335e8d8bef9SDimitry Andric                 "Tool was started and is using the OMPT interface.\n");
336fe6060f1SDimitry Andric             ompt_tool_module = h;
3370b57cec5SDimitry Andric             break;
3380b57cec5SDimitry Andric           }
339e8d8bef9SDimitry Andric           OMPT_VERBOSE_INIT_CONTINUED_PRINT(
340e8d8bef9SDimitry Andric               "Found but not using the OMPT interface.\n");
341e8d8bef9SDimitry Andric           OMPT_VERBOSE_INIT_PRINT("Continuing search...\n");
342e8d8bef9SDimitry Andric         }
343fe6060f1SDimitry Andric         OMPT_DLCLOSE(h);
344e8d8bef9SDimitry Andric       }
3450b57cec5SDimitry Andric       fname = __kmp_str_token(NULL, sep, &buf);
3460b57cec5SDimitry Andric     }
3470b57cec5SDimitry Andric     __kmp_str_free(&libs);
348e8d8bef9SDimitry Andric   } else {
349e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("No OMP_TOOL_LIBRARIES defined.\n");
3500b57cec5SDimitry Andric   }
351e8d8bef9SDimitry Andric 
352e8d8bef9SDimitry Andric   // usable tool found in tool-libraries
353e8d8bef9SDimitry Andric   if (ret) {
354e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");
355480093f4SDimitry Andric     return ret;
356e8d8bef9SDimitry Andric   }
357480093f4SDimitry Andric 
358480093f4SDimitry Andric #if KMP_OS_UNIX
359480093f4SDimitry Andric   { // Non-standard: load archer tool if application is built with TSan
360480093f4SDimitry Andric     const char *fname = "libarcher.so";
361e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT(
362e8d8bef9SDimitry Andric         "...searching tool libraries failed. Using archer tool.\n");
363e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("Opening %s... ", fname);
364480093f4SDimitry Andric     void *h = dlopen(fname, RTLD_LAZY);
365480093f4SDimitry Andric     if (h) {
366e8d8bef9SDimitry Andric       OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
367e8d8bef9SDimitry Andric       OMPT_VERBOSE_INIT_PRINT("Searching for ompt_start_tool in %s... ", fname);
368480093f4SDimitry Andric       start_tool = (ompt_start_tool_t)dlsym(h, "ompt_start_tool");
369e8d8bef9SDimitry Andric       if (start_tool) {
370480093f4SDimitry Andric         ret = (*start_tool)(omp_version, runtime_version);
371e8d8bef9SDimitry Andric         if (ret) {
372e8d8bef9SDimitry Andric           OMPT_VERBOSE_INIT_CONTINUED_PRINT("Success.\n");
373e8d8bef9SDimitry Andric           OMPT_VERBOSE_INIT_PRINT(
374e8d8bef9SDimitry Andric               "Tool was started and is using the OMPT interface.\n");
375e8d8bef9SDimitry Andric           OMPT_VERBOSE_INIT_PRINT(
376e8d8bef9SDimitry Andric               "----- END LOGGING OF TOOL REGISTRATION -----\n");
377480093f4SDimitry Andric           return ret;
378480093f4SDimitry Andric         }
379e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_CONTINUED_PRINT(
380e8d8bef9SDimitry Andric             "Found but not using the OMPT interface.\n");
381e8d8bef9SDimitry Andric       } else {
382e8d8bef9SDimitry Andric         OMPT_VERBOSE_INIT_CONTINUED_PRINT("Failed: %s\n", dlerror());
383e8d8bef9SDimitry Andric       }
384e8d8bef9SDimitry Andric     }
385480093f4SDimitry Andric   }
386480093f4SDimitry Andric #endif
387e8d8bef9SDimitry Andric   OMPT_VERBOSE_INIT_PRINT("No OMP tool loaded.\n");
388e8d8bef9SDimitry Andric   OMPT_VERBOSE_INIT_PRINT("----- END LOGGING OF TOOL REGISTRATION -----\n");
3890b57cec5SDimitry Andric   return ret;
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric void ompt_pre_init() {
3930b57cec5SDimitry Andric   //--------------------------------------------------
3940b57cec5SDimitry Andric   // Execute the pre-initialization logic only once.
3950b57cec5SDimitry Andric   //--------------------------------------------------
3960b57cec5SDimitry Andric   static int ompt_pre_initialized = 0;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   if (ompt_pre_initialized)
3990b57cec5SDimitry Andric     return;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   ompt_pre_initialized = 1;
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   //--------------------------------------------------
4040b57cec5SDimitry Andric   // Use a tool iff a tool is enabled and available.
4050b57cec5SDimitry Andric   //--------------------------------------------------
4060b57cec5SDimitry Andric   const char *ompt_env_var = getenv("OMP_TOOL");
4070b57cec5SDimitry Andric   tool_setting_e tool_setting = omp_tool_error;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   if (!ompt_env_var || !strcmp(ompt_env_var, ""))
4100b57cec5SDimitry Andric     tool_setting = omp_tool_unset;
4110b57cec5SDimitry Andric   else if (OMPT_STR_MATCH(ompt_env_var, "disabled"))
4120b57cec5SDimitry Andric     tool_setting = omp_tool_disabled;
4130b57cec5SDimitry Andric   else if (OMPT_STR_MATCH(ompt_env_var, "enabled"))
4140b57cec5SDimitry Andric     tool_setting = omp_tool_enabled;
4150b57cec5SDimitry Andric 
416e8d8bef9SDimitry Andric   const char *ompt_env_verbose_init = getenv("OMP_TOOL_VERBOSE_INIT");
417e8d8bef9SDimitry Andric   // possible options: disabled | stdout | stderr | <filename>
418e8d8bef9SDimitry Andric   // if set, not empty and not disabled -> prepare for logging
419e8d8bef9SDimitry Andric   if (ompt_env_verbose_init && strcmp(ompt_env_verbose_init, "") &&
420e8d8bef9SDimitry Andric       !OMPT_STR_MATCH(ompt_env_verbose_init, "disabled")) {
421e8d8bef9SDimitry Andric     verbose_init = 1;
422e8d8bef9SDimitry Andric     if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDERR"))
423e8d8bef9SDimitry Andric       verbose_file = stderr;
424e8d8bef9SDimitry Andric     else if (OMPT_STR_MATCH(ompt_env_verbose_init, "STDOUT"))
425e8d8bef9SDimitry Andric       verbose_file = stdout;
426e8d8bef9SDimitry Andric     else
427e8d8bef9SDimitry Andric       verbose_file = fopen(ompt_env_verbose_init, "w");
428e8d8bef9SDimitry Andric   } else
429e8d8bef9SDimitry Andric     verbose_init = 0;
430e8d8bef9SDimitry Andric 
4310b57cec5SDimitry Andric #if OMPT_DEBUG
4320b57cec5SDimitry Andric   printf("ompt_pre_init(): tool_setting = %d\n", tool_setting);
4330b57cec5SDimitry Andric #endif
4340b57cec5SDimitry Andric   switch (tool_setting) {
4350b57cec5SDimitry Andric   case omp_tool_disabled:
436e8d8bef9SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("OMP tool disabled. \n");
4370b57cec5SDimitry Andric     break;
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   case omp_tool_unset:
4400b57cec5SDimitry Andric   case omp_tool_enabled:
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric     //--------------------------------------------------
4430b57cec5SDimitry Andric     // Load tool iff specified in environment variable
4440b57cec5SDimitry Andric     //--------------------------------------------------
4450b57cec5SDimitry Andric     ompt_start_tool_result =
4460b57cec5SDimitry Andric         ompt_try_start_tool(__kmp_openmp_version, ompt_get_runtime_version());
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric     memset(&ompt_enabled, 0, sizeof(ompt_enabled));
4490b57cec5SDimitry Andric     break;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   case omp_tool_error:
452fe6060f1SDimitry Andric     fprintf(stderr,
453fe6060f1SDimitry Andric             "Warning: OMP_TOOL has invalid value \"%s\".\n"
4540b57cec5SDimitry Andric             "  legal values are (NULL,\"\",\"disabled\","
4550b57cec5SDimitry Andric             "\"enabled\").\n",
4560b57cec5SDimitry Andric             ompt_env_var);
4570b57cec5SDimitry Andric     break;
4580b57cec5SDimitry Andric   }
459e8d8bef9SDimitry Andric   if (verbose_init && verbose_file != stderr && verbose_file != stdout)
460e8d8bef9SDimitry Andric     fclose(verbose_file);
4610b57cec5SDimitry Andric #if OMPT_DEBUG
462bdd1243dSDimitry Andric   printf("ompt_pre_init(): ompt_enabled = %d\n", ompt_enabled.enabled);
4630b57cec5SDimitry Andric #endif
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric extern "C" int omp_get_initial_device(void);
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric void ompt_post_init() {
4690b57cec5SDimitry Andric   //--------------------------------------------------
4700b57cec5SDimitry Andric   // Execute the post-initialization logic only once.
4710b57cec5SDimitry Andric   //--------------------------------------------------
4720b57cec5SDimitry Andric   static int ompt_post_initialized = 0;
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   if (ompt_post_initialized)
4750b57cec5SDimitry Andric     return;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   ompt_post_initialized = 1;
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   //--------------------------------------------------
4800b57cec5SDimitry Andric   // Initialize the tool if so indicated.
4810b57cec5SDimitry Andric   //--------------------------------------------------
4820b57cec5SDimitry Andric   if (ompt_start_tool_result) {
4830b57cec5SDimitry Andric     ompt_enabled.enabled = !!ompt_start_tool_result->initialize(
484fe6060f1SDimitry Andric         ompt_fn_lookup, omp_get_initial_device(),
485fe6060f1SDimitry Andric         &(ompt_start_tool_result->tool_data));
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric     if (!ompt_enabled.enabled) {
4880b57cec5SDimitry Andric       // tool not enabled, zero out the bitmap, and done
4890b57cec5SDimitry Andric       memset(&ompt_enabled, 0, sizeof(ompt_enabled));
4900b57cec5SDimitry Andric       return;
4910b57cec5SDimitry Andric     }
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric     kmp_info_t *root_thread = ompt_get_thread();
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric     ompt_set_thread_state(root_thread, ompt_state_overhead);
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_thread_begin) {
4980b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_thread_begin)(
4990b57cec5SDimitry Andric           ompt_thread_initial, __ompt_get_thread_data_internal());
5000b57cec5SDimitry Andric     }
50106c3fb27SDimitry Andric     ompt_data_t *task_data = nullptr;
50206c3fb27SDimitry Andric     ompt_data_t *parallel_data = nullptr;
503fe6060f1SDimitry Andric     __ompt_get_task_info_internal(0, NULL, &task_data, NULL, &parallel_data,
504fe6060f1SDimitry Andric                                   NULL);
5050b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_implicit_task) {
5060b57cec5SDimitry Andric       ompt_callbacks.ompt_callback(ompt_callback_implicit_task)(
5070b57cec5SDimitry Andric           ompt_scope_begin, parallel_data, task_data, 1, 1, ompt_task_initial);
5080b57cec5SDimitry Andric     }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric     ompt_set_thread_state(root_thread, ompt_state_work_serial);
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric }
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric void ompt_fini() {
515bdd1243dSDimitry Andric   if (ompt_enabled.enabled) {
516bdd1243dSDimitry Andric     if (ompt_start_tool_result && ompt_start_tool_result->finalize) {
5170b57cec5SDimitry Andric       ompt_start_tool_result->finalize(&(ompt_start_tool_result->tool_data));
5180b57cec5SDimitry Andric     }
519bdd1243dSDimitry Andric     if (libomptarget_ompt_result && libomptarget_ompt_result->finalize) {
520bdd1243dSDimitry Andric       libomptarget_ompt_result->finalize(NULL);
521bdd1243dSDimitry Andric     }
522bdd1243dSDimitry Andric   }
5230b57cec5SDimitry Andric 
524fe6060f1SDimitry Andric   if (ompt_tool_module)
525fe6060f1SDimitry Andric     OMPT_DLCLOSE(ompt_tool_module);
5260b57cec5SDimitry Andric   memset(&ompt_enabled, 0, sizeof(ompt_enabled));
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric /*****************************************************************************
5300b57cec5SDimitry Andric  * interface operations
5310b57cec5SDimitry Andric  ****************************************************************************/
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric /*****************************************************************************
5340b57cec5SDimitry Andric  * state
5350b57cec5SDimitry Andric  ****************************************************************************/
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state,
5380b57cec5SDimitry Andric                                            const char **next_state_name) {
5390b57cec5SDimitry Andric   const static int len = sizeof(ompt_state_info) / sizeof(ompt_state_info_t);
5400b57cec5SDimitry Andric   int i = 0;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   for (i = 0; i < len - 1; i++) {
5430b57cec5SDimitry Andric     if (ompt_state_info[i].state_id == current_state) {
5440b57cec5SDimitry Andric       *next_state = ompt_state_info[i + 1].state_id;
5450b57cec5SDimitry Andric       *next_state_name = ompt_state_info[i + 1].state_name;
5460b57cec5SDimitry Andric       return 1;
5470b57cec5SDimitry Andric     }
5480b57cec5SDimitry Andric   }
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   return 0;
5510b57cec5SDimitry Andric }
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl,
5540b57cec5SDimitry Andric                                                 int *next_impl,
5550b57cec5SDimitry Andric                                                 const char **next_impl_name) {
5560b57cec5SDimitry Andric   const static int len =
5570b57cec5SDimitry Andric       sizeof(kmp_mutex_impl_info) / sizeof(kmp_mutex_impl_info_t);
5580b57cec5SDimitry Andric   int i = 0;
5590b57cec5SDimitry Andric   for (i = 0; i < len - 1; i++) {
5600b57cec5SDimitry Andric     if (kmp_mutex_impl_info[i].id != current_impl)
5610b57cec5SDimitry Andric       continue;
5620b57cec5SDimitry Andric     *next_impl = kmp_mutex_impl_info[i + 1].id;
5630b57cec5SDimitry Andric     *next_impl_name = kmp_mutex_impl_info[i + 1].name;
5640b57cec5SDimitry Andric     return 1;
5650b57cec5SDimitry Andric   }
5660b57cec5SDimitry Andric   return 0;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric /*****************************************************************************
5700b57cec5SDimitry Andric  * callbacks
5710b57cec5SDimitry Andric  ****************************************************************************/
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which,
5740b57cec5SDimitry Andric                                                      ompt_callback_t callback) {
5750b57cec5SDimitry Andric   switch (which) {
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric #define ompt_event_macro(event_name, callback_type, event_id)                  \
5780b57cec5SDimitry Andric   case event_name:                                                             \
5790b57cec5SDimitry Andric     ompt_callbacks.ompt_callback(event_name) = (callback_type)callback;        \
5800b57cec5SDimitry Andric     ompt_enabled.event_name = (callback != 0);                                 \
5810b57cec5SDimitry Andric     if (callback)                                                              \
5820b57cec5SDimitry Andric       return ompt_event_implementation_status(event_name);                     \
5830b57cec5SDimitry Andric     else                                                                       \
5840b57cec5SDimitry Andric       return ompt_set_always;
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric     FOREACH_OMPT_EVENT(ompt_event_macro)
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric #undef ompt_event_macro
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   default:
5910b57cec5SDimitry Andric     return ompt_set_error;
5920b57cec5SDimitry Andric   }
5930b57cec5SDimitry Andric }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which,
5960b57cec5SDimitry Andric                                        ompt_callback_t *callback) {
5970b57cec5SDimitry Andric   if (!ompt_enabled.enabled)
5980b57cec5SDimitry Andric     return ompt_get_callback_failure;
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   switch (which) {
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric #define ompt_event_macro(event_name, callback_type, event_id)                  \
603489b1cf2SDimitry Andric   case event_name: {                                                           \
6040b57cec5SDimitry Andric     ompt_callback_t mycb =                                                     \
6050b57cec5SDimitry Andric         (ompt_callback_t)ompt_callbacks.ompt_callback(event_name);             \
6060b57cec5SDimitry Andric     if (ompt_enabled.event_name && mycb) {                                     \
6070b57cec5SDimitry Andric       *callback = mycb;                                                        \
6080b57cec5SDimitry Andric       return ompt_get_callback_success;                                        \
6090b57cec5SDimitry Andric     }                                                                          \
610489b1cf2SDimitry Andric     return ompt_get_callback_failure;                                          \
611489b1cf2SDimitry Andric   }
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric     FOREACH_OMPT_EVENT(ompt_event_macro)
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric #undef ompt_event_macro
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   default:
6180b57cec5SDimitry Andric     return ompt_get_callback_failure;
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric /*****************************************************************************
6230b57cec5SDimitry Andric  * parallel regions
6240b57cec5SDimitry Andric  ****************************************************************************/
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level,
6270b57cec5SDimitry Andric                                             ompt_data_t **parallel_data,
6280b57cec5SDimitry Andric                                             int *team_size) {
6290b57cec5SDimitry Andric   if (!ompt_enabled.enabled)
6300b57cec5SDimitry Andric     return 0;
6310b57cec5SDimitry Andric   return __ompt_get_parallel_info_internal(ancestor_level, parallel_data,
6320b57cec5SDimitry Andric                                            team_size);
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) {
6360b57cec5SDimitry Andric   if (!ompt_enabled.enabled)
6370b57cec5SDimitry Andric     return ompt_state_work_serial;
6380b57cec5SDimitry Andric   int thread_state = __ompt_get_state_internal(wait_id);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   if (thread_state == ompt_state_undefined) {
6410b57cec5SDimitry Andric     thread_state = ompt_state_work_serial;
6420b57cec5SDimitry Andric   }
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   return thread_state;
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric /*****************************************************************************
6480b57cec5SDimitry Andric  * tasks
6490b57cec5SDimitry Andric  ****************************************************************************/
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) {
6520b57cec5SDimitry Andric   if (!ompt_enabled.enabled)
6530b57cec5SDimitry Andric     return NULL;
6540b57cec5SDimitry Andric   return __ompt_get_thread_data_internal();
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type,
6580b57cec5SDimitry Andric                                         ompt_data_t **task_data,
6590b57cec5SDimitry Andric                                         ompt_frame_t **task_frame,
6600b57cec5SDimitry Andric                                         ompt_data_t **parallel_data,
6610b57cec5SDimitry Andric                                         int *thread_num) {
6620b57cec5SDimitry Andric   if (!ompt_enabled.enabled)
6630b57cec5SDimitry Andric     return 0;
6640b57cec5SDimitry Andric   return __ompt_get_task_info_internal(ancestor_level, type, task_data,
6650b57cec5SDimitry Andric                                        task_frame, parallel_data, thread_num);
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size,
6690b57cec5SDimitry Andric                                           int block) {
6700b57cec5SDimitry Andric   return __ompt_get_task_memory_internal(addr, size, block);
6710b57cec5SDimitry Andric }
6720b57cec5SDimitry Andric 
6730b57cec5SDimitry Andric /*****************************************************************************
6740b57cec5SDimitry Andric  * num_procs
6750b57cec5SDimitry Andric  ****************************************************************************/
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_num_procs(void) {
6780b57cec5SDimitry Andric   // copied from kmp_ftn_entry.h (but modified: OMPT can only be called when
6790b57cec5SDimitry Andric   // runtime is initialized)
6800b57cec5SDimitry Andric   return __kmp_avail_proc;
6810b57cec5SDimitry Andric }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric /*****************************************************************************
6840b57cec5SDimitry Andric  * places
6850b57cec5SDimitry Andric  ****************************************************************************/
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_num_places(void) {
6880b57cec5SDimitry Andric // copied from kmp_ftn_entry.h (but modified)
6890b57cec5SDimitry Andric #if !KMP_AFFINITY_SUPPORTED
6900b57cec5SDimitry Andric   return 0;
6910b57cec5SDimitry Andric #else
6920b57cec5SDimitry Andric   if (!KMP_AFFINITY_CAPABLE())
6930b57cec5SDimitry Andric     return 0;
694bdd1243dSDimitry Andric   return __kmp_affinity.num_masks;
6950b57cec5SDimitry Andric #endif
6960b57cec5SDimitry Andric }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size,
6990b57cec5SDimitry Andric                                              int *ids) {
7000b57cec5SDimitry Andric // copied from kmp_ftn_entry.h (but modified)
7010b57cec5SDimitry Andric #if !KMP_AFFINITY_SUPPORTED
7020b57cec5SDimitry Andric   return 0;
7030b57cec5SDimitry Andric #else
7040b57cec5SDimitry Andric   int i, count;
7050b57cec5SDimitry Andric   int tmp_ids[ids_size];
706fe6060f1SDimitry Andric   for (int j = 0; j < ids_size; j++)
707fe6060f1SDimitry Andric     tmp_ids[j] = 0;
7080b57cec5SDimitry Andric   if (!KMP_AFFINITY_CAPABLE())
7090b57cec5SDimitry Andric     return 0;
710bdd1243dSDimitry Andric   if (place_num < 0 || place_num >= (int)__kmp_affinity.num_masks)
7110b57cec5SDimitry Andric     return 0;
7120b57cec5SDimitry Andric   /* TODO: Is this safe for asynchronous call from signal handler during runtime
7130b57cec5SDimitry Andric    * shutdown? */
714bdd1243dSDimitry Andric   kmp_affin_mask_t *mask = KMP_CPU_INDEX(__kmp_affinity.masks, place_num);
7150b57cec5SDimitry Andric   count = 0;
7160b57cec5SDimitry Andric   KMP_CPU_SET_ITERATE(i, mask) {
7170b57cec5SDimitry Andric     if ((!KMP_CPU_ISSET(i, __kmp_affin_fullMask)) ||
7180b57cec5SDimitry Andric         (!KMP_CPU_ISSET(i, mask))) {
7190b57cec5SDimitry Andric       continue;
7200b57cec5SDimitry Andric     }
7210b57cec5SDimitry Andric     if (count < ids_size)
7220b57cec5SDimitry Andric       tmp_ids[count] = i;
7230b57cec5SDimitry Andric     count++;
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric   if (ids_size >= count) {
7260b57cec5SDimitry Andric     for (i = 0; i < count; i++) {
7270b57cec5SDimitry Andric       ids[i] = tmp_ids[i];
7280b57cec5SDimitry Andric     }
7290b57cec5SDimitry Andric   }
7300b57cec5SDimitry Andric   return count;
7310b57cec5SDimitry Andric #endif
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_place_num(void) {
7350b57cec5SDimitry Andric // copied from kmp_ftn_entry.h (but modified)
7360b57cec5SDimitry Andric #if !KMP_AFFINITY_SUPPORTED
7370b57cec5SDimitry Andric   return -1;
7380b57cec5SDimitry Andric #else
7390b57cec5SDimitry Andric   if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
7400b57cec5SDimitry Andric     return -1;
7410b57cec5SDimitry Andric 
7420b57cec5SDimitry Andric   int gtid;
7430b57cec5SDimitry Andric   kmp_info_t *thread;
7440b57cec5SDimitry Andric   if (!KMP_AFFINITY_CAPABLE())
7450b57cec5SDimitry Andric     return -1;
7460b57cec5SDimitry Andric   gtid = __kmp_entry_gtid();
7470b57cec5SDimitry Andric   thread = __kmp_thread_from_gtid(gtid);
7480b57cec5SDimitry Andric   if (thread == NULL || thread->th.th_current_place < 0)
7490b57cec5SDimitry Andric     return -1;
7500b57cec5SDimitry Andric   return thread->th.th_current_place;
7510b57cec5SDimitry Andric #endif
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size,
7550b57cec5SDimitry Andric                                                    int *place_nums) {
7560b57cec5SDimitry Andric // copied from kmp_ftn_entry.h (but modified)
7570b57cec5SDimitry Andric #if !KMP_AFFINITY_SUPPORTED
7580b57cec5SDimitry Andric   return 0;
7590b57cec5SDimitry Andric #else
7600b57cec5SDimitry Andric   if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
7610b57cec5SDimitry Andric     return 0;
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   int i, gtid, place_num, first_place, last_place, start, end;
7640b57cec5SDimitry Andric   kmp_info_t *thread;
7650b57cec5SDimitry Andric   if (!KMP_AFFINITY_CAPABLE())
7660b57cec5SDimitry Andric     return 0;
7670b57cec5SDimitry Andric   gtid = __kmp_entry_gtid();
7680b57cec5SDimitry Andric   thread = __kmp_thread_from_gtid(gtid);
7690b57cec5SDimitry Andric   if (thread == NULL)
7700b57cec5SDimitry Andric     return 0;
7710b57cec5SDimitry Andric   first_place = thread->th.th_first_place;
7720b57cec5SDimitry Andric   last_place = thread->th.th_last_place;
7730b57cec5SDimitry Andric   if (first_place < 0 || last_place < 0)
7740b57cec5SDimitry Andric     return 0;
7750b57cec5SDimitry Andric   if (first_place <= last_place) {
7760b57cec5SDimitry Andric     start = first_place;
7770b57cec5SDimitry Andric     end = last_place;
7780b57cec5SDimitry Andric   } else {
7790b57cec5SDimitry Andric     start = last_place;
7800b57cec5SDimitry Andric     end = first_place;
7810b57cec5SDimitry Andric   }
7820b57cec5SDimitry Andric   if (end - start <= place_nums_size)
7830b57cec5SDimitry Andric     for (i = 0, place_num = start; place_num <= end; ++place_num, ++i) {
7840b57cec5SDimitry Andric       place_nums[i] = place_num;
7850b57cec5SDimitry Andric     }
7860b57cec5SDimitry Andric   return end - start + 1;
7870b57cec5SDimitry Andric #endif
7880b57cec5SDimitry Andric }
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric /*****************************************************************************
7910b57cec5SDimitry Andric  * places
7920b57cec5SDimitry Andric  ****************************************************************************/
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_proc_id(void) {
7950b57cec5SDimitry Andric   if (!ompt_enabled.enabled || __kmp_get_gtid() < 0)
7960b57cec5SDimitry Andric     return -1;
79781ad6265SDimitry Andric #if KMP_HAVE_SCHED_GETCPU
7980b57cec5SDimitry Andric   return sched_getcpu();
7990b57cec5SDimitry Andric #elif KMP_OS_WINDOWS
8000b57cec5SDimitry Andric   PROCESSOR_NUMBER pn;
8010b57cec5SDimitry Andric   GetCurrentProcessorNumberEx(&pn);
8020b57cec5SDimitry Andric   return 64 * pn.Group + pn.Number;
8030b57cec5SDimitry Andric #else
8040b57cec5SDimitry Andric   return -1;
8050b57cec5SDimitry Andric #endif
8060b57cec5SDimitry Andric }
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric /*****************************************************************************
8090b57cec5SDimitry Andric  * compatability
8100b57cec5SDimitry Andric  ****************************************************************************/
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric /*
8130b57cec5SDimitry Andric  * Currently unused function
8140b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; }
8150b57cec5SDimitry Andric */
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric /*****************************************************************************
8180b57cec5SDimitry Andric  * application-facing API
8190b57cec5SDimitry Andric  ****************************************************************************/
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric /*----------------------------------------------------------------------------
8220b57cec5SDimitry Andric  | control
8230b57cec5SDimitry Andric  ---------------------------------------------------------------------------*/
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) {
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   if (ompt_enabled.enabled) {
8280b57cec5SDimitry Andric     if (ompt_enabled.ompt_callback_control_tool) {
8290b57cec5SDimitry Andric       return ompt_callbacks.ompt_callback(ompt_callback_control_tool)(
8300b57cec5SDimitry Andric           command, modifier, arg, OMPT_LOAD_RETURN_ADDRESS(__kmp_entry_gtid()));
8310b57cec5SDimitry Andric     } else {
8320b57cec5SDimitry Andric       return -1;
8330b57cec5SDimitry Andric     }
8340b57cec5SDimitry Andric   } else {
8350b57cec5SDimitry Andric     return -2;
8360b57cec5SDimitry Andric   }
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric /*****************************************************************************
8400b57cec5SDimitry Andric  * misc
8410b57cec5SDimitry Andric  ****************************************************************************/
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) {
8440b57cec5SDimitry Andric   return __ompt_get_unique_id_internal();
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric OMPT_API_ROUTINE void ompt_finalize_tool(void) { __kmp_internal_end_atexit(); }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric /*****************************************************************************
8500b57cec5SDimitry Andric  * Target
8510b57cec5SDimitry Andric  ****************************************************************************/
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num,
8540b57cec5SDimitry Andric                                           ompt_id_t *target_id,
8550b57cec5SDimitry Andric                                           ompt_id_t *host_op_id) {
8560b57cec5SDimitry Andric   return 0; // thread is not in a target region
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric OMPT_API_ROUTINE int ompt_get_num_devices(void) {
8600b57cec5SDimitry Andric   return 1; // only one device (the current device) is available
8610b57cec5SDimitry Andric }
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric /*****************************************************************************
8640b57cec5SDimitry Andric  * API inquiry for tool
8650b57cec5SDimitry Andric  ****************************************************************************/
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric static ompt_interface_fn_t ompt_fn_lookup(const char *s) {
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric #define ompt_interface_fn(fn)                                                  \
8700b57cec5SDimitry Andric   fn##_t fn##_f = fn;                                                          \
8710b57cec5SDimitry Andric   if (strcmp(s, #fn) == 0)                                                     \
8720b57cec5SDimitry Andric     return (ompt_interface_fn_t)fn##_f;
8730b57cec5SDimitry Andric 
8740b57cec5SDimitry Andric   FOREACH_OMPT_INQUIRY_FN(ompt_interface_fn)
8750b57cec5SDimitry Andric 
876bdd1243dSDimitry Andric #undef ompt_interface_fn
877bdd1243dSDimitry Andric 
878e8d8bef9SDimitry Andric   return NULL;
8790b57cec5SDimitry Andric }
880bdd1243dSDimitry Andric 
88106c3fb27SDimitry Andric static ompt_data_t *ompt_get_task_data() { return __ompt_get_task_data(); }
88206c3fb27SDimitry Andric 
88306c3fb27SDimitry Andric static ompt_data_t *ompt_get_target_task_data() {
88406c3fb27SDimitry Andric   return __ompt_get_target_task_data();
88506c3fb27SDimitry Andric }
88606c3fb27SDimitry Andric 
887bdd1243dSDimitry Andric /// Lookup function to query libomp callbacks registered by the tool
888bdd1243dSDimitry Andric static ompt_interface_fn_t ompt_libomp_target_fn_lookup(const char *s) {
88906c3fb27SDimitry Andric #define provide_fn(fn)                                                         \
89006c3fb27SDimitry Andric   if (strcmp(s, #fn) == 0)                                                     \
89106c3fb27SDimitry Andric     return (ompt_interface_fn_t)fn;
89206c3fb27SDimitry Andric 
89306c3fb27SDimitry Andric   provide_fn(ompt_get_callback);
89406c3fb27SDimitry Andric   provide_fn(ompt_get_task_data);
89506c3fb27SDimitry Andric   provide_fn(ompt_get_target_task_data);
89606c3fb27SDimitry Andric #undef provide_fn
89706c3fb27SDimitry Andric 
898bdd1243dSDimitry Andric #define ompt_interface_fn(fn, type, code)                                      \
899bdd1243dSDimitry Andric   if (strcmp(s, #fn) == 0)                                                     \
900bdd1243dSDimitry Andric     return (ompt_interface_fn_t)ompt_callbacks.ompt_callback(fn);
901bdd1243dSDimitry Andric 
902bdd1243dSDimitry Andric   FOREACH_OMPT_DEVICE_EVENT(ompt_interface_fn)
903bdd1243dSDimitry Andric   FOREACH_OMPT_EMI_EVENT(ompt_interface_fn)
904bdd1243dSDimitry Andric   FOREACH_OMPT_NOEMI_EVENT(ompt_interface_fn)
905bdd1243dSDimitry Andric #undef ompt_interface_fn
906bdd1243dSDimitry Andric 
907bdd1243dSDimitry Andric   return (ompt_interface_fn_t)0;
908bdd1243dSDimitry Andric }
909bdd1243dSDimitry Andric 
910bdd1243dSDimitry Andric /// This function is called by the libomptarget connector to assign
911bdd1243dSDimitry Andric /// callbacks already registered with libomp.
912bdd1243dSDimitry Andric _OMP_EXTERN void ompt_libomp_connect(ompt_start_tool_result_t *result) {
91306c3fb27SDimitry Andric   OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Enter ompt_libomp_connect\n");
914bdd1243dSDimitry Andric 
915bdd1243dSDimitry Andric   // Ensure libomp callbacks have been added if not already
916bdd1243dSDimitry Andric   __ompt_force_initialization();
917bdd1243dSDimitry Andric 
918*0fca6ea1SDimitry Andric   if (ompt_enabled.enabled && result) {
919*0fca6ea1SDimitry Andric     OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Connecting with libomptarget\n");
920bdd1243dSDimitry Andric     // Pass in the libomp lookup function so that the already registered
921bdd1243dSDimitry Andric     // functions can be extracted and assigned to the callbacks in
922bdd1243dSDimitry Andric     // libomptarget
923bdd1243dSDimitry Andric     result->initialize(ompt_libomp_target_fn_lookup,
92406c3fb27SDimitry Andric                        /* initial_device_num */ 0, /* tool_data */ nullptr);
925bdd1243dSDimitry Andric     // Track the object provided by libomptarget so that the finalizer can be
926bdd1243dSDimitry Andric     // called during OMPT finalization
927bdd1243dSDimitry Andric     libomptarget_ompt_result = result;
928bdd1243dSDimitry Andric   }
92906c3fb27SDimitry Andric   OMPT_VERBOSE_INIT_PRINT("libomp --> OMPT: Exit ompt_libomp_connect\n");
930bdd1243dSDimitry Andric }
931