From 01035dc04df49061adf4c7c0ddf4b2e2df6e31f7 Mon Sep 17 00:00:00 2001 From: Dhruva Chakrabarti Date: Fri, 5 May 2023 12:00:26 +0200 Subject: [OpenMP] [OMPT] [amdgpu] [4/8] Implemented callback registration in nextgen plugins The purpose of this patch is to Implement registration of callback functions in the generic plugin by looking up corresponding callbacks in libomptarget. The overall design document is https://rice.app.box.com/s/pf3gix2hs4d4o1aatwir1set05xmjljc Defined an object of type OmptDeviceCallbacksTy in the amdgpu plugin for holding the tool-provided callback functions. Implemented a global constructor in the plugin that creates a connector object to connect with libomptarget. The callbacks that are already registered with libomptarget are looked up and registered with the plugin. Combined with an internal patch from Dhruva Chakrabarti, which fixes the OMPT initialization ordering. Achieved through removal of the constructor attribute from ompt_init. Patch from John Mellor-Crummey With contributions from: Dhruva Chakrabarti Michael Halkenhaeuser Reviewed By: dhruvachak, tianshilei1992 Differential Revision: https://reviews.llvm.org/D124070 --- .../libomptarget/include/ompt_device_callbacks.h | 16 ++- openmp/libomptarget/plugins-nextgen/CMakeLists.txt | 1 + .../plugins-nextgen/amdgpu/CMakeLists.txt | 4 + .../plugins-nextgen/common/CMakeLists.txt | 1 + .../plugins-nextgen/common/OMPT/CMakeLists.txt | 72 +++++++++++ .../plugins-nextgen/common/OMPT/OmptCallback.cpp | 83 ++++++++++++ .../common/PluginInterface/CMakeLists.txt | 4 + .../plugins-nextgen/cuda/CMakeLists.txt | 4 + openmp/libomptarget/src/CMakeLists.txt | 2 +- openmp/libomptarget/src/OmptCallback.cpp | 141 +++++++++++++++++++++ openmp/libomptarget/src/exports | 1 + openmp/libomptarget/src/ompt_callback.cpp | 87 ------------- openmp/libomptarget/src/rtl.cpp | 9 ++ 13 files changed, 335 insertions(+), 90 deletions(-) create mode 100644 openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt create mode 100644 openmp/libomptarget/plugins-nextgen/common/OMPT/OmptCallback.cpp create mode 100644 openmp/libomptarget/src/OmptCallback.cpp delete mode 100644 openmp/libomptarget/src/ompt_callback.cpp (limited to 'openmp') diff --git a/openmp/libomptarget/include/ompt_device_callbacks.h b/openmp/libomptarget/include/ompt_device_callbacks.h index 3dbba3dedbee..127e18950249 100644 --- a/openmp/libomptarget/include/ompt_device_callbacks.h +++ b/openmp/libomptarget/include/ompt_device_callbacks.h @@ -49,6 +49,20 @@ public: #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 @@ private: /// 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 index af02f050f467..a51da395680b 100644 --- a/openmp/libomptarget/plugins-nextgen/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/CMakeLists.txt @@ -49,6 +49,7 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "${tmachine}$") 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 index b689ff5a38d5..d0d5f54c667d 100644 --- a/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/amdgpu/CMakeLists.txt @@ -90,6 +90,10 @@ add_llvm_library(omptarget.rtl.amdgpu.nextgen SHARED 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 index 1c5594eec5af..f0645d0d1753 100644 --- 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/OMPT/CMakeLists.txt b/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt new file mode 100644 index 000000000000..c50dd18dce02 --- /dev/null +++ b/openmp/libomptarget/plugins-nextgen/common/OMPT/CMakeLists.txt @@ -0,0 +1,72 @@ +##===----------------------------------------------------------------------===## +# +# 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 +# +##===----------------------------------------------------------------------===## +# +# Aggregation of parts which can be used by OpenMP tools +# +##===----------------------------------------------------------------------===## + +# 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(OMPT) + +if (LLVM_LINK_LLVM_DYLIB) + set(llvm_libs LLVM) +else() + llvm_map_components_to_libnames(llvm_libs + ${LLVM_TARGETS_TO_BUILD} + AggressiveInstCombine + Analysis + BinaryFormat + BitReader + BitWriter + CodeGen + Core + Extensions + InstCombine + Instrumentation + IPO + IRReader + Linker + MC + Object + Passes + Remarks + ScalarOpts + Support + Target + TargetParser + TransformUtils + Vectorize + ) +endif() + +target_link_libraries(OMPT + PUBLIC + ${llvm_libs} + elf_common + MemoryManager +) + +# Define the TARGET_NAME and DEBUG_PREFIX. +target_compile_definitions(OMPT PRIVATE + TARGET_NAME="OMPT" + DEBUG_PREFIX="OMPT" +) + +target_include_directories(OMPT + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${LIBOMPTARGET_INCLUDE_DIR} +) + +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 index 000000000000..eb47f10a3f41 --- /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 index 91d64f429823..90d2113c4ea7 100644 --- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/CMakeLists.txt @@ -62,6 +62,10 @@ target_link_libraries(PluginInterface 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 index 397b06b67692..736a961f5618 100644 --- a/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt +++ b/openmp/libomptarget/plugins-nextgen/cuda/CMakeLists.txt @@ -42,6 +42,10 @@ add_llvm_library(omptarget.rtl.cuda.nextgen SHARED 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 index ef3a6270b78a..425121c9ef10 100644 --- a/openmp/libomptarget/src/CMakeLists.txt +++ b/openmp/libomptarget/src/CMakeLists.txt @@ -20,7 +20,7 @@ add_llvm_library(omptarget interface.cpp interop.cpp omptarget.cpp - ompt_callback.cpp + OmptCallback.cpp rtl.cpp LegacyAPI.cpp diff --git a/openmp/libomptarget/src/OmptCallback.cpp b/openmp/libomptarget/src/OmptCallback.cpp new file mode 100644 index 000000000000..885757e28793 --- /dev/null +++ b/openmp/libomptarget/src/OmptCallback.cpp @@ -0,0 +1,141 @@ +//===-- 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. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementation of OMPT callback interfaces for target independent layer +// +//===----------------------------------------------------------------------===// + +#ifdef OMPT_SUPPORT + +#include +#include +#include +#include + +#include "omp-tools.h" + +#include "Debug.h" +#include "ompt_connector.h" +#include "ompt_device_callbacks.h" +#include "private.h" + +#define fnptr_to_ptr(x) ((void *)(uint64_t)x) + +/// Used to indicate whether OMPT was enabled for this library +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. +/// \p lookup to be used to query callbacks registered with libomp +/// \p initial_device_num Initial device num provided by libomp +/// \p tool_data as provided by the tool +static int ompt_libomptarget_initialize(ompt_function_lookup_t lookup, + int initial_device_num, + ompt_data_t *tool_data) { + DP("enter ompt_libomptarget_initialize!\n"); + 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 + // libomptarget as well + OmptDeviceCallbacks.registerCallbacks(lookup); + DP("exit ompt_libomptarget_initialize!\n"); + 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"); + // 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"); +} + +/***************************************************************************** + * constructor + *****************************************************************************/ +/// 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. +void InitOmptLibomp() { + DP("OMPT: Enter InitOmptLibomp\n"); + // Connect with libomp + static OmptLibraryConnectorTy LibompConnector("libomp"); + static ompt_start_tool_result_t OmptResult; + + // Initialize OmptResult with the init and fini functions that will be + // called by the connector + OmptResult.initialize = ompt_libomptarget_initialize; + OmptResult.finalize = ompt_libomptarget_finalize; + 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 + LibompConnector.connect(&OmptResult); + 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 index 6c3fdf0950ab..48591dd6c3fa 100644 --- a/openmp/libomptarget/src/exports +++ b/openmp/libomptarget/src/exports @@ -64,6 +64,7 @@ VERS1.0 { __tgt_interop_init; __tgt_interop_use; __tgt_interop_destroy; + ompt_libomptarget_connect; local: *; }; diff --git a/openmp/libomptarget/src/ompt_callback.cpp b/openmp/libomptarget/src/ompt_callback.cpp deleted file mode 100644 index 5715642ad3a9..000000000000 --- a/openmp/libomptarget/src/ompt_callback.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//===-- ompt_callback.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. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Implementation of OMPT callback interfaces for target independent layer -// -//===----------------------------------------------------------------------===// - -#ifdef OMPT_SUPPORT - -#include -#include -#include -#include - -#include "omp-tools.h" - -#include "ompt_connector.h" -#include "ompt_device_callbacks.h" -#include "private.h" - -#define fnptr_to_ptr(x) ((void *)(uint64_t)x) - -/// Used to indicate whether OMPT was enabled for this library -bool ompt_enabled = false; -/// Object maintaining all the callbacks for this library -OmptDeviceCallbacksTy OmptDeviceCallbacks; - -/// 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. -/// \p lookup to be used to query callbacks registered with libomp -/// \p initial_device_num Initial device num provided by libomp -/// \p tool_data as provided by the tool -static int ompt_libomptarget_initialize(ompt_function_lookup_t lookup, - int initial_device_num, - ompt_data_t *tool_data) { - DP("enter ompt_libomptarget_initialize!\n"); - ompt_enabled = 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 - // libomptarget as well - OmptDeviceCallbacks.registerCallbacks(lookup); - DP("exit ompt_libomptarget_initialize!\n"); - return 0; -} - -static void ompt_libomptarget_finalize(ompt_data_t *data) { - DP("enter ompt_libomptarget_finalize!\n"); - ompt_enabled = false; - DP("exit ompt_libomptarget_finalize!\n"); -} - -/***************************************************************************** - * constructor - *****************************************************************************/ -/// 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"); - // Connect with libomp - static OmptLibraryConnectorTy LibompConnector("libomp"); - static ompt_start_tool_result_t OmptResult; - - // Initialize OmptResult with the init and fini functions that will be - // called by the connector - OmptResult.initialize = ompt_libomptarget_initialize; - OmptResult.finalize = ompt_libomptarget_finalize; - 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 - LibompConnector.connect(&OmptResult); - DP("OMPT: Exit ompt_init\n"); -} - -#endif // OMPT_SUPPORT diff --git a/openmp/libomptarget/src/rtl.cpp b/openmp/libomptarget/src/rtl.cpp index 9c7cc355d054..5360d9784cb6 100644 --- a/openmp/libomptarget/src/rtl.cpp +++ b/openmp/libomptarget/src/rtl.cpp @@ -43,6 +43,10 @@ PluginManager *PM; 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 @@ __attribute__((constructor(101))) void init() { if (ProfileTraceFile) timeTraceProfilerInitialize(500 /* us */, "libomptarget"); + #ifdef OMPT_SUPPORT + // Initialize OMPT first + InitOmptLibomp(); + #endif + PM->RTLs.loadRTLs(); PM->registerDelayedLibraries(); } -- cgit v1.2.1