diff --git a/openmp/libomptarget/include/ompt_device_callbacks.h b/openmp/libomptarget/include/ompt_device_callbacks.h --- a/openmp/libomptarget/include/ompt_device_callbacks.h +++ b/openmp/libomptarget/include/ompt_device_callbacks.h @@ -49,6 +49,20 @@ #undef OmptBindCallback } + /// Used to find a callback given its name + ompt_interface_fn_t lookupCallback(const char *InterfaceFunctionName) { +#define OmptLookup(Name, Type, Code) \ + if (strcmp(InterfaceFunctionName, #Name) == 0) \ + return (ompt_interface_fn_t)Name##_fn; + + FOREACH_OMPT_TARGET_CALLBACK(OmptLookup); +#undef OmptLookup + return (ompt_interface_fn_t) nullptr; + } + + /// Wrapper function to find a callback given its name + static ompt_interface_fn_t doLookup(const char *InterfaceFunctionName); + private: /// Set to true if callbacks for this library have been initialized bool Enabled; @@ -62,8 +76,6 @@ /// Device callbacks object for the library that performs the instantiation extern OmptDeviceCallbacksTy OmptDeviceCallbacks; -#undef DEBUG_PREFIX - #endif // OMPT_SUPPORT #endif // _OMPT_DEVICE_CALLBACKS_H diff --git a/openmp/libomptarget/plugins-nextgen/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/CMakeLists.txt --- a/openmp/libomptarget/plugins-nextgen/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/CMakeLists.txt @@ -49,6 +49,7 @@ PRIVATE elf_common MemoryManager + OMPT PluginInterface ${LIBOMPTARGET_DEP_LIBFFI_LIBRARIES} ${OPENMP_PTHREAD_LIB} diff --git a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt --- a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt @@ -90,6 +90,10 @@ NO_INSTALL_RPATH ) +if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT)) + target_link_libraries(omptarget.rtl.amdgpu.nextgen PRIVATE OMPT) +endif() + if (LIBOMP_HAVE_VERSION_SCRIPT_FLAG) target_link_libraries(omptarget.rtl.amdgpu.nextgen PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports") diff --git a/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt --- a/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/common/CMakeLists.txt @@ -10,4 +10,5 @@ # ##===----------------------------------------------------------------------===## +add_subdirectory(OMPT) add_subdirectory(PluginInterface) diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt copy from openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt copy to openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt --- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt @@ -6,23 +6,17 @@ # ##===----------------------------------------------------------------------===## # -# Common parts which can be used by all plugins +# Aggregation of parts which can be used by OpenMP tools # ##===----------------------------------------------------------------------===## -# NOTE: Don't try to build `PluginInterface` using `add_llvm_library` because we -# don't want to export `PluginInterface` while `add_llvm_library` requires that. -add_library(PluginInterface OBJECT - PluginInterface.cpp GlobalHandler.cpp JIT.cpp) - -# Only enable JIT for those targets that LLVM can support. -string(TOUPPER "${LLVM_TARGETS_TO_BUILD}" TargetsSupported) -foreach(Target ${TargetsSupported}) - target_compile_definitions(PluginInterface PRIVATE "LIBOMPTARGET_JIT_${Target}") -endforeach() +# NOTE: Don't try to build `OMPT` using `add_llvm_library` because we +# don't want to export `OMPT` while `add_llvm_library` requires that. +add_library(OMPT OBJECT + OmptCallback.cpp) # This is required when using LLVM libraries. -llvm_update_compile_flags(PluginInterface) +llvm_update_compile_flags(OMPT) if (LLVM_LINK_LLVM_DYLIB) set(llvm_libs LLVM) @@ -55,7 +49,7 @@ ) endif() -target_link_libraries(PluginInterface +target_link_libraries(OMPT PUBLIC ${llvm_libs} elf_common @@ -63,16 +57,16 @@ ) # Define the TARGET_NAME and DEBUG_PREFIX. -target_compile_definitions(PluginInterface PRIVATE - TARGET_NAME="PluginInterface" - DEBUG_PREFIX="PluginInterface" +target_compile_definitions(OMPT PRIVATE + TARGET_NAME="OMPT" + DEBUG_PREFIX="OMPT" ) -target_include_directories(PluginInterface +target_include_directories(OMPT INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} PRIVATE ${LIBOMPTARGET_INCLUDE_DIR} ) -set_target_properties(PluginInterface PROPERTIES +set_target_properties(OMPT PROPERTIES POSITION_INDEPENDENT_CODE ON CXX_VISIBILITY_PRESET protected) diff --git a/openmp/libomptarget/plugins-nextgen/common/OMPT/OmptCallback.cpp b/openmp/libomptarget/plugins-nextgen/common/OMPT/OmptCallback.cpp new file mode 100644 --- /dev/null +++ b/openmp/libomptarget/plugins-nextgen/common/OMPT/OmptCallback.cpp @@ -0,0 +1,83 @@ +//===---------- OmptCallback.cpp - Generic OMPT callbacks --------- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// OMPT support for PluginInterface +// +//===----------------------------------------------------------------------===// + +#ifdef OMPT_SUPPORT +#include +#include +#include +#include + +#include "Debug.h" +#include "ompt_connector.h" +#include "ompt_device_callbacks.h" + +/// Object maintaining all the callbacks in the plugin +OmptDeviceCallbacksTy OmptDeviceCallbacks; + +/// Lookup function used for querying callback functions maintained +/// by the plugin +ompt_interface_fn_t +OmptDeviceCallbacksTy::doLookup(const char *InterfaceFunctionName) { + // TODO This will be populated with device tracing functions + return (ompt_interface_fn_t) nullptr; +} + +/// Used to indicate whether OMPT was enabled for this library +static bool OmptEnabled = false; + +/// This function is passed to libomptarget as part of the OMPT connector +/// object. It is called by libomptarget during initialization of OMPT in the +/// plugin. \p lookup to be used to query callbacks registered with libomptarget +/// \p initial_device_num Initial device num provided by libomptarget +/// \p tool_data as provided by the tool +static int OmptDeviceInit(ompt_function_lookup_t lookup, int initial_device_num, + ompt_data_t *tool_data) { + DP("OMPT: Enter OmptDeviceInit\n"); + OmptEnabled = true; + // The lookup parameter is provided by libomptarget which already has the tool + // callbacks registered at this point. The registration call below causes the + // same callback functions to be registered in the plugin as well. + OmptDeviceCallbacks.registerCallbacks(lookup); + DP("OMPT: Exit OmptDeviceInit\n"); + return 0; +} + +/// This function is passed to libomptarget as part of the OMPT connector +/// object. It is called by libomptarget during finalization of OMPT in the +/// plugin. +static void OmptDeviceFini(ompt_data_t *tool_data) { + DP("OMPT: Executing OmptDeviceFini\n"); +} + +/// Used to initialize callbacks implemented by the tool. This interface will +/// lookup the callbacks table in libomptarget and assign them to the callbacks +/// table maintained in the calling plugin library. +void OmptCallbackInit() { + DP("OMPT: Entering OmptCallbackInit\n"); + /// Connect plugin instance with libomptarget + OmptLibraryConnectorTy LibomptargetConnector("libomptarget"); + ompt_start_tool_result_t OmptResult; + + // Initialize OmptResult with the init and fini functions that will be + // called by the connector + OmptResult.initialize = OmptDeviceInit; + OmptResult.finalize = OmptDeviceFini; + OmptResult.tool_data.value = 0; + + // Initialize the device callbacks first + OmptDeviceCallbacks.init(); + + // Now call connect that causes the above init/fini functions to be called + LibomptargetConnector.connect(&OmptResult); + DP("OMPT: Exiting OmptCallbackInit\n"); +} +#endif diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt --- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt @@ -62,6 +62,10 @@ MemoryManager ) +if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT)) + target_link_libraries(PluginInterface PUBLIC OMPT) +endif() + # Define the TARGET_NAME and DEBUG_PREFIX. target_compile_definitions(PluginInterface PRIVATE TARGET_NAME="PluginInterface" diff --git a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt --- a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt @@ -42,6 +42,10 @@ NO_INSTALL_RPATH ) +if ((OMPT_TARGET_DEFAULT) AND (LIBOMPTARGET_OMPT_SUPPORT)) + target_link_libraries(omptarget.rtl.cuda.nextgen PRIVATE OMPT) +endif() + if (LIBOMP_HAVE_VERSION_SCRIPT_FLAG) target_link_libraries(omptarget.rtl.cuda.nextgen PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/../exports,-z,defs") diff --git a/openmp/libomptarget/src/CMakeLists.txt b/openmp/libomptarget/src/CMakeLists.txt --- a/openmp/libomptarget/src/CMakeLists.txt +++ b/openmp/libomptarget/src/CMakeLists.txt @@ -20,7 +20,7 @@ interface.cpp interop.cpp omptarget.cpp - ompt_callback.cpp + OmptCallback.cpp rtl.cpp LegacyAPI.cpp diff --git a/openmp/libomptarget/src/ompt_callback.cpp b/openmp/libomptarget/src/OmptCallback.cpp rename from openmp/libomptarget/src/ompt_callback.cpp rename to openmp/libomptarget/src/OmptCallback.cpp --- a/openmp/libomptarget/src/ompt_callback.cpp +++ b/openmp/libomptarget/src/OmptCallback.cpp @@ -1,4 +1,4 @@ -//===-- ompt_callback.cpp - Target independent OpenMP target RTL -- C++ -*-===// +//===-- OmptCallback.cpp - Target independent OpenMP target RTL --- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -19,6 +19,7 @@ #include "omp-tools.h" +#include "Debug.h" #include "ompt_connector.h" #include "ompt_device_callbacks.h" #include "private.h" @@ -26,10 +27,39 @@ #define fnptr_to_ptr(x) ((void *)(uint64_t)x) /// Used to indicate whether OMPT was enabled for this library -bool ompt_enabled = false; +bool OmptEnabled = false; /// Object maintaining all the callbacks for this library OmptDeviceCallbacksTy OmptDeviceCallbacks; +/// Used to maintain the finalization function that is received +/// from the plugin during connect +class LibomptargetRtlFinalizer { +public: + LibomptargetRtlFinalizer() : RtlFinalization(nullptr) {} + void registerRtl(ompt_finalize_t FinalizationFunction) { + assert((RtlFinalization == nullptr) && + "RTL finalization may only be registered once"); + RtlFinalization = FinalizationFunction; + } + void finalize() { + if (RtlFinalization) + RtlFinalization(nullptr /* tool_data */); + RtlFinalization = nullptr; + } + +private: + ompt_finalize_t RtlFinalization; +}; + +/// Object that will maintain the RTL finalizer from the plugin +static LibomptargetRtlFinalizer LibraryFinalizer; + +/// Lookup function to be used by libomptarget library +ompt_interface_fn_t +OmptDeviceCallbacksTy::doLookup(const char *InterfaceFunctionName) { + return OmptDeviceCallbacks.lookupCallback(InterfaceFunctionName); +} + /// This is the function called by the higher layer (libomp) responsible /// for initializing OMPT in this library. This is passed to libomp /// as part of the OMPT connector object. @@ -40,7 +70,7 @@ int initial_device_num, ompt_data_t *tool_data) { DP("enter ompt_libomptarget_initialize!\n"); - ompt_enabled = true; + OmptEnabled = true; // The lookup parameter is provided by libomp which already has the // tool callbacks registered at this point. The registration call // below causes the same callback functions to be registered in @@ -50,9 +80,14 @@ return 0; } +/// This function is passed to libomp as part of the OMPT connector object. +/// It is called by libomp during finalization of OMPT in libomptarget. static void ompt_libomptarget_finalize(ompt_data_t *data) { DP("enter ompt_libomptarget_finalize!\n"); - ompt_enabled = false; + // Before disabling OMPT, call the finalizer (of the plugin) that was + // registered with this library + LibraryFinalizer.finalize(); + OmptEnabled = false; DP("exit ompt_libomptarget_finalize!\n"); } @@ -61,11 +96,9 @@ *****************************************************************************/ /// Used to initialize callbacks implemented by the tool. This interface /// will lookup the callbacks table in libomp and assign them to the callbacks -/// maintained in libomptarget. Using priority 102 to have this constructor -/// run after the init target library constructor with priority 101 (see -/// rtl.cpp). -__attribute__((constructor(102))) static void ompt_init(void) { - DP("OMPT: Enter ompt_init\n"); +/// maintained in libomptarget. +void InitOmptLibomp() { + DP("OMPT: Enter InitOmptLibomp\n"); // Connect with libomp static OmptLibraryConnectorTy LibompConnector("libomp"); static ompt_start_tool_result_t OmptResult; @@ -81,7 +114,28 @@ // Now call connect that causes the above init/fini functions to be called LibompConnector.connect(&OmptResult); - DP("OMPT: Exit ompt_init\n"); + DP("OMPT: Exit InitOmptLibomp\n"); } +extern "C" { +/// Used for connecting libomptarget with a plugin +void ompt_libomptarget_connect(ompt_start_tool_result_t *result) { + DP("OMPT: Enter ompt_libomptarget_connect\n"); + if (OmptEnabled && result) { + // Cache the fini function so that it can be invoked on exit + LibraryFinalizer.registerRtl(result->finalize); + // Invoke the provided init function with the lookup function maintained + // in this library so that callbacks maintained by this library are + // retrieved. + result->initialize(OmptDeviceCallbacksTy::doLookup, + 0 /* initial_device_num */, nullptr /* tool_data */); + } + DP("OMPT: Leave ompt_libomptarget_connect\n"); +} +} +#else +extern "C" { +/// Dummy definition when OMPT is disabled +void ompt_libomptarget_connect() {} +} #endif // OMPT_SUPPORT diff --git a/openmp/libomptarget/src/exports b/openmp/libomptarget/src/exports --- a/openmp/libomptarget/src/exports +++ b/openmp/libomptarget/src/exports @@ -64,6 +64,7 @@ __tgt_interop_init; __tgt_interop_use; __tgt_interop_destroy; + ompt_libomptarget_connect; local: *; }; diff --git a/openmp/libomptarget/src/rtl.cpp b/openmp/libomptarget/src/rtl.cpp --- a/openmp/libomptarget/src/rtl.cpp +++ b/openmp/libomptarget/src/rtl.cpp @@ -43,6 +43,10 @@ static char *ProfileTraceFile = nullptr; +#ifdef OMPT_SUPPORT +extern void InitOmptLibomp(); +#endif + __attribute__((constructor(101))) void init() { DP("Init target library!\n"); @@ -65,6 +69,11 @@ if (ProfileTraceFile) timeTraceProfilerInitialize(500 /* us */, "libomptarget"); + #ifdef OMPT_SUPPORT + // Initialize OMPT first + InitOmptLibomp(); + #endif + PM->RTLs.loadRTLs(); PM->registerDelayedLibraries(); }