Skip to content

Commit 4708475

Browse files
committed
[L0] fix a deadlock in queue sync and event status query
This fixes a possible deadlock in the following scenario: // Some event that is meant to be signaled by the host event = urEventCreateWithNativeHandle(...); Thread A: urEnqueueEventsWaitWithBarrier(q, waitlist = {event}, ...); // This will synchronously wait for the event to be signaled // from thread B. This hold q->Mutex exclusively. urQueueFinish(q); Thread B: // The current implementation of this query waits to aquire // event->queue->Mutex. This will never happen since thread A // is holding it. urEventGetInfo(event, ..., UR_EVENT_INFO_COMMAND_EXECUTION_STATUS); // This is meant to unblock thread A. zeEventHostSignal(event); The fix is simple. The only reason urEventGetInfo needs to acquire the queue lock is to opportunistically make progress on the event by submitting a related open command list if one exists. This is not required. And so the fix is to skip this logic if we fail to immediately acquire the lock (which indicates that something else is operating on the queue).
1 parent 4814e71 commit 4708475

File tree

1 file changed

+9
-5
lines changed

1 file changed

+9
-5
lines changed

source/adapters/level_zero/event.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -399,11 +399,15 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetInfo(
399399
auto UrQueue = Event->UrQueue;
400400
if (UrQueue) {
401401
// Lock automatically releases when this goes out of scope.
402-
std::scoped_lock<ur_shared_mutex> lock(UrQueue->Mutex);
403-
const auto &OpenCommandList = UrQueue->eventOpenCommandList(Event);
404-
if (OpenCommandList != UrQueue->CommandListMap.end()) {
405-
UR_CALL(UrQueue->executeOpenCommandList(
406-
OpenCommandList->second.isCopy(UrQueue)));
402+
std::unique_lock<ur_shared_mutex> Lock(UrQueue->Mutex, std::try_to_lock);
403+
// If we fail to acquire the lock, it's possible that the queue might
404+
// already be waiting for this event in synchronize().
405+
if (Lock.owns_lock()) {
406+
const auto &OpenCommandList = UrQueue->eventOpenCommandList(Event);
407+
if (OpenCommandList != UrQueue->CommandListMap.end()) {
408+
UR_CALL(UrQueue->executeOpenCommandList(
409+
OpenCommandList->second.isCopy(UrQueue)));
410+
}
407411
}
408412
}
409413

0 commit comments

Comments
 (0)