diff --git a/sycl/cmake/modules/AddSYCLUnitTest.cmake b/sycl/cmake/modules/AddSYCLUnitTest.cmake index 41a78866512c4..ec8afcf345f4e 100644 --- a/sycl/cmake/modules/AddSYCLUnitTest.cmake +++ b/sycl/cmake/modules/AddSYCLUnitTest.cmake @@ -7,6 +7,8 @@ macro(add_sycl_unittest test_dirname link_variant) set(LLVM_REQUIRES_EH ON) set(LLVM_REQUIRES_RTTI ON) + get_target_property(SYCL_BINARY_DIR sycl-toolchain BINARY_DIR) + string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower) if (MSVC AND build_type_lower MATCHES "debug") set(sycl_obj_target "sycld_object") @@ -47,7 +49,7 @@ macro(add_sycl_unittest test_dirname link_variant) SYCL_CONFIG_FILE_NAME=null.cfg SYCL_DEVICELIB_NO_FALLBACK=1 SYCL_CACHE_DIR="${CMAKE_BINARY_DIR}/sycl_cache" - "PATH=${CMAKE_BINARY_DIR}/bin;$ENV{PATH}" + "PATH=${SYCL_BINARY_DIR}/unittests/lib;${CMAKE_BINARY_DIR}/bin;$ENV{PATH}" ${CMAKE_CURRENT_BINARY_DIR}/${test_dirname} DEPENDS ${test_dirname} @@ -59,7 +61,7 @@ macro(add_sycl_unittest test_dirname link_variant) SYCL_CONFIG_FILE_NAME=null.cfg SYCL_DEVICELIB_NO_FALLBACK=1 SYCL_CACHE_DIR="${CMAKE_BINARY_DIR}/sycl_cache" - "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}" + "LD_LIBRARY_PATH=${SYCL_BINARY_DIR}/unittests/lib:${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}" ${CMAKE_CURRENT_BINARY_DIR}/${test_dirname} DEPENDS ${test_dirname} @@ -73,10 +75,11 @@ macro(add_sycl_unittest test_dirname link_variant) LLVMTestingSupport OpenCL-Headers unified-runtime::mock + mockOpenCL ${SYCL_LINK_LIBS} ) - add_dependencies(${test_dirname} ur_adapter_mock) + add_dependencies(${test_dirname} ur_adapter_mock mockOpenCL) if(SYCL_ENABLE_EXTENSION_JIT) target_link_libraries(${test_dirname} PRIVATE sycl-jit) diff --git a/sycl/include/sycl/detail/common.hpp b/sycl/include/sycl/detail/common.hpp index 1243ae7536b8e..393b45e918ddd 100644 --- a/sycl/include/sycl/detail/common.hpp +++ b/sycl/include/sycl/detail/common.hpp @@ -8,6 +8,11 @@ #pragma once +#if _MSC_VER +#include +#else +#include +#endif #include // for __SYCL_ALWAYS_INLINE #include // for __SYCL_EXPORT @@ -379,6 +384,43 @@ static constexpr std::array RepeatValue(const T &Arg) { // classes. struct AllowCTADTag; +// Look up a function name that was dynamically linked +// This is used by the runtime where it needs to manipulate native handles (e.g. +// retaining OpenCL handles). On Windows, the symbol name is looked up in +// `WinName`. In Linux, it uses `LinName`. +// +// The library must already have been loaded (perhaps by UR), otherwise this +// function throws. +template +fn *dynLookupFunction([[maybe_unused]] const char *WinName, + [[maybe_unused]] const char *LinName, + const char *FunName) { +#ifdef _MSC_VER + auto handle = GetModuleHandleA(WinName); + if (!handle) { + throw sycl::exception(make_error_code(errc::runtime), + "OpenCL library is not loaded"); + } + auto *retVal = GetProcAddress(handle, FunName); +#else + auto handle = dlopen(LinName, RTLD_LAZY | RTLD_NOLOAD); + if (!handle) { + throw sycl::exception(make_error_code(errc::runtime), + "OpenCL library is not loaded"); + } + auto *retVal = dlsym(handle, FunName); + dlclose(handle); +#endif + if (!handle) { + throw sycl::exception(make_error_code(errc::runtime), + "OpenCL method could not be found"); + } + return reinterpret_cast(retVal); +} +#define _OCL_GET_FUNCTION(FN) \ + (::sycl::_V1::detail::dynLookupFunction("OpenCL", \ + "libOpenCL.so", #FN)) + } // namespace detail } // namespace _V1 } // namespace sycl diff --git a/sycl/source/backend.cpp b/sycl/source/backend.cpp index 2c876a570e3c6..725c5e0439e13 100644 --- a/sycl/source/backend.cpp +++ b/sycl/source/backend.cpp @@ -181,7 +181,7 @@ __SYCL_EXPORT event make_event(ur_native_handle_t NativeHandle, std::make_shared(UrEvent, Context)); if (Backend == backend::opencl) - Adapter->call(UrEvent); + _OCL_GET_FUNCTION(clRetainEvent)(ur::cast(NativeHandle)); return Event; } @@ -205,7 +205,7 @@ make_kernel_bundle(ur_native_handle_t NativeHandle, "urProgramCreateWithNativeHandle resulted in a null program handle."); if (ContextImpl->getBackend() == backend::opencl) - Adapter->call(UrProgram); + _OCL_GET_FUNCTION(clRetainProgram)(ur::cast(NativeHandle)); std::vector ProgramDevices; uint32_t NumDevices = 0; @@ -352,7 +352,7 @@ kernel make_kernel(const context &TargetContext, &UrKernel); if (Backend == backend::opencl) - Adapter->call(UrKernel); + _OCL_GET_FUNCTION(clRetainKernel)(ur::cast(NativeHandle)); // Construct the SYCL queue from UR queue. return detail::createSyclObjFromImpl( diff --git a/sycl/source/detail/buffer_impl.cpp b/sycl/source/detail/buffer_impl.cpp index 777091f6be572..4ad2c9eadb982 100644 --- a/sycl/source/detail/buffer_impl.cpp +++ b/sycl/source/detail/buffer_impl.cpp @@ -87,7 +87,7 @@ buffer_impl::getNativeVector(backend BackendName) const { auto Adapter = Platform->getAdapter(); if (Platform->getBackend() == backend::opencl) { - Adapter->call(NativeMem); + _OCL_GET_FUNCTION(clRetainMemObject)(ur::cast(NativeMem)); } ur_native_handle_t Handle = 0; diff --git a/sycl/source/detail/context_impl.cpp b/sycl/source/detail/context_impl.cpp index e527d0a0c46a8..58e7b3ed4cd50 100644 --- a/sycl/source/detail/context_impl.cpp +++ b/sycl/source/detail/context_impl.cpp @@ -303,10 +303,11 @@ context_impl::findMatchingDeviceImpl(ur_device_handle_t &DeviceUR) const { ur_native_handle_t context_impl::getNative() const { const auto &Adapter = getAdapter(); - if (getBackend() == backend::opencl) - Adapter->call(getHandleRef()); ur_native_handle_t Handle; Adapter->call(getHandleRef(), &Handle); + if (getBackend() == backend::opencl) { + _OCL_GET_FUNCTION(clRetainContext)(ur::cast(Handle)); + } return Handle; } diff --git a/sycl/source/detail/device_image_impl.hpp b/sycl/source/detail/device_image_impl.hpp index ac58b7b80f467..8bb3a24b6d537 100644 --- a/sycl/source/detail/device_image_impl.hpp +++ b/sycl/source/detail/device_image_impl.hpp @@ -300,11 +300,13 @@ class device_image_impl { const auto &ContextImplPtr = detail::getSyclObjImpl(MContext); const AdapterPtr &Adapter = ContextImplPtr->getAdapter(); - if (ContextImplPtr->getBackend() == backend::opencl) - Adapter->call(MProgram); ur_native_handle_t NativeProgram = 0; Adapter->call(MProgram, &NativeProgram); + if (ContextImplPtr->getBackend() == backend::opencl) { + auto *RetainFun = _OCL_GET_FUNCTION(clRetainProgram); + RetainFun(ur::cast(NativeProgram)); + } return NativeProgram; } diff --git a/sycl/source/detail/device_impl.cpp b/sycl/source/detail/device_impl.cpp index 5cb7fa1e29585..266dbc85a7f0f 100644 --- a/sycl/source/detail/device_impl.cpp +++ b/sycl/source/detail/device_impl.cpp @@ -98,7 +98,7 @@ bool device_impl::is_affinity_supported( cl_device_id device_impl::get() const { // TODO catch an exception and put it to list of asynchronous exceptions - getAdapter()->call(MDevice); + _OCL_GET_FUNCTION(clRetainDevice)(ur::cast(getNative())); return ur::cast(getNative()); } @@ -345,10 +345,11 @@ std::vector device_impl::create_sub_devices() const { ur_native_handle_t device_impl::getNative() const { auto Adapter = getAdapter(); - if (getBackend() == backend::opencl) - Adapter->call(getHandleRef()); ur_native_handle_t Handle; Adapter->call(getHandleRef(), &Handle); + if (getBackend() == backend::opencl) { + _OCL_GET_FUNCTION(clRetainDevice)(ur::cast(Handle)); + } return Handle; } diff --git a/sycl/source/detail/event_impl.cpp b/sycl/source/detail/event_impl.cpp index 520b4de1ae888..367cc6caf6426 100644 --- a/sycl/source/detail/event_impl.cpp +++ b/sycl/source/detail/event_impl.cpp @@ -500,10 +500,10 @@ ur_native_handle_t event_impl::getNative() { this->setHandle(UREvent); Handle = UREvent; } - if (MContext->getBackend() == backend::opencl) - Adapter->call(Handle); ur_native_handle_t OutHandle; Adapter->call(Handle, &OutHandle); + if (MContext->getBackend() == backend::opencl) + _OCL_GET_FUNCTION(clRetainEvent)(ur::cast(OutHandle)); return OutHandle; } diff --git a/sycl/source/detail/kernel_impl.hpp b/sycl/source/detail/kernel_impl.hpp index 1b07d866dcc4c..77292d754955f 100644 --- a/sycl/source/detail/kernel_impl.hpp +++ b/sycl/source/detail/kernel_impl.hpp @@ -75,10 +75,10 @@ class kernel_impl { /// /// \return a valid cl_kernel instance cl_kernel get() const { - getAdapter()->call(MKernel); ur_native_handle_t nativeHandle = 0; getAdapter()->call(MKernel, &nativeHandle); + _OCL_GET_FUNCTION(clRetainKernel)(ur::cast(nativeHandle)); return ur::cast(nativeHandle); } @@ -179,12 +179,13 @@ class kernel_impl { ur_native_handle_t getNative() const { const AdapterPtr &Adapter = MContext->getAdapter(); - if (MContext->getBackend() == backend::opencl) - Adapter->call(MKernel); - ur_native_handle_t NativeKernel = 0; Adapter->call(MKernel, &NativeKernel); + if (MContext->getBackend() == backend::opencl) { + _OCL_GET_FUNCTION(clRetainKernel)(ur::cast(NativeKernel)); + } + return NativeKernel; } diff --git a/sycl/source/detail/queue_impl.cpp b/sycl/source/detail/queue_impl.cpp index d8ca3fb8c1544..dc319bac4c517 100644 --- a/sycl/source/detail/queue_impl.cpp +++ b/sycl/source/detail/queue_impl.cpp @@ -731,8 +731,6 @@ void queue_impl::destructorNotification() { ur_native_handle_t queue_impl::getNative(int32_t &NativeHandleDesc) const { const AdapterPtr &Adapter = getAdapter(); - if (getContextImplPtr()->getBackend() == backend::opencl) - Adapter->call(MQueues[0]); ur_native_handle_t Handle{}; ur_queue_native_desc_t UrNativeDesc{UR_STRUCTURE_TYPE_QUEUE_NATIVE_DESC, nullptr, nullptr}; @@ -740,6 +738,10 @@ ur_native_handle_t queue_impl::getNative(int32_t &NativeHandleDesc) const { Adapter->call(MQueues[0], &UrNativeDesc, &Handle); + if (getContextImplPtr()->getBackend() == backend::opencl) { + auto *RetainFn = _OCL_GET_FUNCTION(clRetainCommandQueue); + RetainFn(ur::cast(Handle)); + } return Handle; } diff --git a/sycl/source/detail/queue_impl.hpp b/sycl/source/detail/queue_impl.hpp index 710e48be35909..c2ea3f7df60ae 100644 --- a/sycl/source/detail/queue_impl.hpp +++ b/sycl/source/detail/queue_impl.hpp @@ -273,10 +273,11 @@ class queue_impl { /// \return an OpenCL interoperability queue handle. cl_command_queue get() { - getAdapter()->call(MQueues[0]); ur_native_handle_t nativeHandle = 0; getAdapter()->call(MQueues[0], nullptr, &nativeHandle); + auto *retainFn = _OCL_GET_FUNCTION(clRetainCommandQueue); + retainFn(ur::cast(nativeHandle)); return ur::cast(nativeHandle); } diff --git a/sycl/source/detail/sycl_mem_obj_t.cpp b/sycl/source/detail/sycl_mem_obj_t.cpp index 25e092232ae7f..333b87452d427 100644 --- a/sycl/source/detail/sycl_mem_obj_t.cpp +++ b/sycl/source/detail/sycl_mem_obj_t.cpp @@ -57,8 +57,9 @@ SYCLMemObjT::SYCLMemObjT(ur_native_handle_t MemObject, make_error_code(errc::invalid), "Input context must be the same as the context of cl_mem"); - if (MInteropContext->getBackend() == backend::opencl) - Adapter->call(MInteropMemObject); + if (MInteropContext->getBackend() == backend::opencl) { + _OCL_GET_FUNCTION(clRetainMemObject)(ur::cast(MemObject)); + } } ur_mem_type_t getImageType(int Dimensions) { @@ -112,8 +113,9 @@ SYCLMemObjT::SYCLMemObjT(ur_native_handle_t MemObject, make_error_code(errc::invalid), "Input context must be the same as the context of cl_mem"); - if (MInteropContext->getBackend() == backend::opencl) - Adapter->call(MInteropMemObject); + if (MInteropContext->getBackend() == backend::opencl) { + _OCL_GET_FUNCTION(clRetainMemObject)(ur::cast(MemObject)); + } } void SYCLMemObjT::releaseMem(ContextImplPtr Context, void *MemAllocation) { diff --git a/sycl/source/device.cpp b/sycl/source/device.cpp index 13590e980841c..aaed77f19c6e6 100644 --- a/sycl/source/device.cpp +++ b/sycl/source/device.cpp @@ -43,7 +43,7 @@ device::device(cl_device_id DeviceId) { auto Platform = detail::platform_impl::getPlatformFromUrDevice(Device, Adapter); impl = Platform->getOrMakeDeviceImpl(Device, Platform); - Adapter->call(impl->getHandleRef()); + _OCL_GET_FUNCTION(clRetainDevice)(DeviceId); } device::device(const device_selector &deviceSelector) { diff --git a/sycl/source/event.cpp b/sycl/source/event.cpp index df68777ca6df4..b301453bfbe59 100644 --- a/sycl/source/event.cpp +++ b/sycl/source/event.cpp @@ -29,9 +29,7 @@ event::event(cl_event ClEvent, const context &SyclContext) detail::ur::cast(ClEvent), SyclContext)) { // This is a special interop constructor for OpenCL, so the event must be // retained. - // TODO(pi2ur): Don't just cast from cl_event above - impl->getAdapter()->call( - detail::ur::cast(ClEvent)); + _OCL_GET_FUNCTION(clRetainEvent)(ClEvent); } bool event::operator==(const event &rhs) const { return rhs.impl == impl; } diff --git a/sycl/source/kernel.cpp b/sycl/source/kernel.cpp index b0055f74ef4bc..1742f80cdfd1f 100644 --- a/sycl/source/kernel.cpp +++ b/sycl/source/kernel.cpp @@ -30,7 +30,7 @@ kernel::kernel(cl_kernel ClKernel, const context &SyclContext) { // This is a special interop constructor for OpenCL, so the kernel must be // retained. if (get_backend() == backend::opencl) { - impl->getAdapter()->call(hKernel); + _OCL_GET_FUNCTION(clRetainKernel)(ClKernel); } } diff --git a/sycl/test/Unit/lit.cfg.py b/sycl/test/Unit/lit.cfg.py index 3bf9aefeeaabc..f68681a5c0dbf 100644 --- a/sycl/test/Unit/lit.cfg.py +++ b/sycl/test/Unit/lit.cfg.py @@ -70,8 +70,11 @@ def find_shlibpath_var(): for shlibpath_var in find_shlibpath_var(): # in stand-alone builds, shlibdir is clang's build tree # while llvm_libs_dir is installed LLVM (and possibly older clang) + # For unit tests, we have a "mock" OpenCL which needs to have + # priority and so is at the start of the shlibpath list shlibpath = os.path.pathsep.join( ( + os.path.join(config.test_exec_root, "lib"), config.shlibdir, config.llvm_libs_dir, config.environment.get(shlibpath_var, ""), diff --git a/sycl/unittests/CMakeLists.txt b/sycl/unittests/CMakeLists.txt index 8831426784de2..ecff3982baf6a 100644 --- a/sycl/unittests/CMakeLists.txt +++ b/sycl/unittests/CMakeLists.txt @@ -23,6 +23,8 @@ string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower) include(AddSYCLUnitTest) +add_subdirectory(mock_opencl) + add_custom_target(check-sycl-unittests) add_subdirectory(ur) diff --git a/sycl/unittests/Extensions/CompositeDevice.cpp b/sycl/unittests/Extensions/CompositeDevice.cpp index 8c875ebd9beda..1951287134caa 100644 --- a/sycl/unittests/Extensions/CompositeDevice.cpp +++ b/sycl/unittests/Extensions/CompositeDevice.cpp @@ -1,4 +1,5 @@ #include "sycl/platform.hpp" +#include #include #include @@ -143,8 +144,7 @@ TEST(CompositeDeviceTest, PlatformExtOneAPIGetCompositeDevices) { // We don't expect to see COMPOSITE_DEVICE_1 here, because one of its // components (COMPONENT_DEVICE_D) is not available. ASSERT_EQ(Composites.size(), 1u); - ASSERT_EQ(sycl::bit_cast( - sycl::get_native(Composites.front())), + ASSERT_EQ(sycl::detail::getSyclObjImpl(Composites.front())->getHandleRef(), COMPOSITE_DEVICE_0); } @@ -162,8 +162,7 @@ TEST(CompositeDeviceTest, SYCLExtOneAPIExperimentalGetCompositeDevices) { // We don't expect to see COMPOSITE_DEVICE_1 here, because one of its // components (COMPONENT_DEVICE_D) is not available. ASSERT_EQ(Composites.size(), 1u); - ASSERT_EQ(sycl::bit_cast( - sycl::get_native(Composites.front())), + ASSERT_EQ(sycl::detail::getSyclObjImpl(Composites.front())->getHandleRef(), COMPOSITE_DEVICE_0); } diff --git a/sycl/unittests/SYCL2020/GetNativeOpenCL.cpp b/sycl/unittests/SYCL2020/GetNativeOpenCL.cpp index ba2ae917808d3..3f4ab5fa6b4a5 100644 --- a/sycl/unittests/SYCL2020/GetNativeOpenCL.cpp +++ b/sycl/unittests/SYCL2020/GetNativeOpenCL.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -115,14 +116,26 @@ TEST(GetNative, GetNativeHandle) { cgh.single_task>([=]() { (void)Acc; }); }); + ASSERT_EQ(mockOpenCLNumContextRetains(), 0ul); + ASSERT_EQ(mockOpenCLNumQueueRetains(), 0ul); + ASSERT_EQ(mockOpenCLNumDeviceRetains(), 0ul); + ASSERT_EQ(mockOpenCLNumEventRetains(), 0ul); + ASSERT_EQ(TestCounter, 2 + DeviceRetainCounter - 1) + << "Not all the retain methods were called"; + get_native(Context); get_native(Queue); get_native(Device); get_native(Event); get_native(Buffer); - // Depending on global caches state, urDeviceRetain is called either once or - // twice, so there'll be 6 or 7 calls. - ASSERT_EQ(TestCounter, 6 + DeviceRetainCounter - 1) - << "Not all the retain methods were called"; + ASSERT_EQ(mockOpenCLNumContextRetains(), 1ul); + ASSERT_EQ(mockOpenCLNumQueueRetains(), 1ul); + ASSERT_EQ(mockOpenCLNumDeviceRetains(), 1ul); + ASSERT_EQ(mockOpenCLNumEventRetains(), 1ul); + + // get_native shouldn't retain the SYCL objects, but instead retains the + // underlying handles + ASSERT_EQ(TestCounter, 2 + DeviceRetainCounter - 1) + << "get_native retained SYCL objects"; } diff --git a/sycl/unittests/helpers/KernelInteropCommon.hpp b/sycl/unittests/helpers/KernelInteropCommon.hpp index 146df5cd301f1..3e13b70a2edd7 100644 --- a/sycl/unittests/helpers/KernelInteropCommon.hpp +++ b/sycl/unittests/helpers/KernelInteropCommon.hpp @@ -108,6 +108,13 @@ ur_result_t after_urKernelGetInfo(void *pParams) { return UR_RESULT_SUCCESS; } +size_t mockOpenCLNumKernelRetains(); +size_t mockOpenCLNumQueueRetains(); +size_t mockOpenCLNumMemObjectRetains(); +size_t mockOpenCLNumContextRetains(); +size_t mockOpenCLNumDeviceRetains(); +size_t mockOpenCLNumEventRetains(); + void redefineMockForKernelInterop(sycl::unittest::UrMock<> &Mock) { mock::getCallbacks().set_after_callback("urContextCreate", &after_urContextCreate); diff --git a/sycl/unittests/helpers/UrMock.hpp b/sycl/unittests/helpers/UrMock.hpp index 53c4db96dd84d..3e99f4f1422f2 100644 --- a/sycl/unittests/helpers/UrMock.hpp +++ b/sycl/unittests/helpers/UrMock.hpp @@ -502,6 +502,8 @@ inline ur_result_t mock_urCommandBufferAppendKernelLaunchExp(void *pParams) { } // namespace MockAdapter +void loadMockOpenCL(); + /// The UrMock<> class sets up UR for adapter mocking with the set of default /// overrides above, and ensures the appropriate parts of the sycl runtime and /// UR mocking code are reset/torn down in between tests. @@ -515,6 +517,12 @@ template class UrMock { /// This ensures UR is setup for adapter mocking and also injects our default /// entry-point overrides into the mock adapter. UrMock() { + if constexpr (Backend == backend::opencl) { + // Some tests use the interop handles, so we need to ensure the fake + // OpenCL library is loaded + loadMockOpenCL(); + } + #define ADD_DEFAULT_OVERRIDE(func_name, func_override) \ mock::getCallbacks().set_replace_callback(#func_name, \ &MockAdapter::func_override); diff --git a/sycl/unittests/mock_opencl/CMakeLists.txt b/sycl/unittests/mock_opencl/CMakeLists.txt new file mode 100644 index 0000000000000..a2d6fbcd5687d --- /dev/null +++ b/sycl/unittests/mock_opencl/CMakeLists.txt @@ -0,0 +1,8 @@ +get_target_property(SYCL_BINARY_DIR sycl-toolchain BINARY_DIR) + +add_library(mockOpenCL SHARED EXCLUDE_FROM_ALL mock_opencl.cpp) +set_target_properties(mockOpenCL PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${SYCL_BINARY_DIR}/unittests/lib + RUNTIME_OUTPUT_DIRECTORY ${SYCL_BINARY_DIR}/unittests/lib + ARCHIVE_OUTPUT_DIRECTORY ${SYCL_BINARY_DIR}/unittests/lib + OUTPUT_NAME OpenCL) diff --git a/sycl/unittests/mock_opencl/mock_opencl.cpp b/sycl/unittests/mock_opencl/mock_opencl.cpp new file mode 100644 index 0000000000000..c6b52cd6a1853 --- /dev/null +++ b/sycl/unittests/mock_opencl/mock_opencl.cpp @@ -0,0 +1,60 @@ +#include + +static size_t kernelRetains = 0; +static size_t queueRetains = 0; +static size_t memObjectRetains = 0; +static size_t contextRetains = 0; +static size_t deviceRetains = 0; +static size_t eventRetains = 0; + +extern "C" { +using handle = size_t *; +using cl_int = int; + +int clRetainKernel(handle) { + kernelRetains++; + return 0; +} +int clRetainCommandQueue(handle) { + queueRetains++; + return 0; +} +int clRetainMemObject(handle) { + memObjectRetains++; + return 0; +} +int clRetainContext(handle) { + contextRetains++; + return 0; +} +int clRetainDevice(handle) { + deviceRetains++; + return 0; +} +int clRetainEvent(handle) { + eventRetains++; + return 0; +} +} + +// This function is a no-op and can be used to force the fake OpenCL library to +// be linked by calling it +namespace sycl { +namespace _V1 { +namespace unittest { +void loadMockOpenCL() {} +} // namespace unittest +} // namespace _V1 +} // namespace sycl + +size_t mockOpenCLNumKernelRetains() { return kernelRetains; } + +size_t mockOpenCLNumQueueRetains() { return queueRetains; } + +size_t mockOpenCLNumMemObjectRetains() { return memObjectRetains; } + +size_t mockOpenCLNumContextRetains() { return contextRetains; } + +size_t mockOpenCLNumDeviceRetains() { return deviceRetains; } + +size_t mockOpenCLNumEventRetains() { return deviceRetains; } diff --git a/sycl/unittests/queue/InteropRetain.cpp b/sycl/unittests/queue/InteropRetain.cpp index c29d3b9e93c5a..c6df14ccc2c71 100644 --- a/sycl/unittests/queue/InteropRetain.cpp +++ b/sycl/unittests/queue/InteropRetain.cpp @@ -12,6 +12,7 @@ #include #include +#include #include namespace { @@ -33,15 +34,18 @@ TEST(PiInteropTest, CheckRetain) { mock::getCallbacks().set_before_callback("urQueueRetain", &redefinedQueueRetain); queue Q{Ctx, default_selector()}; - EXPECT_TRUE(QueueRetainCalled == 0); + EXPECT_EQ(QueueRetainCalled, 0); + EXPECT_EQ(mockOpenCLNumQueueRetains(), 0ul); cl_command_queue OCLQ = get_native(Q); - EXPECT_TRUE(QueueRetainCalled == 1); + EXPECT_EQ(QueueRetainCalled, 0); + EXPECT_EQ(mockOpenCLNumQueueRetains(), 1ul); // The make_queue should not call to urQueueRetain. The // urQueueCreateWithNativeHandle should do the "retain" if needed. queue Q1 = make_queue(OCLQ, Ctx); - EXPECT_TRUE(QueueRetainCalled == 1); + EXPECT_EQ(QueueRetainCalled, 0); + EXPECT_EQ(mockOpenCLNumQueueRetains(), 1ul); } } // namespace