Skip to content

Commit d0e3ed2

Browse files
committed
[SYCL] do not add nullptr Events in getPiEvents function
1 parent 65436fb commit d0e3ed2

File tree

4 files changed

+102
-4
lines changed

4 files changed

+102
-4
lines changed

sycl/plugins/level_zero/pi_level_zero.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,7 @@ pi_result _pi_ze_event_list_t::createAndRetainPiZeEventList(
12401240

12411241
if (EventListLength > 0) {
12421242
for (pi_uint32 I = 0; I < EventListLength; I++) {
1243+
PI_ASSERT(EventList[I] != nullptr, PI_INVALID_VALUE);
12431244
auto ZeEvent = EventList[I]->ZeEvent;
12441245

12451246
if (FilterEventWaitList) {

sycl/source/detail/scheduler/commands.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,11 @@ static std::string commandToName(Command::CommandType Type) {
160160
static std::vector<RT::PiEvent>
161161
getPiEvents(const std::vector<EventImplPtr> &EventImpls) {
162162
std::vector<RT::PiEvent> RetPiEvents;
163-
for (auto &EventImpl : EventImpls)
164-
RetPiEvents.push_back(EventImpl->getHandleRef());
163+
for (auto &EventImpl : EventImpls) {
164+
if (EventImpl->getHandleRef() != nullptr)
165+
RetPiEvents.push_back(EventImpl->getHandleRef());
166+
}
167+
165168
return RetPiEvents;
166169
}
167170

@@ -2231,12 +2234,12 @@ cl_int ExecCGCommand::enqueueImp() {
22312234
case CG::CGTYPE::BarrierWaitlist: {
22322235
CGBarrier *Barrier = static_cast<CGBarrier *>(MCommandGroup.get());
22332236
std::vector<detail::EventImplPtr> Events = Barrier->MEventsWaitWithBarrier;
2234-
if (MQueue->get_device().is_host() || Events.empty()) {
2237+
std::vector<RT::PiEvent> PiEvents = getPiEvents(Events);
2238+
if (MQueue->get_device().is_host() || PiEvents.empty()) {
22352239
// NOP for host device.
22362240
// If Events is empty, then the barrier has no effect.
22372241
return PI_SUCCESS;
22382242
}
2239-
std::vector<RT::PiEvent> PiEvents = getPiEvents(Events);
22402243
const detail::plugin &Plugin = MQueue->getPlugin();
22412244
Plugin.call<PiApiKind::piEnqueueEventsWaitWithBarrier>(
22422245
MQueue->getHandleRef(), PiEvents.size(), &PiEvents[0], &Event);

sycl/unittests/scheduler/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
add_sycl_unittest(SchedulerTests OBJECT
22
BlockedCommands.cpp
3+
Commands.cpp
34
FailedCommands.cpp
45
FinishedCmdCleanup.cpp
56
LeafLimit.cpp

sycl/unittests/scheduler/Commands.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//==----------- Commands.cpp --- Commands unit tests -----------------------==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "SchedulerTest.hpp"
10+
#include "SchedulerTestUtils.hpp"
11+
#include <helpers/PiMock.hpp>
12+
13+
#include <iostream>
14+
15+
using namespace cl::sycl;
16+
17+
pi_result redefinePiEnqueueEventsWaitWithBarrier(pi_queue Queue,
18+
pi_uint32 NumEventsInWaitList,
19+
const pi_event *EventWaitList,
20+
pi_event *Event) {
21+
22+
for (pi_uint32 i = 0; i != NumEventsInWaitList; ++i)
23+
EXPECT_NE(EventWaitList[i], nullptr);
24+
25+
return PI_SUCCESS;
26+
}
27+
28+
// Hack that allows to return a context in redefinePiEventGetInfo
29+
RT::PiContext queue_global_context = nullptr;
30+
31+
pi_result redefinePiEventGetInfo(pi_event, pi_event_info, size_t,
32+
void *param_value, size_t *) {
33+
*reinterpret_cast<RT::PiContext *>(param_value) = queue_global_context;
34+
return PI_SUCCESS;
35+
}
36+
37+
pi_result redefinePiEventRetain(pi_event) { return PI_SUCCESS; }
38+
39+
pi_result redefinePiEventRelease(pi_event) { return PI_SUCCESS; }
40+
41+
//
42+
// This test checks a handling of empty events in WaitWithBarrier command.
43+
// Original reproducer for l0 plugin led to segfault(nullptr dereference):
44+
//
45+
// #include <CL/sycl.hpp>
46+
// int main() {
47+
// sycl::queue q;
48+
// sycl::event e;
49+
// q.submit_barrier({e});
50+
// }
51+
//
52+
TEST_F(SchedulerTest, WaitEmptyEventWithBarrier) {
53+
// NB! This test requires at least one non-host environmet
54+
// For example, OpenCL.
55+
default_selector Selector{};
56+
if (Selector.select_device().is_host()) {
57+
std::cerr << "Not run due to host-only environment\n";
58+
return;
59+
}
60+
61+
platform Plt{Selector};
62+
unittest::PiMock Mock{Plt};
63+
64+
Mock.redefine<detail::PiApiKind::piEnqueueEventsWaitWithBarrier>(
65+
redefinePiEnqueueEventsWaitWithBarrier);
66+
67+
queue Queue{Plt.get_devices()[0]};
68+
cl::sycl::detail::QueueImplPtr QueueImpl = detail::getSyclObjImpl(Queue);
69+
70+
queue_global_context =
71+
detail::getSyclObjImpl(Queue.get_context())->getHandleRef();
72+
73+
Mock.redefine<detail::PiApiKind::piEventGetInfo>(redefinePiEventGetInfo);
74+
Mock.redefine<detail::PiApiKind::piEventRetain>(redefinePiEventRetain);
75+
Mock.redefine<detail::PiApiKind::piEventRelease>(redefinePiEventRelease);
76+
77+
auto EmptyEvent = std::make_shared<detail::event_impl>();
78+
auto Event = std::make_shared<detail::event_impl>(
79+
reinterpret_cast<RT::PiEvent>(0x01), Queue.get_context());
80+
81+
using EventList = std::vector<detail::EventImplPtr>;
82+
std::vector<EventList> InputEventWaitLists = {
83+
{EmptyEvent}, {Event, Event}, {EmptyEvent, Event}};
84+
85+
MockScheduler MS;
86+
87+
for (auto &Arg : InputEventWaitLists) {
88+
std::unique_ptr<detail::CG> CommandGroup(
89+
new detail::CGBarrier(std::move(Arg), {}, {}, {}, {}, {},
90+
detail::CG::CGTYPE::BarrierWaitlist, {}));
91+
MS.Scheduler::addCG(std::move(CommandGroup), QueueImpl);
92+
}
93+
}

0 commit comments

Comments
 (0)