Skip to content

Commit 5737ad9

Browse files
authored
[SYCL] Avoid datarace when waiting on the same event in multiple threads (#1803)
One thread could acquire shared access in `waitForEvent` after another thread executed `cleanupFinishedCommands` (which has exclusive access). This resulted in "Event has no associated command?" assertion failure in `GraphProcessor::waitForEvent`. Signed-off-by: Dmitri Mokhov <[email protected]>
1 parent 089fc67 commit 5737ad9

File tree

4 files changed

+38
-1
lines changed

4 files changed

+38
-1
lines changed

sycl/source/detail/event_impl.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,15 @@ class event_impl {
133133

134134
/// Returns command that is associated with the event.
135135
///
136+
/// Scheduler mutex must be locked in read mode when this is called.
137+
///
136138
/// @return a generic pointer to Command object instance.
137139
void *getCommand() { return MCommand; }
138140

139141
/// Associates this event with the command.
140142
///
143+
/// Scheduler mutex must be locked in write mode when this is called.
144+
///
141145
/// @param Command is a generic pointer to Command object instance.
142146
void setCommand(void *Command) { MCommand = Command; }
143147

sycl/source/detail/scheduler/graph_processor.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ Scheduler::GraphProcessor::getWaitList(EventImplPtr Event) {
3838

3939
void Scheduler::GraphProcessor::waitForEvent(EventImplPtr Event) {
4040
Command *Cmd = getCommand(Event);
41-
assert(Cmd && "Event has no associated command?");
41+
// Command can be nullptr if user creates cl::sycl::event explicitly or the
42+
// event has been waited on by another thread
43+
if (!Cmd)
44+
return;
45+
4246
EnqueueResultT Res;
4347
bool Enqueued = enqueueCommand(Cmd, Res, BLOCKING);
4448
if (!Enqueued && EnqueueResultT::SyclEnqueueFailed == Res.MResult)

sycl/unittests/scheduler/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ add_sycl_unittest(SchedulerTests OBJECT
55
LeafLimit.cpp
66
MemObjCommandCleanup.cpp
77
CommandsWaitForEvents.cpp
8+
WaitAfterCleanup.cpp
89
utils.cpp
910
)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//==------------ WaitAfterCleanup.cpp ---- Scheduler 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+
12+
using namespace cl::sycl;
13+
14+
TEST_F(SchedulerTest, WaitAfterCleanup) {
15+
auto Cmd = new MockCommand(detail::getSyclObjImpl(MQueue));
16+
auto Event = Cmd->getEvent();
17+
ASSERT_NE(Event, nullptr) << "Command must have an event\n";
18+
19+
detail::Scheduler::getInstance().waitForEvent(Event);
20+
ASSERT_EQ(Event->getCommand(), Cmd)
21+
<< "Command should not have been cleaned up yet\n";
22+
23+
detail::Scheduler::getInstance().cleanupFinishedCommands(Event);
24+
ASSERT_EQ(Event->getCommand(), nullptr)
25+
<< "Command should have been cleaned up\n";
26+
27+
detail::Scheduler::getInstance().waitForEvent(Event);
28+
}

0 commit comments

Comments
 (0)