refactor: Unify GTPin initialization logic between APIs

Add support for new GTPin loading logic in OCL path, similar to existing
in L0 - invoking exposed, dedicated API call (OpenGTPinOCL).
- Move logic to shared, including unit tests
- Check whether instrumentation is required on
  clGetPlatformIDs API call, and if yes,
  make a call to OpenGTPinOCL function.
Signed-off-by: Kacper Nowak <kacper.nowak@intel.com>
This commit is contained in:
Kacper Nowak 2023-08-02 19:33:48 +02:00 committed by Compute-Runtime-Automation
parent 05fb8e9c00
commit 68a5108e05
18 changed files with 162 additions and 106 deletions

View File

@ -11,12 +11,12 @@
#include "shared/source/execution_environment/execution_environment.h"
#include "shared/source/os_interface/debug_env_reader.h"
#include "shared/source/os_interface/device_factory.h"
#include "shared/source/pin/pin.h"
#include "level_zero/core/source/device/device.h"
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/core/source/driver/driver_imp.h"
#include "level_zero/tools/source/metrics/metric.h"
#include "level_zero/tools/source/pin/pin.h"
#include <memory>
#include <thread>
@ -81,8 +81,9 @@ void DriverImp::initialize(ze_result_t *result) {
}
if ((*result == ZE_RESULT_SUCCESS) && envVariables.pin) {
*result = PinContext::init();
if (*result != ZE_RESULT_SUCCESS) {
std::string gtpinFuncName{"OpenGTPin"};
if (false == NEO::PinContext::init(gtpinFuncName)) {
*result = ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
delete GlobalDriver;
GlobalDriverHandle = nullptr;
GlobalDriver = nullptr;

View File

@ -1,14 +0,0 @@
#
# Copyright (C) 2020-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/pin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pin.h
)
add_subdirectories()

View File

@ -1,18 +0,0 @@
#
# Copyright (C) 2020-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(UNIX)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_pin.h
)
target_include_directories(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
endif()

View File

@ -1,17 +0,0 @@
#
# Copyright (C) 2020-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(WIN32)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_pin.h
)
target_include_directories(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
endif()

View File

@ -297,6 +297,7 @@ cl_int CL_API_CALL clGetDeviceIDs(cl_platform_id platform,
/* If no suitable device, set a error. */
if (retNum == 0)
retVal = CL_DEVICE_NOT_FOUND;
} while (false);
TRACING_EXIT(ClGetDeviceIDs, &retVal);
return retVal;
@ -438,6 +439,13 @@ cl_context CL_API_CALL clCreateContext(const cl_context_properties *properties,
break;
}
}
/* At this point we can safely notify GTPin to allow initialization */
EnvironmentVariableReader envReader;
if (envReader.getSetting("ZET_ENABLE_PROGRAM_INSTRUMENTATION", false)) {
if (false == pPlatform->notifyGtpinInit()) {
retVal = CL_INVALID_OPERATION;
}
}
if (CL_SUCCESS != retVal) {
break;
}

View File

@ -17,6 +17,7 @@
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/get_info.h"
#include "shared/source/helpers/hw_info.h"
#include "shared/source/pin/pin.h"
#include "shared/source/source_level_debugger/source_level_debugger.h"
#include "opencl/source/api/api.h"
@ -185,6 +186,17 @@ bool Platform::initialize(std::vector<std::unique_ptr<Device>> devices) {
return true;
}
bool Platform::notifyGtpinInit() {
bool res = false;
auto notifyGTPin = [](bool &res) {
const std::string gtpinFuncName{"OpenGTPinOCL"};
res = PinContext::init(gtpinFuncName);
return;
};
std::call_once(this->oclInitGTPinOnce, notifyGTPin, res);
return res;
}
void Platform::fillGlobalDispatchTable() {
sharingFactory.fillGlobalDispatchTable();
}

View File

@ -48,6 +48,7 @@ class Platform : public BaseObject<_cl_platform_id> {
MOCKABLE_VIRTUAL bool initialize(std::vector<std::unique_ptr<Device>> devices);
bool isInitialized();
bool notifyGtpinInit();
size_t getNumDevices() const;
ClDevice **getClDevices();
@ -71,6 +72,7 @@ class Platform : public BaseObject<_cl_platform_id> {
ClDeviceVector clDevices;
ExecutionEnvironment &executionEnvironment;
std::once_flag initializeExtensionsWithVersionOnce;
std::once_flag oclInitGTPinOnce;
};
extern std::vector<std::unique_ptr<Platform>> *platformsImpl;

View File

@ -6,6 +6,9 @@
*/
#include "shared/source/helpers/ptr_math.h"
#include "shared/source/pin/pin.h"
#include "shared/test/common/mocks/mock_io_functions.h"
#include "shared/test/common/mocks/mock_os_library.h"
#include "opencl/test/unit_test/api/cl_api_tests.h"
#include "opencl/test/unit_test/mocks/mock_platform.h"
@ -247,4 +250,43 @@ TEST_F(ClCreateContextTests, GivenDevicesFromDifferentPlatformsWhenCreatingConte
EXPECT_EQ(CL_INVALID_DEVICE, retVal);
EXPECT_EQ(nullptr, clContext);
}
TEST_F(ClCreateContextTests, givenProgramInstrumentationEnabledAndSuccesfulGtpinNotifyingWhenCreatingContextThenReturnSuccess) {
VariableBackup<uint32_t> mockGetenvCalledBackup(&IoFunctions::mockGetenvCalled, 0);
std::unordered_map<std::string, std::string> mockableEnvs = {{"ZET_ENABLE_PROGRAM_INSTRUMENTATION", "1"}};
VariableBackup<std::unordered_map<std::string, std::string> *> mockableEnvValuesBackup(&IoFunctions::mockableEnvValues, &mockableEnvs);
uint32_t (*openPinHandler)(void *) = [](void *arg) -> uint32_t { return 0; };
auto newPtr = new MockOsLibrary(reinterpret_cast<void *>(openPinHandler), false);
MockOsLibrary::loadLibraryNewObject = newPtr;
NEO::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
auto context = clCreateContext(nullptr, 1u, &testedClDevice, nullptr, nullptr, &retVal);
EXPECT_EQ(CL_SUCCESS, retVal);
ASSERT_NE(nullptr, context);
retVal = clReleaseContext(context);
EXPECT_EQ(CL_SUCCESS, retVal);
MockOsLibrary::loadLibraryNewObject = nullptr;
delete newPtr;
}
TEST_F(ClCreateContextTests, givenProgramInstrumentationEnabledAndFailedGtpinNotifyingWhenCreatingContextThenReturnError) {
VariableBackup<uint32_t> mockGetenvCalledBackup(&IoFunctions::mockGetenvCalled, 0);
std::unordered_map<std::string, std::string> mockableEnvs = {{"ZET_ENABLE_PROGRAM_INSTRUMENTATION", "1"}};
VariableBackup<std::unordered_map<std::string, std::string> *> mockableEnvValuesBackup(&IoFunctions::mockableEnvValues, &mockableEnvs);
uint32_t (*openPinHandler)(void *) = [](void *arg) -> uint32_t { return -1; }; // bad gtpin handler
auto newPtr = new MockOsLibrary(reinterpret_cast<void *>(openPinHandler), false);
MockOsLibrary::loadLibraryNewObject = newPtr;
NEO::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
auto context = clCreateContext(nullptr, 1u, &testedClDevice, nullptr, nullptr, &retVal);
EXPECT_EQ(CL_INVALID_OPERATION, retVal);
EXPECT_EQ(nullptr, context);
MockOsLibrary::loadLibraryNewObject = nullptr;
delete newPtr;
}
} // namespace ULT

View File

@ -143,6 +143,7 @@ append_sources_from_properties(CORE_SOURCES
NEO_DEVICE_BINARY_FORMAT
NEO_UNIFIED_MEMORY
NEO_CORE_RELEASE_HELPER
NEO_GTPIN
)
if(WIN32)
@ -205,4 +206,13 @@ get_property(NEO_SRCS_ENABLE_CORE GLOBAL PROPERTY NEO_SRCS_ENABLE_CORE)
target_sources(ocloc_lib PRIVATE ${NEO_SRCS_ENABLE_CORE})
if(UNIX)
set_property(GLOBAL APPEND PROPERTY NEO_CORE_SRCS_LINK ${CORE_SRCS_LINK_LINUX})
target_include_directories(${NEO_SHARED_RELEASE_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pin/linux)
if(NOT NEO_SKIP_UNIT_TESTS)
target_include_directories(${NEO_SHARED_MOCKABLE_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pin/linux)
endif()
else()
target_include_directories(${NEO_SHARED_RELEASE_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pin/windows)
if(NOT NEO_SKIP_UNIT_TESTS)
target_include_directories(${NEO_SHARED_MOCKABLE_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pin/windows)
endif()
endif()

View File

@ -0,0 +1,14 @@
#
# Copyright (C) 2020-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(NEO_GTPIN
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/pin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pin.h
)
set_property(GLOBAL PROPERTY NEO_GTPIN ${NEO_GTPIN})
add_subdirectories()

View File

@ -0,0 +1,13 @@
#
# Copyright (C) 2020-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(UNIX)
list(APPEND NEO_GTPIN
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_pin.h
)
include_directories(${NEO_SHARED_DIRECTORY}/pin/)
endif()

View File

@ -1,18 +1,15 @@
/*
* Copyright (C) 2020 Intel Corporation
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/pin/pin.h"
#include "level_zero/tools/source/pin/pin.h"
namespace L0 {
namespace NEO {
typedef uint32_t (*OpenGTPin_fn)(void *gtPinInit);
const std::string PinContext::gtPinLibraryFilename = "libgtpin.so";
} // namespace L0
} // namespace NEO

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2022 Intel Corporation
* Copyright (C) 2020-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -9,39 +9,35 @@
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "level_zero/source/inc/ze_intel_gpu.h"
#include "os_pin.h"
const std::string gtPinOpenFunctionName = "OpenGTPin";
namespace L0 {
namespace NEO {
PinContext::OsLibraryLoadPtr PinContext::osLibraryLoadFunction(NEO::OsLibrary::load);
ze_result_t PinContext::init() {
bool PinContext::init(const std::string &gtPinOpenFunctionName) {
NEO::OsLibrary *hGtPinLibrary = nullptr;
hGtPinLibrary = PinContext::osLibraryLoadFunction(gtPinLibraryFilename.c_str());
hGtPinLibrary = PinContext::osLibraryLoadFunction(PinContext::gtPinLibraryFilename.c_str());
if (hGtPinLibrary == nullptr) {
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Unable to find gtpin library %s\n", gtPinLibraryFilename.c_str());
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Unable to find gtpin library %s\n", PinContext::gtPinLibraryFilename.c_str());
return false;
}
OpenGTPin_fn openGTPin = reinterpret_cast<OpenGTPin_fn>(hGtPinLibrary->getProcAddress(gtPinOpenFunctionName.c_str()));
if (openGTPin == nullptr) {
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Unable to find gtpin library open function symbol %s\n", gtPinOpenFunctionName.c_str());
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
return false;
}
uint32_t openResult = openGTPin(nullptr);
if (openResult != 0) {
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "gtpin library open %s failed with status %u\n", gtPinOpenFunctionName.c_str(), openResult);
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
return false;
}
return ZE_RESULT_SUCCESS;
return true;
}
} // namespace L0
} // namespace NEO

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2022 Intel Corporation
* Copyright (C) 2020-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@ -8,14 +8,11 @@
#pragma once
#include "shared/source/os_interface/os_library.h"
#include <level_zero/ze_api.h>
#include <level_zero/zet_api.h>
namespace L0 {
namespace NEO {
class PinContext {
public:
static ze_result_t init();
static bool init(const std::string &gtPinOpenFunctionName);
using OsLibraryLoadPtr = std::add_pointer<NEO::OsLibrary *(const std::string &)>::type;
static OsLibraryLoadPtr osLibraryLoadFunction;
@ -23,4 +20,4 @@ class PinContext {
static const std::string gtPinLibraryFilename;
};
} // namespace L0
} // namespace NEO

View File

@ -0,0 +1,13 @@
#
# Copyright (C) 2020-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(WIN32)
list(APPEND NEO_GTPIN
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_pin.h
)
include_directories(${NEO_SHARED_DIRECTORY}/pin/)
endif()

View File

@ -1,18 +1,15 @@
/*
* Copyright (C) 2020 Intel Corporation
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/pin/pin.h"
#include "level_zero/tools/source/pin/pin.h"
namespace L0 {
namespace NEO {
typedef uint32_t(__fastcall *OpenGTPin_fn)(void *gtPinInit);
const std::string PinContext::gtPinLibraryFilename = "gtpin.dll";
} // namespace L0
} // namespace NEO

View File

@ -1,10 +1,10 @@
#
# Copyright (C) 2022 Intel Corporation
# Copyright (C) 2022-2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
target_sources(${TARGET_NAME} PRIVATE
target_sources(neo_shared_tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_pin.cpp
)

View File

@ -1,43 +1,45 @@
/*
* Copyright (C) 2022 Intel Corporation
* Copyright (C) 2022-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/pin/pin.h"
#include "shared/test/common/mocks/mock_os_library.h"
#include "level_zero/tools/source/pin/pin.h"
#include "gtest/gtest.h"
namespace ult {
namespace ULT {
TEST(PinInitializationTest, GivenValidLibraryPinContextInitSucceeds) {
uint32_t (*openPinHandler)(void *) = [](void *arg) -> uint32_t { return 0; };
auto newPtr = new MockOsLibrary(reinterpret_cast<void *>(openPinHandler), false);
MockOsLibrary::loadLibraryNewObject = newPtr;
L0::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
EXPECT_EQ(L0::PinContext::init(), ZE_RESULT_SUCCESS);
L0::PinContext::osLibraryLoadFunction = NEO::OsLibrary::load;
NEO::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
std::string mockGTPinFunctionName{"aaa"};
EXPECT_TRUE(NEO::PinContext::init(mockGTPinFunctionName));
MockOsLibrary::loadLibraryNewObject = nullptr;
delete newPtr;
}
TEST(PinInitializationTest, GivenBadLibraryNamePinContextInitFAILS) {
MockOsLibrary::loadLibraryNewObject = nullptr;
L0::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
EXPECT_EQ(L0::PinContext::init(), ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
L0::PinContext::osLibraryLoadFunction = NEO::OsLibrary::load;
NEO::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
std::string mockGTPinFunctionName{"aaa"};
EXPECT_FALSE(NEO::PinContext::init(mockGTPinFunctionName));
MockOsLibrary::loadLibraryNewObject = nullptr;
}
TEST(PinInitializationTest, GivenBadProcAddressPinContextInitFAILS) {
auto newPtr = new MockOsLibrary(nullptr, false);
MockOsLibrary::loadLibraryNewObject = newPtr;
L0::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
EXPECT_EQ(L0::PinContext::init(), ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
L0::PinContext::osLibraryLoadFunction = NEO::OsLibrary::load;
NEO::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
std::string mockGTPinFunctionName{"aaa"};
EXPECT_FALSE(NEO::PinContext::init(mockGTPinFunctionName));
MockOsLibrary::loadLibraryNewObject = nullptr;
delete newPtr;
}
@ -46,11 +48,12 @@ TEST(PinInitializationTest, GivenBadPinHandlerPinContextInitFAILS) {
uint32_t (*openPinHandler)(void *) = [](void *arg) -> uint32_t { return 1; };
auto newPtr = new MockOsLibrary(reinterpret_cast<void *>(openPinHandler), false);
MockOsLibrary::loadLibraryNewObject = newPtr;
L0::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
EXPECT_EQ(L0::PinContext::init(), ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
L0::PinContext::osLibraryLoadFunction = NEO::OsLibrary::load;
NEO::PinContext::osLibraryLoadFunction = MockOsLibrary::load;
std::string mockGTPinFunctionName{"aaa"};
EXPECT_FALSE(NEO::PinContext::init(mockGTPinFunctionName));
MockOsLibrary::loadLibraryNewObject = nullptr;
delete newPtr;
}
} // namespace ult
} // namespace ULT