Skip to content

Commit bd80f34

Browse files
authored
[SYCL] Protect access to the pi_event objects in the L0 plugin (#6230)
1 parent 62afb59 commit bd80f34

File tree

1 file changed

+74
-50
lines changed

1 file changed

+74
-50
lines changed

sycl/plugins/level_zero/pi_level_zero.cpp

100755100644
Lines changed: 74 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ _pi_context::getFreeSlotInExistingOrNewPool(ze_event_pool_handle_t &Pool,
491491
}
492492

493493
pi_result _pi_context::decrementUnreleasedEventsInPool(pi_event Event) {
494+
std::shared_lock EventLock(Event->Mutex, std::defer_lock);
495+
std::scoped_lock LockAll(ZeEventPoolCacheMutex, EventLock);
494496
if (!Event->ZeEventPool) {
495497
// This must be an interop event created on a users's pool.
496498
// Do nothing.
@@ -501,7 +503,6 @@ pi_result _pi_context::decrementUnreleasedEventsInPool(pi_event Event) {
501503
getZeEventPoolCache(Event->isHostVisible(), Event->isProfilingEnabled());
502504

503505
// Put the empty pool to the cache of the pools.
504-
std::lock_guard<std::mutex> Lock(ZeEventPoolCacheMutex);
505506
if (NumEventsUnreleasedInEventPool[Event->ZeEventPool] == 0)
506507
die("Invalid event release: event pool doesn't have unreleased events");
507508
if (--NumEventsUnreleasedInEventPool[Event->ZeEventPool] == 0) {
@@ -1148,7 +1149,10 @@ pi_result resetCommandLists(pi_queue Queue) {
11481149
for (auto Event : EventListToCleanup) {
11491150
// We don't need to synchronize the events since the fence
11501151
// synchronized above already does that.
1151-
Event->Completed = true;
1152+
{
1153+
std::scoped_lock EventLock(Event->Mutex);
1154+
Event->Completed = true;
1155+
}
11521156
PI_CALL(CleanupCompletedEvent(Event));
11531157
// This event was removed from the command list, so decrement ref count
11541158
// (it was incremented when they were added to the command list).
@@ -1445,6 +1449,7 @@ pi_result _pi_queue::executeCommandList(pi_command_list_ptr_t CommandList,
14451449
// Update each command's event in the command-list to "see" this
14461450
// proxy event as a host-visible counterpart.
14471451
for (auto &Event : CommandList->second.EventList) {
1452+
std::scoped_lock EventLock(Event->Mutex);
14481453
if (!Event->HostVisibleEvent) {
14491454
Event->HostVisibleEvent = HostVisibleEvent;
14501455
PI_CALL(piEventRetain(HostVisibleEvent));
@@ -1693,17 +1698,20 @@ pi_result _pi_ze_event_list_t::createAndRetainPiZeEventList(
16931698
if (EventListLength > 0) {
16941699
for (pi_uint32 I = 0; I < EventListLength; I++) {
16951700
PI_ASSERT(EventList[I] != nullptr, PI_INVALID_VALUE);
1696-
if (EventList[I]->Completed)
1697-
continue;
1698-
1699-
// Poll of the host-visible events.
1700-
auto HostVisibleEvent = EventList[I]->HostVisibleEvent;
1701-
if (FilterEventWaitList && HostVisibleEvent) {
1702-
auto Res =
1703-
ZE_CALL_NOCHECK(zeEventQueryStatus, (HostVisibleEvent->ZeEvent));
1704-
if (Res == ZE_RESULT_SUCCESS) {
1705-
// Event has already completed, don't put it into the list
1701+
{
1702+
std::shared_lock Lock(EventList[I]->Mutex);
1703+
if (EventList[I]->Completed)
17061704
continue;
1705+
1706+
// Poll of the host-visible events.
1707+
auto HostVisibleEvent = EventList[I]->HostVisibleEvent;
1708+
if (FilterEventWaitList && HostVisibleEvent) {
1709+
auto Res = ZE_CALL_NOCHECK(zeEventQueryStatus,
1710+
(HostVisibleEvent->ZeEvent));
1711+
if (Res == ZE_RESULT_SUCCESS) {
1712+
// Event has already completed, don't put it into the list
1713+
continue;
1714+
}
17071715
}
17081716
}
17091717

@@ -1758,6 +1766,7 @@ pi_result _pi_ze_event_list_t::createAndRetainPiZeEventList(
17581766
}
17591767
}
17601768

1769+
std::shared_lock Lock(EventList[I]->Mutex);
17611770
this->ZeEventList[TmpListLength] = EventList[I]->ZeEvent;
17621771
this->PiEventList[TmpListLength] = EventList[I];
17631772
TmpListLength += 1;
@@ -1780,6 +1789,7 @@ pi_result _pi_ze_event_list_t::createAndRetainPiZeEventList(
17801789
OpenCommandList->second.isCopy(CurQueue)))
17811790
return Res;
17821791
}
1792+
std::shared_lock Lock(CurQueue->LastCommandEvent->Mutex);
17831793
this->ZeEventList[TmpListLength] = CurQueue->LastCommandEvent->ZeEvent;
17841794
this->PiEventList[TmpListLength] = CurQueue->LastCommandEvent;
17851795
TmpListLength += 1;
@@ -3370,7 +3380,10 @@ pi_result piQueueRelease(pi_queue Queue) {
33703380
for (auto Event : EventListToCleanup) {
33713381
// We don't need to synchronize the events since the queue
33723382
// synchronized above already does that.
3373-
Event->Completed = true;
3383+
{
3384+
std::scoped_lock EventLock(Event->Mutex);
3385+
Event->Completed = true;
3386+
}
33743387
PI_CALL(CleanupCompletedEvent(Event));
33753388
// This event was removed from the command list, so decrement ref count
33763389
// (it was incremented when they were added to the command list).
@@ -5187,6 +5200,9 @@ pi_result piextKernelGetNativeHandle(pi_kernel Kernel,
51875200
//
51885201
pi_result
51895202
_pi_event::getOrCreateHostVisibleEvent(ze_event_handle_t &ZeHostVisibleEvent) {
5203+
PI_ASSERT(Queue, PI_INVALID_EVENT);
5204+
5205+
std::scoped_lock Lock(Queue->Mutex, this->Mutex);
51905206

51915207
if (!HostVisibleEvent) {
51925208
if (EventsScope != OnDemandHostVisibleProxy)
@@ -5197,32 +5213,28 @@ _pi_event::getOrCreateHostVisibleEvent(ze_event_handle_t &ZeHostVisibleEvent) {
51975213
// proxy is created.
51985214
//
51995215
// Get a new command list to be used on this call
5200-
{
5201-
std::scoped_lock Lock(Queue->Mutex);
52025216

5203-
// We want to batch these commands to avoid extra submissions (costly)
5204-
bool OkToBatch = true;
5217+
// We want to batch these commands to avoid extra submissions (costly)
5218+
bool OkToBatch = true;
52055219

5206-
pi_command_list_ptr_t CommandList{};
5207-
if (auto Res = Queue->Context->getAvailableCommandList(
5208-
Queue, CommandList, false /* UseCopyEngine */, OkToBatch))
5209-
return Res;
5220+
pi_command_list_ptr_t CommandList{};
5221+
if (auto Res = Queue->Context->getAvailableCommandList(
5222+
Queue, CommandList, false /* UseCopyEngine */, OkToBatch))
5223+
return Res;
52105224

5211-
// Create a "proxy" host-visible event.
5212-
auto Res = createEventAndAssociateQueue(
5213-
Queue, &HostVisibleEvent, PI_COMMAND_TYPE_USER, CommandList, true);
5214-
// HostVisibleEvent->CleanedUp = true;
5215-
if (Res != PI_SUCCESS)
5216-
return Res;
5225+
// Create a "proxy" host-visible event.
5226+
auto Res = createEventAndAssociateQueue(
5227+
Queue, &HostVisibleEvent, PI_COMMAND_TYPE_USER, CommandList, true);
5228+
// HostVisibleEvent->CleanedUp = true;
5229+
if (Res != PI_SUCCESS)
5230+
return Res;
52175231

5218-
ZE_CALL(zeCommandListAppendWaitOnEvents,
5219-
(CommandList->first, 1, &ZeEvent));
5220-
ZE_CALL(zeCommandListAppendSignalEvent,
5221-
(CommandList->first, HostVisibleEvent->ZeEvent));
5232+
ZE_CALL(zeCommandListAppendWaitOnEvents, (CommandList->first, 1, &ZeEvent));
5233+
ZE_CALL(zeCommandListAppendSignalEvent,
5234+
(CommandList->first, HostVisibleEvent->ZeEvent));
52225235

5223-
if (auto Res = Queue->executeCommandList(CommandList, false, OkToBatch))
5224-
return Res;
5225-
}
5236+
if (auto Res = Queue->executeCommandList(CommandList, false, OkToBatch))
5237+
return Res;
52265238
}
52275239

52285240
ZeHostVisibleEvent = HostVisibleEvent->ZeEvent;
@@ -5297,12 +5309,18 @@ pi_result piEventGetInfo(pi_event Event, pi_event_info ParamName,
52975309

52985310
ReturnHelper ReturnValue(ParamValueSize, ParamValue, ParamValueSizeRet);
52995311
switch (ParamName) {
5300-
case PI_EVENT_INFO_COMMAND_QUEUE:
5312+
case PI_EVENT_INFO_COMMAND_QUEUE: {
5313+
std::shared_lock EventLock(Event->Mutex);
53015314
return ReturnValue(pi_queue{Event->Queue});
5302-
case PI_EVENT_INFO_CONTEXT:
5315+
}
5316+
case PI_EVENT_INFO_CONTEXT: {
5317+
std::shared_lock EventLock(Event->Mutex);
53035318
return ReturnValue(pi_context{Event->Context});
5304-
case PI_EVENT_INFO_COMMAND_TYPE:
5319+
}
5320+
case PI_EVENT_INFO_COMMAND_TYPE: {
5321+
std::shared_lock EventLock(Event->Mutex);
53055322
return ReturnValue(pi_cast<pi_uint64>(Event->CommandType));
5323+
}
53065324
case PI_EVENT_INFO_COMMAND_EXECUTION_STATUS: {
53075325
// Check to see if the event's Queue has an open command list due to
53085326
// batching. If so, go ahead and close and submit it, because it is
@@ -5329,6 +5347,7 @@ pi_result piEventGetInfo(pi_event Event, pi_event_info ParamName,
53295347
// Make sure that we query a host-visible event only.
53305348
// If one wasn't yet created then don't create it here as well, and
53315349
// just conservatively return that event is not yet completed.
5350+
std::shared_lock EventLock(Event->Mutex);
53325351
auto HostVisibleEvent = Event->HostVisibleEvent;
53335352
if (Event->Completed) {
53345353
Result = CL_COMPLETE;
@@ -5359,6 +5378,7 @@ pi_result piEventGetProfilingInfo(pi_event Event, pi_profiling_info ParamName,
53595378

53605379
PI_ASSERT(Event, PI_INVALID_EVENT);
53615380

5381+
std::shared_lock EventLock(Event->Mutex);
53625382
if (Event->Queue &&
53635383
(Event->Queue->Properties & PI_QUEUE_PROFILING_ENABLE) == 0) {
53645384
return PI_PROFILING_INFO_NOT_AVAILABLE;
@@ -5549,18 +5569,20 @@ pi_result piEventsWait(pi_uint32 NumEvents, const pi_event *EventList) {
55495569
}
55505570
std::unordered_set<pi_queue> Queues;
55515571
for (uint32_t I = 0; I < NumEvents; I++) {
5552-
if (!EventList[I]->Completed) {
5553-
auto HostVisibleEvent = EventList[I]->HostVisibleEvent;
5554-
if (!HostVisibleEvent)
5555-
die("The host-visible proxy event missing");
5572+
{
5573+
std::shared_lock EventLock(EventList[I]->Mutex);
5574+
if (!EventList[I]->Completed) {
5575+
auto HostVisibleEvent = EventList[I]->HostVisibleEvent;
5576+
if (!HostVisibleEvent)
5577+
die("The host-visible proxy event missing");
55565578

5557-
ze_event_handle_t ZeEvent = HostVisibleEvent->ZeEvent;
5558-
zePrint("ZeEvent = %#lx\n", pi_cast<std::uintptr_t>(ZeEvent));
5559-
ZE_CALL(zeHostSynchronize, (ZeEvent));
5579+
ze_event_handle_t ZeEvent = HostVisibleEvent->ZeEvent;
5580+
zePrint("ZeEvent = %#lx\n", pi_cast<std::uintptr_t>(ZeEvent));
5581+
ZE_CALL(zeHostSynchronize, (ZeEvent));
5582+
}
5583+
if (auto Q = EventList[I]->Queue)
5584+
Queues.insert(Q);
55605585
}
5561-
if (auto Q = EventList[I]->Queue)
5562-
Queues.insert(Q);
5563-
55645586
// NOTE: we are cleaning up after the event here to free resources
55655587
// sooner in case run-time is not calling piEventRelease soon enough.
55665588
CleanupCompletedEvent(EventList[I]);
@@ -5644,9 +5666,11 @@ pi_result piextEventGetNativeHandle(pi_event Event,
56445666
PI_ASSERT(Event, PI_INVALID_EVENT);
56455667
PI_ASSERT(NativeHandle, PI_INVALID_VALUE);
56465668

5647-
auto *ZeEvent = pi_cast<ze_event_handle_t *>(NativeHandle);
5648-
*ZeEvent = Event->ZeEvent;
5649-
5669+
{
5670+
std::shared_lock Lock(Event->Mutex);
5671+
auto *ZeEvent = pi_cast<ze_event_handle_t *>(NativeHandle);
5672+
*ZeEvent = Event->ZeEvent;
5673+
}
56505674
// Event can potentially be in an open command-list, make sure that
56515675
// it is submitted for execution to avoid potential deadlock if
56525676
// interop app is going to wait for it.

0 commit comments

Comments
 (0)