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, ¶llel_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