1*330d8983SJohannes Doerfert //===-- OpenMP/OMPT/Connector.h - OpenMP Tooling lib connector -*- C++ -*-===// 2*330d8983SJohannes Doerfert // 3*330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5*330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*330d8983SJohannes Doerfert // 7*330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 8*330d8983SJohannes Doerfert // 9*330d8983SJohannes Doerfert // Support used by OMPT implementation to establish communication between 10*330d8983SJohannes Doerfert // various OpenMP runtime libraries: host openmp library, target-independent 11*330d8983SJohannes Doerfert // runtime library, and device-dependent runtime libraries. 12*330d8983SJohannes Doerfert // 13*330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 14*330d8983SJohannes Doerfert 15*330d8983SJohannes Doerfert #ifndef OMPTARGET_OPENMP_OMPT_CONNECTOR_H 16*330d8983SJohannes Doerfert #define OMPTARGET_OPENMP_OMPT_CONNECTOR_H 17*330d8983SJohannes Doerfert 18*330d8983SJohannes Doerfert #ifdef OMPT_SUPPORT 19*330d8983SJohannes Doerfert 20*330d8983SJohannes Doerfert #include "llvm/Support/DynamicLibrary.h" 21*330d8983SJohannes Doerfert 22*330d8983SJohannes Doerfert #include <memory> 23*330d8983SJohannes Doerfert #include <string> 24*330d8983SJohannes Doerfert 25*330d8983SJohannes Doerfert #include "omp-tools.h" 26*330d8983SJohannes Doerfert #include "omptarget.h" 27*330d8983SJohannes Doerfert 28*330d8983SJohannes Doerfert #include "Shared/Debug.h" 29*330d8983SJohannes Doerfert 30*330d8983SJohannes Doerfert #pragma push_macro("DEBUG_PREFIX") 31*330d8983SJohannes Doerfert #undef DEBUG_PREFIX 32*330d8983SJohannes Doerfert #define DEBUG_PREFIX "OMPT" 33*330d8983SJohannes Doerfert 34*330d8983SJohannes Doerfert /// Type for the function to be invoked for connecting two libraries. 35*330d8983SJohannes Doerfert typedef void (*OmptConnectRtnTy)(ompt_start_tool_result_t *result); 36*330d8983SJohannes Doerfert 37*330d8983SJohannes Doerfert /// Establish connection between openmp runtime libraries 38*330d8983SJohannes Doerfert /// 39*330d8983SJohannes Doerfert /// This class is used to communicate between an OMPT implementation in 40*330d8983SJohannes Doerfert /// libomptarget and libomp. It is also used to communicate between an 41*330d8983SJohannes Doerfert /// OMPT implementation in a device-specific plugin and 42*330d8983SJohannes Doerfert /// libomptarget. The decision whether OMPT is enabled or not needs to 43*330d8983SJohannes Doerfert /// be made when the library is loaded before any functions in the 44*330d8983SJohannes Doerfert /// library are invoked. For that reason, an instance of this class is 45*330d8983SJohannes Doerfert /// intended to be defined in the constructor for libomptarget or a 46*330d8983SJohannes Doerfert /// plugin so that the decision about whether OMPT is supposed to be 47*330d8983SJohannes Doerfert /// enabled is known before any interface function in the library is 48*330d8983SJohannes Doerfert /// invoked. 49*330d8983SJohannes Doerfert class OmptLibraryConnectorTy { 50*330d8983SJohannes Doerfert public: 51*330d8983SJohannes Doerfert /// Use \p LibName as the prefix of the global function used for connecting 52*330d8983SJohannes Doerfert /// two libraries, the source indicated by \p LibName and the destination 53*330d8983SJohannes Doerfert /// being the one that creates this object. OmptLibraryConnectorTy(const char * Ident)54*330d8983SJohannes Doerfert OmptLibraryConnectorTy(const char *Ident) { 55*330d8983SJohannes Doerfert LibIdent.append(Ident); 56*330d8983SJohannes Doerfert IsInitialized = false; 57*330d8983SJohannes Doerfert } 58*330d8983SJohannes Doerfert OmptLibraryConnectorTy() = delete; 59*330d8983SJohannes Doerfert /// Use \p OmptResult init to connect the two libraries denoted by this 60*330d8983SJohannes Doerfert /// object. The init function of \p OmptResult will be used during connection 61*330d8983SJohannes Doerfert /// and the fini function of \p OmptResult will be used during teardown. connect(ompt_start_tool_result_t * OmptResult)62*330d8983SJohannes Doerfert void connect(ompt_start_tool_result_t *OmptResult) { 63*330d8983SJohannes Doerfert initialize(); 64*330d8983SJohannes Doerfert if (!LibConnHandle) 65*330d8983SJohannes Doerfert return; 66*330d8983SJohannes Doerfert // Call the function provided by the source library for connect 67*330d8983SJohannes Doerfert LibConnHandle(OmptResult); 68*330d8983SJohannes Doerfert } 69*330d8983SJohannes Doerfert 70*330d8983SJohannes Doerfert private: initialize()71*330d8983SJohannes Doerfert void initialize() { 72*330d8983SJohannes Doerfert if (IsInitialized) 73*330d8983SJohannes Doerfert return; 74*330d8983SJohannes Doerfert 75*330d8983SJohannes Doerfert std::string ErrMsg; 76*330d8983SJohannes Doerfert std::string LibName = LibIdent; 77*330d8983SJohannes Doerfert LibName += ".so"; 78*330d8983SJohannes Doerfert 79*330d8983SJohannes Doerfert DP("OMPT: Trying to load library %s\n", LibName.c_str()); 80*330d8983SJohannes Doerfert auto DynLibHandle = std::make_unique<llvm::sys::DynamicLibrary>( 81*330d8983SJohannes Doerfert llvm::sys::DynamicLibrary::getPermanentLibrary(LibName.c_str(), 82*330d8983SJohannes Doerfert &ErrMsg)); 83*330d8983SJohannes Doerfert if (!DynLibHandle->isValid()) { 84*330d8983SJohannes Doerfert // The upper layer will bail out if the handle is null. 85*330d8983SJohannes Doerfert LibConnHandle = nullptr; 86*330d8983SJohannes Doerfert } else { 87*330d8983SJohannes Doerfert auto LibConnRtn = "ompt_" + LibIdent + "_connect"; 88*330d8983SJohannes Doerfert DP("OMPT: Trying to get address of connection routine %s\n", 89*330d8983SJohannes Doerfert LibConnRtn.c_str()); 90*330d8983SJohannes Doerfert LibConnHandle = reinterpret_cast<OmptConnectRtnTy>( 91*330d8983SJohannes Doerfert DynLibHandle->getAddressOfSymbol(LibConnRtn.c_str())); 92*330d8983SJohannes Doerfert } 93*330d8983SJohannes Doerfert DP("OMPT: Library connection handle = %p\n", LibConnHandle); 94*330d8983SJohannes Doerfert IsInitialized = true; 95*330d8983SJohannes Doerfert } 96*330d8983SJohannes Doerfert 97*330d8983SJohannes Doerfert /// Ensure initialization occurs only once 98*330d8983SJohannes Doerfert bool IsInitialized; 99*330d8983SJohannes Doerfert /// Handle of connect routine provided by source library 100*330d8983SJohannes Doerfert OmptConnectRtnTy LibConnHandle; 101*330d8983SJohannes Doerfert /// Name of connect routine provided by source library 102*330d8983SJohannes Doerfert std::string LibIdent; 103*330d8983SJohannes Doerfert }; 104*330d8983SJohannes Doerfert 105*330d8983SJohannes Doerfert #endif // OMPT_SUPPORT 106*330d8983SJohannes Doerfert 107*330d8983SJohannes Doerfert #pragma pop_macro("DEBUG_PREFIX") 108*330d8983SJohannes Doerfert 109*330d8983SJohannes Doerfert #endif // OMPTARGET_OPENMP_OMPT_CONNECTOR_H 110