|
| 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