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; diff --git a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt --- a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt +++ b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt @@ -68,6 +68,7 @@ impl/get_elf_mach_gfx_name.cpp impl/system.cpp impl/msgpack.cpp + src/ompt_callback.cpp src/rtl.cpp ${LIBOMPTARGET_EXTRA_SOURCE} diff --git a/openmp/libomptarget/plugins/amdgpu/src/ompt_callback.cpp b/openmp/libomptarget/plugins/amdgpu/src/ompt_callback.cpp new file mode 100644 --- /dev/null +++ b/openmp/libomptarget/plugins/amdgpu/src/ompt_callback.cpp @@ -0,0 +1,85 @@ +//===-------- ompt_callback.cpp - AMDGPU 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 AMDGPU +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include "Debug.h" +#include "ompt_connector.h" +#include "ompt_device_callbacks.h" + +/// Object maintaining all the callbacks in the plugin +OmptDeviceCallbacksTy ompt_device_callbacks; + +/// 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 ompt_enabled = false; + +#ifdef OMPT_SUPPORT +/// 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 ompt_device_init(ompt_function_lookup_t lookup, + int initial_device_num, ompt_data_t *tool_data) { + DP("OMPT: Enter ompt_device_init\n"); + ompt_enabled = 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. + ompt_device_callbacks.registerCallbacks(lookup); + DP("OMPT: Exit ompt_device_init\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 ompt_device_fini(ompt_data_t *tool_data) { + DP("OMPT: executing amdgpu_ompt_device_fini\n"); +} + +//**************************************************************************** +// constructor +//**************************************************************************** +/// 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 this plugin library. +__attribute__((constructor)) static void ompt_init(void) { + DP("OMPT: Entering ompt_init\n"); + /// Connect with libomptarget + static OmptLibraryConnectorTy LibomptargetConnector("ompt_libomptarget"); + 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_device_init; + OmptResult.finalize = ompt_device_fini; + OmptResult.tool_data.value = 0; + + // Initialize the device callbacks first + ompt_device_callbacks.init(); + + // Now call connect that causes the above init/fini functions to be called + LibomptargetConnector.connect(&OmptResult); + DP("OMPT: Exiting ompt_init\n"); +} +#endif diff --git a/openmp/libomptarget/src/exports b/openmp/libomptarget/src/exports --- a/openmp/libomptarget/src/exports +++ b/openmp/libomptarget/src/exports @@ -62,6 +62,7 @@ __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 --- a/openmp/libomptarget/src/ompt_callback.cpp +++ b/openmp/libomptarget/src/ompt_callback.cpp @@ -19,6 +19,7 @@ #include "omp-tools.h" +#include "Debug.h" #include "ompt_connector.h" #include "ompt_device_callbacks.h" #include "private.h" @@ -30,6 +31,34 @@ /// 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() : FiniFn(nullptr) {} + void registerRtl(ompt_finalize_t fn) { + assert(FiniFn == nullptr && "Finalizer already registered"); + FiniFn = fn; + } + void finalize() { + if (FiniFn) + FiniFn(nullptr /* tool_data */); + FiniFn = nullptr; + } + +private: + ompt_finalize_t FiniFn; +}; + +/// Object that will maintain the finalizer of the plugin +static LibomptargetRtlFinalizer LibOmptTargetRTLFinalizer; + +/// 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. @@ -50,8 +79,13 @@ 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 + LibOmptTargetRTLFinalizer.finalize(); ompt_enabled = false; DP("exit ompt_libomptarget_finalize!\n"); } @@ -85,3 +119,20 @@ } #endif // OMPT_SUPPORT + +extern "C" { +/// Used for connecting libomptarget with a plugin +void ompt_libomptarget_connect(ompt_start_tool_result_t *result) { + DP("OMPT: Enter libomptarget_ompt_connect\n"); + if (ompt_enabled && result) { + // Cache the fini function so that it can be invoked on exit + LibOmptTargetRTLFinalizer.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 libomptarget_ompt_connect\n"); +} +}