66//
77// ===----------------------------------------------------------------------===//
88
9+ #include < detail/config.hpp>
910#include < detail/handler_impl.hpp>
1011#include < detail/kernel_bundle_impl.hpp>
12+ #include < detail/program_manager/program_manager.hpp>
1113#include < detail/queue_impl.hpp>
1214#include < detail/scheduler/commands.hpp>
1315#include < sycl/sycl.hpp>
1416
1517#include < helpers/MockDeviceImage.hpp>
1618#include < helpers/MockKernelInfo.hpp>
19+ #include < helpers/ScopedEnvVar.hpp>
1720#include < helpers/UrMock.hpp>
1821
1922#include < gtest/gtest.h>
@@ -98,28 +101,17 @@ static sycl::unittest::MockDeviceImageArray<1> EAMImgArray{&EAMImg};
98101static sycl::unittest::MockDeviceImageArray<1 > EAM2ImgArray{&EAM2Img};
99102static sycl::unittest::MockDeviceImageArray<1 > EAM3ImgArray{&EAM3Img};
100103
101- // ur_program_handle_t address is used as a key for ProgramManager::NativePrograms
102- // storage. redefinedProgramLinkCommon makes ur_program_handle_t address equal to 0x1.
103- // Make sure that size of Bin is different for device images used in these tests
104- // and greater than 1.
104+ // ur_program_handle_t address is used as a key for
105+ // ProgramManager::NativePrograms storage. redefinedProgramLinkCommon makes
106+ // ur_program_handle_t address equal to 0x1. Make sure that size of Bin is
107+ // different for device images used in these tests and greater than 1.
105108inline ur_result_t redefinedProgramCreateEAM (void *pParams) {
106109 auto params = *static_cast <ur_program_create_with_il_params_t *>(pParams);
107110 static size_t UrProgramAddr = 2 ;
108111 **params.pphProgram = reinterpret_cast <ur_program_handle_t >(UrProgramAddr++);
109112 return UR_RESULT_SUCCESS;
110113}
111114
112- mock::dummy_handle_t_ FixedHandle;
113- inline ur_result_t setFixedProgramPtr (void *pParams) {
114- auto params = *static_cast <ur_program_create_with_il_params_t *>(pParams);
115- **params.pphProgram = reinterpret_cast <ur_program_handle_t >(&FixedHandle);
116- return UR_RESULT_SUCCESS;
117- }
118- inline ur_result_t releaseFixedProgramPtr (void *pParams) {
119- // Do nothing
120- return UR_RESULT_SUCCESS;
121- }
122-
123115class MockHandler : public sycl ::handler {
124116
125117public:
@@ -218,6 +210,53 @@ TEST(EliminatedArgMask, KernelBundleWith2Kernels) {
218210 EXPECT_EQ (*EliminatedArgMask, ExpElimArgMask);
219211}
220212
213+ std::vector<std::unique_ptr<mock::dummy_handle_t_>> UsedProgramHandles;
214+ std::vector<std::unique_ptr<mock::dummy_handle_t_>> ProgramHandlesToReuse;
215+ inline ur_result_t setFixedProgramPtr (void *pParams) {
216+ auto params = *static_cast <ur_program_create_with_il_params_t *>(pParams);
217+ if (!ProgramHandlesToReuse.empty ()) {
218+ auto it = ProgramHandlesToReuse.begin () + 1 ;
219+ std::move (ProgramHandlesToReuse.begin (), it,
220+ std::back_inserter (UsedProgramHandles));
221+ ProgramHandlesToReuse.erase (ProgramHandlesToReuse.begin (), it);
222+ } else
223+ UsedProgramHandles.push_back (
224+ std::make_unique<mock::dummy_handle_t_>(sizeof (unsigned )));
225+ **params.pphProgram =
226+ reinterpret_cast <ur_program_handle_t >(UsedProgramHandles.back ().get ());
227+ return UR_RESULT_SUCCESS;
228+ }
229+ inline ur_result_t releaseFixedProgramPtr (void *pParams) {
230+ auto params = *static_cast <ur_program_release_params_t *>(pParams);
231+ {
232+ auto it = std::find_if (
233+ UsedProgramHandles.begin (), UsedProgramHandles.end (),
234+ [¶ms](const std::unique_ptr<mock::dummy_handle_t_> &item) {
235+ return reinterpret_cast <ur_program_handle_t >(item.get ()) ==
236+ *params.phProgram ;
237+ });
238+ if (it == UsedProgramHandles.end ())
239+ return UR_RESULT_SUCCESS;
240+ std::move (it, it + 1 , std::back_inserter (ProgramHandlesToReuse));
241+ UsedProgramHandles.erase (it, it + 1 );
242+ }
243+ return UR_RESULT_SUCCESS;
244+ }
245+
246+ inline ur_result_t customProgramRetain (void *pParams) {
247+ // do nothing
248+ return UR_RESULT_SUCCESS;
249+ }
250+
251+ class ProgramManagerTest {
252+ public:
253+ static std::unordered_multimap<ur_program_handle_t ,
254+ const sycl::detail::RTDeviceBinaryImage *> &
255+ getNativePrograms () {
256+ return sycl::detail::ProgramManager::getInstance ().NativePrograms ;
257+ }
258+ };
259+
221260// It's possible for the same handle to be reused for multiple distinct programs
222261// This can happen if a program is released (freeing underlying memory) and then
223262// a new program happens to get given that same memory for its handle.
@@ -227,6 +266,7 @@ TEST(EliminatedArgMask, KernelBundleWith2Kernels) {
227266TEST (EliminatedArgMask, ReuseOfHandleValues) {
228267 sycl::detail::ProgramManager &PM =
229268 sycl::detail::ProgramManager::getInstance ();
269+ auto &NativePrograms = ProgramManagerTest::getNativePrograms ();
230270
231271 ur_program_handle_t ProgBefore = nullptr ;
232272 ur_program_handle_t ProgAfter = nullptr ;
@@ -238,6 +278,8 @@ TEST(EliminatedArgMask, ReuseOfHandleValues) {
238278 &setFixedProgramPtr);
239279 mock::getCallbacks ().set_replace_callback (" urProgramRelease" ,
240280 &releaseFixedProgramPtr);
281+ mock::getCallbacks ().set_replace_callback (" urProgramRetain" ,
282+ &customProgramRetain);
241283
242284 const sycl::device Dev = Plt.get_devices ()[0 ];
243285 sycl::queue Queue{Dev};
@@ -247,8 +289,12 @@ TEST(EliminatedArgMask, ReuseOfHandleValues) {
247289 auto Mask = PM.getEliminatedKernelArgMask (ProgBefore, Name);
248290 EXPECT_NE (Mask, nullptr );
249291 EXPECT_EQ (Mask->at (0 ), 1 );
292+ EXPECT_EQ (UsedProgramHandles.size (), 1u );
293+ EXPECT_EQ (NativePrograms.count (ProgBefore), 1u );
250294 }
251295
296+ EXPECT_EQ (UsedProgramHandles.size (), 0u );
297+
252298 {
253299 auto Name = sycl::detail::KernelInfo<EAMTestKernel3>::getName ();
254300 sycl::unittest::UrMock<> Mock;
@@ -257,6 +303,8 @@ TEST(EliminatedArgMask, ReuseOfHandleValues) {
257303 &setFixedProgramPtr);
258304 mock::getCallbacks ().set_replace_callback (" urProgramRelease" ,
259305 &releaseFixedProgramPtr);
306+ mock::getCallbacks ().set_replace_callback (" urProgramRetain" ,
307+ &customProgramRetain);
260308
261309 const sycl::device Dev = Plt.get_devices ()[0 ];
262310 sycl::queue Queue{Dev};
@@ -266,6 +314,8 @@ TEST(EliminatedArgMask, ReuseOfHandleValues) {
266314 auto Mask = PM.getEliminatedKernelArgMask (ProgAfter, Name);
267315 EXPECT_NE (Mask, nullptr );
268316 EXPECT_EQ (Mask->at (0 ), 0 );
317+ EXPECT_EQ (UsedProgramHandles.size (), 1u );
318+ EXPECT_EQ (NativePrograms.count (ProgBefore), 1u );
269319 }
270320
271321 // Verify that the test is behaving correctly and that the pointer is being
0 commit comments