/* * ompt-general.cpp -- OMPT implementation of interface functions */ //===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /***************************************************************************** * system include files ****************************************************************************/ #include <assert.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #if KMP_OS_UNIX #include <dlfcn.h> #endif /***************************************************************************** * ompt include files ****************************************************************************/ #include "ompt-specific.cpp" /***************************************************************************** * macros ****************************************************************************/ #define ompt_get_callback_success … #define ompt_get_callback_failure … #define no_tool_present … #define OMPT_API_ROUTINE … #ifndef OMPT_STR_MATCH #define OMPT_STR_MATCH … #endif // prints for an enabled OMP_TOOL_VERBOSE_INIT. // In the future a prefix could be added in the first define, the second define // omits the prefix to allow for continued lines. Example: "PREFIX: Start // tool... Success." instead of "PREFIX: Start tool... PREFIX: Success." #define OMPT_VERBOSE_INIT_PRINT(...) … #define OMPT_VERBOSE_INIT_CONTINUED_PRINT(...) … static FILE *verbose_file; static int verbose_init; /***************************************************************************** * types ****************************************************************************/ ompt_state_info_t; kmp_mutex_impl_info_t; enum tool_setting_e { … }; /***************************************************************************** * global variables ****************************************************************************/ ompt_callbacks_active_t ompt_enabled; ompt_state_info_t ompt_state_info[] = …; kmp_mutex_impl_info_t kmp_mutex_impl_info[] = …; ompt_callbacks_internal_t ompt_callbacks; static ompt_start_tool_result_t *ompt_start_tool_result = …; #if KMP_OS_WINDOWS static HMODULE ompt_tool_module = NULL; static HMODULE ompt_archer_module = NULL; #define OMPT_DLCLOSE … #else static void *ompt_tool_module = …; static void *ompt_archer_module = …; #define OMPT_DLCLOSE(Lib) … #endif /// Used to track the initializer and the finalizer provided by libomptarget static ompt_start_tool_result_t *libomptarget_ompt_result = …; /***************************************************************************** * forward declarations ****************************************************************************/ static ompt_interface_fn_t ompt_fn_lookup(const char *s); OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void); /***************************************************************************** * initialization and finalization (private operations) ****************************************************************************/ ompt_start_tool_t; #if KMP_OS_DARWIN // While Darwin supports weak symbols, the library that wishes to provide a new // implementation has to link against this runtime which defeats the purpose // of having tools that are agnostic of the underlying runtime implementation. // // Fortunately, the linker includes all symbols of an executable in the global // symbol table by default so dlsym() even finds static implementations of // ompt_start_tool. For this to work on Linux, -Wl,--export-dynamic needs to be // passed when building the application which we don't want to rely on. static ompt_start_tool_result_t *ompt_tool_darwin(unsigned int omp_version, const char *runtime_version) { ompt_start_tool_result_t *ret = NULL; // Search symbol in the current address space. ompt_start_tool_t start_tool = (ompt_start_tool_t)dlsym(RTLD_DEFAULT, "ompt_start_tool"); if (start_tool) { ret = start_tool(omp_version, runtime_version); } return ret; } #elif OMPT_HAVE_WEAK_ATTRIBUTE // On Unix-like systems that support weak symbols the following implementation // of ompt_start_tool() will be used in case no tool-supplied implementation of // this function is present in the address space of a process. _OMP_EXTERN OMPT_WEAK_ATTRIBUTE ompt_start_tool_result_t * ompt_start_tool(unsigned int omp_version, const char *runtime_version) { … } #elif OMPT_HAVE_PSAPI // On Windows, the ompt_tool_windows function is used to find the // ompt_start_tool symbol across all modules loaded by a process. If // ompt_start_tool is found, ompt_start_tool's return value is used to // initialize the tool. Otherwise, NULL is returned and OMPT won't be enabled. #include <psapi.h> #pragma comment(lib, "psapi.lib") // The number of loaded modules to start enumeration with EnumProcessModules() #define NUM_MODULES … static ompt_start_tool_result_t * ompt_tool_windows(unsigned int omp_version, const char *runtime_version) { int i; DWORD needed, new_size; HMODULE *modules; HANDLE process = GetCurrentProcess(); modules = (HMODULE *)malloc(NUM_MODULES * sizeof(HMODULE)); ompt_start_tool_t ompt_tool_p = NULL; #if OMPT_DEBUG printf("ompt_tool_windows(): looking for ompt_start_tool\n"); #endif if (!EnumProcessModules(process, modules, NUM_MODULES * sizeof(HMODULE), &needed)) { // Regardless of the error reason use the stub initialization function free(modules); return NULL; } // Check if NUM_MODULES is enough to list all modules new_size = needed / sizeof(HMODULE); if (new_size > NUM_MODULES) { #if OMPT_DEBUG printf("ompt_tool_windows(): resize buffer to %d bytes\n", needed); #endif modules = (HMODULE *)realloc(modules, needed); // If resizing failed use the stub function. if (!EnumProcessModules(process, modules, needed, &needed)) { free(modules); return NULL; } } for (i = 0; i < new_size; ++i) { (FARPROC &)ompt_tool_p = GetProcAddress(modules[i], "ompt_start_tool"); if (ompt_tool_p) { #if OMPT_DEBUG TCHAR modName[MAX_PATH]; if (GetModuleFileName(modules[i], modName, MAX_PATH)) printf("ompt_tool_windows(): ompt_start_tool found in module %s\n", modName); #endif free(modules); return (*ompt_tool_p)(omp_version, runtime_version); } #if OMPT_DEBUG else { TCHAR modName[MAX_PATH]; if (GetModuleFileName(modules[i], modName, MAX_PATH)) printf("ompt_tool_windows(): ompt_start_tool not found in module %s\n", modName); } #endif } free(modules); return NULL; } #else #error Activation of OMPT is not supported on this platform. #endif static ompt_start_tool_result_t * ompt_try_start_tool(unsigned int omp_version, const char *runtime_version) { … } void ompt_pre_init() { … } extern "C" int omp_get_initial_device(void); void ompt_post_init() { … } void ompt_fini() { … } /***************************************************************************** * interface operations ****************************************************************************/ /***************************************************************************** * state ****************************************************************************/ OMPT_API_ROUTINE int ompt_enumerate_states(int current_state, int *next_state, const char **next_state_name) { … } OMPT_API_ROUTINE int ompt_enumerate_mutex_impls(int current_impl, int *next_impl, const char **next_impl_name) { … } /***************************************************************************** * callbacks ****************************************************************************/ OMPT_API_ROUTINE ompt_set_result_t ompt_set_callback(ompt_callbacks_t which, ompt_callback_t callback) { … } OMPT_API_ROUTINE int ompt_get_callback(ompt_callbacks_t which, ompt_callback_t *callback) { … } /***************************************************************************** * parallel regions ****************************************************************************/ OMPT_API_ROUTINE int ompt_get_parallel_info(int ancestor_level, ompt_data_t **parallel_data, int *team_size) { … } OMPT_API_ROUTINE int ompt_get_state(ompt_wait_id_t *wait_id) { … } /***************************************************************************** * tasks ****************************************************************************/ OMPT_API_ROUTINE ompt_data_t *ompt_get_thread_data(void) { … } OMPT_API_ROUTINE int ompt_get_task_info(int ancestor_level, int *type, ompt_data_t **task_data, ompt_frame_t **task_frame, ompt_data_t **parallel_data, int *thread_num) { … } OMPT_API_ROUTINE int ompt_get_task_memory(void **addr, size_t *size, int block) { … } /***************************************************************************** * num_procs ****************************************************************************/ OMPT_API_ROUTINE int ompt_get_num_procs(void) { … } /***************************************************************************** * places ****************************************************************************/ OMPT_API_ROUTINE int ompt_get_num_places(void) { … } OMPT_API_ROUTINE int ompt_get_place_proc_ids(int place_num, int ids_size, int *ids) { … } OMPT_API_ROUTINE int ompt_get_place_num(void) { … } OMPT_API_ROUTINE int ompt_get_partition_place_nums(int place_nums_size, int *place_nums) { … } /***************************************************************************** * places ****************************************************************************/ OMPT_API_ROUTINE int ompt_get_proc_id(void) { … } /***************************************************************************** * compatability ****************************************************************************/ /* * Currently unused function OMPT_API_ROUTINE int ompt_get_ompt_version() { return OMPT_VERSION; } */ /***************************************************************************** * application-facing API ****************************************************************************/ /*---------------------------------------------------------------------------- | control ---------------------------------------------------------------------------*/ int __kmp_control_tool(uint64_t command, uint64_t modifier, void *arg) { … } /***************************************************************************** * misc ****************************************************************************/ OMPT_API_ROUTINE uint64_t ompt_get_unique_id(void) { … } OMPT_API_ROUTINE void ompt_finalize_tool(void) { … } /***************************************************************************** * Target ****************************************************************************/ OMPT_API_ROUTINE int ompt_get_target_info(uint64_t *device_num, ompt_id_t *target_id, ompt_id_t *host_op_id) { … } OMPT_API_ROUTINE int ompt_get_num_devices(void) { … } /***************************************************************************** * API inquiry for tool ****************************************************************************/ static ompt_interface_fn_t ompt_fn_lookup(const char *s) { … } static ompt_data_t *ompt_get_task_data() { … } static ompt_data_t *ompt_get_target_task_data() { … } /// Lookup function to query libomp callbacks registered by the tool static ompt_interface_fn_t ompt_libomp_target_fn_lookup(const char *s) { … } /// This function is called by the libomptarget connector to assign /// callbacks already registered with libomp. _OMP_EXTERN void ompt_libomp_connect(ompt_start_tool_result_t *result) { … }