1 /*
2 * Copyright (C) 2020-2021 Intel Corporation
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 */
7
8 #include "level_zero/tools/source/sysman/global_operations/global_operations_imp.h"
9 #include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h"
10
11 #include "mock_events.h"
12
13 extern bool sysmanUltsEnable;
14
15 using ::testing::Matcher;
16
17 namespace L0 {
18 namespace ult {
19
20 class SysmanEventsFixture : public SysmanDeviceFixture {
21 protected:
22 std::unique_ptr<Mock<EventsFsAccess>> pFsAccess;
23 FsAccess *pFsAccessOriginal = nullptr;
24 OsEvents *pOsEventsPrev = nullptr;
25 L0::EventsImp *pEventsImp;
26 GlobalOperations *pGlobalOperationsOriginal = nullptr;
27 std::unique_ptr<GlobalOperationsImp> pGlobalOperations;
28 std::unique_ptr<Mock<EventsSysfsAccess>> pSysfsAccess;
29 SysfsAccess *pSysfsAccessOriginal = nullptr;
30
SetUp()31 void SetUp() override {
32 if (!sysmanUltsEnable) {
33 GTEST_SKIP();
34 }
35 SysmanDeviceFixture::SetUp();
36 pFsAccessOriginal = pLinuxSysmanImp->pFsAccess;
37 pFsAccess = std::make_unique<NiceMock<Mock<EventsFsAccess>>>();
38 pLinuxSysmanImp->pFsAccess = pFsAccess.get();
39
40 pEventsImp = static_cast<L0::EventsImp *>(pSysmanDeviceImp->pEvents);
41 pOsEventsPrev = pEventsImp->pOsEvents;
42 pEventsImp->pOsEvents = nullptr;
43 pGlobalOperations = std::make_unique<GlobalOperationsImp>(pLinuxSysmanImp);
44 pGlobalOperationsOriginal = pSysmanDeviceImp->pGlobalOperations;
45 pSysmanDeviceImp->pGlobalOperations = pGlobalOperations.get();
46 pSysmanDeviceImp->pGlobalOperations->init();
47
48 pSysfsAccessOriginal = pLinuxSysmanImp->pSysfsAccess;
49 pSysfsAccess = std::make_unique<NiceMock<Mock<EventsSysfsAccess>>>();
50 pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
51 ON_CALL(*pSysfsAccess.get(), readSymLink(_, _))
52 .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<EventsSysfsAccess>::getValStringSymLinkSuccess));
53
54 pEventsImp->init();
55 }
56
TearDown()57 void TearDown() override {
58 if (!sysmanUltsEnable) {
59 GTEST_SKIP();
60 }
61 if (nullptr != pEventsImp->pOsEvents) {
62 delete pEventsImp->pOsEvents;
63 }
64 pEventsImp->pOsEvents = pOsEventsPrev;
65 pEventsImp = nullptr;
66 pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOriginal;
67 pLinuxSysmanImp->pFsAccess = pFsAccessOriginal;
68 pSysmanDeviceImp->pGlobalOperations = pGlobalOperationsOriginal;
69 SysmanDeviceFixture::TearDown();
70 }
71 };
72
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout)73 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout) {
74 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED));
75 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
76 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsOne));
77 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
78 phDevices[0] = device->toHandle();
79 uint32_t numDeviceEvents = 0;
80 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
81 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
82 EXPECT_EQ(1u, numDeviceEvents);
83 EXPECT_EQ(ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED, pDeviceEvents[0]);
84 delete[] phDevices;
85 delete[] pDeviceEvents;
86 }
87
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived)88 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived) {
89 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED));
90 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
91 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsZero));
92 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
93 phDevices[0] = device->toHandle();
94 uint32_t numDeviceEvents = 0;
95 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
96 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
97 EXPECT_EQ(0u, numDeviceEvents);
98
99 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
100 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValFileNotFound));
101 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
102 EXPECT_EQ(0u, numDeviceEvents);
103
104 delete[] phDevices;
105 delete[] pDeviceEvents;
106 }
107
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForCurrentlyUnsupportedEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived)108 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForCurrentlyUnsupportedEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived) {
109 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_TEMP_THRESHOLD2));
110 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
111 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsOne));
112 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
113 phDevices[0] = device->toHandle();
114 uint32_t numDeviceEvents = 0;
115 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
116 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
117 EXPECT_EQ(0u, numDeviceEvents);
118 delete[] phDevices;
119 delete[] pDeviceEvents;
120 }
121
TEST_F(SysmanEventsFixture,GivenReadSymLinkCallFailsWhenGettingPCIBDFThenEmptyPciIdPathTagReceived)122 TEST_F(SysmanEventsFixture, GivenReadSymLinkCallFailsWhenGettingPCIBDFThenEmptyPciIdPathTagReceived) {
123 ON_CALL(*pSysfsAccess.get(), readSymLink(_, _))
124 .WillByDefault(::testing::Invoke(pSysfsAccess.get(), &Mock<EventsSysfsAccess>::getValStringSymLinkFailure));
125 PublicLinuxEventsImp linuxEventImp(pOsSysman);
126 EXPECT_TRUE(linuxEventImp.pciIdPathTag.empty());
127 }
128
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForDeviceDetachEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout)129 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForDeviceDetachEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout) {
130 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_DETACH));
131 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
132 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsOne));
133 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
134 phDevices[0] = device->toHandle();
135 uint32_t numDeviceEvents = 0;
136 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
137 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
138 EXPECT_EQ(1u, numDeviceEvents);
139 EXPECT_EQ(ZES_EVENT_TYPE_FLAG_DEVICE_DETACH, pDeviceEvents[0]);
140 delete[] phDevices;
141 delete[] pDeviceEvents;
142 }
143
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForDeviceDetachEventsThenAfterReceivingEventRegisterEventAgainToReceiveEvent)144 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForDeviceDetachEventsThenAfterReceivingEventRegisterEventAgainToReceiveEvent) {
145 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_DETACH));
146 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
147 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsOne));
148 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
149 phDevices[0] = device->toHandle();
150 uint32_t numDeviceEvents = 0;
151 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
152 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
153 EXPECT_EQ(1u, numDeviceEvents);
154 EXPECT_EQ(ZES_EVENT_TYPE_FLAG_DEVICE_DETACH, pDeviceEvents[0]);
155 numDeviceEvents = 0;
156 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
157 EXPECT_EQ(0u, numDeviceEvents);
158 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_DETACH));
159 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
160 EXPECT_EQ(1u, numDeviceEvents);
161 EXPECT_EQ(ZES_EVENT_TYPE_FLAG_DEVICE_DETACH, pDeviceEvents[0]);
162 delete[] phDevices;
163 delete[] pDeviceEvents;
164 }
165
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForDeviceDetachEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived)166 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForDeviceDetachEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived) {
167 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_DETACH));
168 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
169 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsZero));
170 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
171 phDevices[0] = device->toHandle();
172 uint32_t numDeviceEvents = 0;
173 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
174 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
175 EXPECT_EQ(0u, numDeviceEvents);
176
177 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
178 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValFileNotFound));
179 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
180 EXPECT_EQ(0u, numDeviceEvents);
181
182 delete[] phDevices;
183 delete[] pDeviceEvents;
184 }
185
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForDeviceAttachEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout)186 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForDeviceAttachEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout) {
187 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH));
188 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
189 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsOne));
190 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
191 phDevices[0] = device->toHandle();
192 uint32_t numDeviceEvents = 0;
193 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
194 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
195 EXPECT_EQ(1u, numDeviceEvents);
196 EXPECT_EQ(ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH, pDeviceEvents[0]);
197 delete[] phDevices;
198 delete[] pDeviceEvents;
199 }
200
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForDeviceAttachEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived)201 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForDeviceAttachEventsThenEventListenAPIWaitForTimeoutIfEventNotReceived) {
202 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH));
203 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
204 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsZero));
205 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
206 phDevices[0] = device->toHandle();
207 uint32_t numDeviceEvents = 0;
208 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
209 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
210 EXPECT_EQ(0u, numDeviceEvents);
211
212 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
213 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValFileNotFound));
214 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
215 EXPECT_EQ(0u, numDeviceEvents);
216
217 delete[] phDevices;
218 delete[] pDeviceEvents;
219 }
220
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForMemHealthEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout)221 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForMemHealthEventsThenEventListenAPIReturnsAfterReceivingEventWithinTimeout) {
222 PublicLinuxEventsImp *pLinuxEventsImp = new PublicLinuxEventsImp(pOsSysman);
223 pLinuxEventsImp->eventRegister(ZES_EVENT_TYPE_FLAG_MEM_HEALTH);
224 pLinuxEventsImp->memHealthAtEventRegister = ZES_MEM_HEALTH_OK;
225 zes_event_type_flags_t events = 0;
226 uint32_t timeout = 1u;
227 EXPECT_TRUE(pLinuxEventsImp->eventListen(events, timeout));
228 EXPECT_EQ(events, ZES_EVENT_TYPE_FLAG_MEM_HEALTH);
229 delete pLinuxEventsImp;
230 }
231
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForMemHealthEventsAndMemHealthDidntOccurThenEventListenAPIReturnsWithinTimeout)232 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForMemHealthEventsAndMemHealthDidntOccurThenEventListenAPIReturnsWithinTimeout) {
233 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_MEM_HEALTH));
234 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
235 phDevices[0] = device->toHandle();
236 uint32_t numDeviceEvents = 0;
237 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
238 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListen(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
239 EXPECT_EQ(0u, numDeviceEvents);
240 delete[] phDevices;
241 delete[] pDeviceEvents;
242 }
243
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForAListOfEventsThenEventRegisterAPIReturnsProperErrorCodeInCaseEventsAreInvalid)244 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForAListOfEventsThenEventRegisterAPIReturnsProperErrorCodeInCaseEventsAreInvalid) {
245 zes_event_type_flags_t events1 = 0x7ffe;
246 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), events1));
247 zes_event_type_flags_t events2 = 0x1e240;
248 EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ENUMERATION, zesDeviceEventRegister(device->toHandle(), events2));
249 }
250
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenExAPIReturnsAfterReceivingEventWithinTimeout)251 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenExAPIReturnsAfterReceivingEventWithinTimeout) {
252 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED));
253 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
254 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsOne));
255 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
256 phDevices[0] = device->toHandle();
257 uint32_t numDeviceEvents = 0;
258 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
259 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListenEx(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
260 EXPECT_EQ(1u, numDeviceEvents);
261 EXPECT_EQ(ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED, pDeviceEvents[0]);
262 delete[] phDevices;
263 delete[] pDeviceEvents;
264 }
265
TEST_F(SysmanEventsFixture,GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenExAPIWaitForTimeoutIfEventNotReceived)266 TEST_F(SysmanEventsFixture, GivenValidDeviceHandleWhenListeningForResetRequiredEventsThenEventListenExAPIWaitForTimeoutIfEventNotReceived) {
267 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceEventRegister(device->toHandle(), ZES_EVENT_TYPE_FLAG_DEVICE_RESET_REQUIRED));
268 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
269 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValReturnValAsZero));
270 zes_device_handle_t *phDevices = new zes_device_handle_t[1];
271 phDevices[0] = device->toHandle();
272 uint32_t numDeviceEvents = 0;
273 zes_event_type_flags_t *pDeviceEvents = new zes_event_type_flags_t[1];
274 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListenEx(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
275 EXPECT_EQ(0u, numDeviceEvents);
276
277 ON_CALL(*pFsAccess.get(), read(_, Matcher<uint32_t &>(_)))
278 .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock<EventsFsAccess>::getValFileNotFound));
279 EXPECT_EQ(ZE_RESULT_SUCCESS, zesDriverEventListenEx(driverHandle->toHandle(), 1u, 1u, phDevices, &numDeviceEvents, pDeviceEvents));
280 EXPECT_EQ(0u, numDeviceEvents);
281
282 delete[] phDevices;
283 delete[] pDeviceEvents;
284 }
285
286 } // namespace ult
287 } // namespace L0
288