Skip to content

Commit 2488da1

Browse files
againullal42and
andauthored
[SYCL] Filter out empty events for the barrier with waitlist (#12951)
Fix for #12177 Now even if the waitlist consists of only empty events we still invoke the scheduler to submit barrier command. Scheduler creates sycl event with associated Barrier Command but doesn't actually enqueue a barrier because waitlist is empty (consists of only empty events). As a result, the event returned by such barrier doesn't have PI handle but it supposed to have. If such event is then passed to some another command later as a dependency then it leads to nullptr dereference. So, filter out such events from waitlist to avoid going to sheduler in such scenarios. Test provided by Andrey Alekseenko <[email protected]> Co-authored-by: Andrey Alekseenko <[email protected]>
1 parent 22fab5a commit 2488da1

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

sycl/source/queue.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,11 @@ event queue::ext_oneapi_submit_barrier(const detail::code_location &CodeLoc) {
238238
/// group is being enqueued on.
239239
event queue::ext_oneapi_submit_barrier(const std::vector<event> &WaitList,
240240
const detail::code_location &CodeLoc) {
241-
if (is_in_order() && WaitList.empty()) {
241+
bool AllEventsEmpty = std::all_of(
242+
begin(WaitList), end(WaitList), [&](const event &Event) -> bool {
243+
return !detail::getSyclObjImpl(Event)->isContextInitialized();
244+
});
245+
if (is_in_order() && AllEventsEmpty) {
242246
// The last command recorded in the graph is not tracked by the queue but by
243247
// the graph itself. We must therefore search for the last node/event in the
244248
// graph.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %{build} %threads_lib -o %t.out
2+
// RUN: %{run} %t.out
3+
4+
// Check that ext_oneapi_submit_barrier works fine in the scenarios
5+
// when provided waitlist consists of only empty events.
6+
7+
#include <iostream>
8+
#include <mutex>
9+
#include <sycl/sycl.hpp>
10+
#include <thread>
11+
12+
static constexpr int niter = 1024;
13+
static constexpr int nthreads = 2;
14+
15+
std::array<std::mutex, nthreads> mutexes;
16+
std::array<std::optional<sycl::event>, nthreads> events;
17+
18+
void threadFunction(int tid) {
19+
sycl::device dev;
20+
std::cout << dev.get_info<sycl::info::device::name>() << std::endl;
21+
sycl::context ctx{dev};
22+
sycl::queue q1{ctx, dev, {sycl::property::queue::in_order()}};
23+
sycl::queue q2{ctx, dev, {sycl::property::queue::in_order()}};
24+
for (int i = 0; i < niter; i++) {
25+
sycl::event ev1 = q1.ext_oneapi_submit_barrier();
26+
q2.ext_oneapi_submit_barrier({ev1});
27+
sycl::event ev2 = q2.ext_oneapi_submit_barrier();
28+
q1.ext_oneapi_submit_barrier({ev2});
29+
}
30+
}
31+
32+
int main() {
33+
std::array<std::thread, nthreads> threads;
34+
35+
for (int i = 0; i < nthreads; i++) {
36+
threads[i] = std::thread{threadFunction, i};
37+
}
38+
39+
for (int i = 0; i < nthreads; i++) {
40+
threads[i].join();
41+
}
42+
std::cout << "All threads have finished." << std::endl;
43+
44+
return 0;
45+
}

0 commit comments

Comments
 (0)