Skip to content

Commit e313d55

Browse files
[SYCL][PI][L0] Fix race condition on read of Event's ZeCommandList. (#2653)
1 parent 3b8fcf2 commit e313d55

File tree

1 file changed

+35
-38
lines changed

1 file changed

+35
-38
lines changed

sycl/plugins/level_zero/pi_level_zero.cpp

Lines changed: 35 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3337,6 +3337,38 @@ pi_result piEventGetProfilingInfo(pi_event Event, pi_profiling_info ParamName,
33373337
return PI_SUCCESS;
33383338
}
33393339

3340+
// Recycle the command list associated with this event.
3341+
static void recycleEventCommandList(pi_event Event) {
3342+
// The implementation of this is slightly tricky. The same event
3343+
// can be referred to by multiple threads, so it is possible to
3344+
// have a race condition between the read of ZeCommandList and
3345+
// it being reset to nullptr in another thread.
3346+
// But, since the ZeCommandList is uniquely associated with the queue
3347+
// for the event, we use the locking that we already have to do on the
3348+
// queue to also serve as the thread safety mechanism for the
3349+
// Event's ZeCommandList.
3350+
auto Queue = Event->Queue;
3351+
3352+
// Lock automatically releases when this goes out of scope.
3353+
std::lock_guard<std::mutex> lock(Queue->PiQueueMutex);
3354+
3355+
auto EventCommandList = Event->ZeCommandList;
3356+
3357+
if (EventCommandList) {
3358+
// Event has been signaled: If the fence for the associated command list
3359+
// is signalled, then reset the fence and command list and add them to the
3360+
// available list for reuse in PI calls.
3361+
if (Queue->RefCount > 0) {
3362+
ze_result_t ZeResult = ZE_CALL_NOCHECK(
3363+
zeFenceQueryStatus(Queue->ZeCommandListFenceMap[EventCommandList]));
3364+
if (ZeResult == ZE_RESULT_SUCCESS) {
3365+
Queue->resetCommandListFenceEntry(EventCommandList, true);
3366+
Event->ZeCommandList = nullptr;
3367+
}
3368+
}
3369+
}
3370+
}
3371+
33403372
pi_result piEventsWait(pi_uint32 NumEvents, const pi_event *EventList) {
33413373

33423374
if (NumEvents && !EventList) {
@@ -3363,26 +3395,7 @@ pi_result piEventsWait(pi_uint32 NumEvents, const pi_event *EventList) {
33633395

33643396
// NOTE: we are destroying associated command lists here to free
33653397
// resources sooner in case RT is not calling piEventRelease soon enough.
3366-
if (EventList[I]->ZeCommandList) {
3367-
// Event has been signaled: If the fence for the associated command list
3368-
// is signalled, then reset the fence and command list and add them to the
3369-
// available list for reuse in PI calls.
3370-
auto Queue = EventList[I]->Queue;
3371-
3372-
// Lock automatically releases when this goes out of scope.
3373-
std::lock_guard<std::mutex> lock(Queue->PiQueueMutex);
3374-
3375-
if (Queue->RefCount > 0) {
3376-
ze_result_t ZeResult = ZE_CALL_NOCHECK(zeFenceQueryStatus(
3377-
EventList[I]
3378-
->Queue->ZeCommandListFenceMap[EventList[I]->ZeCommandList]));
3379-
if (ZeResult == ZE_RESULT_SUCCESS) {
3380-
EventList[I]->Queue->resetCommandListFenceEntry(
3381-
EventList[I]->ZeCommandList, true);
3382-
EventList[I]->ZeCommandList = nullptr;
3383-
}
3384-
}
3385-
}
3398+
recycleEventCommandList(EventList[I]);
33863399
}
33873400
return PI_SUCCESS;
33883401
}
@@ -3409,24 +3422,8 @@ pi_result piEventRetain(pi_event Event) {
34093422
pi_result piEventRelease(pi_event Event) {
34103423
assert(Event);
34113424
if (--(Event->RefCount) == 0) {
3412-
if (Event->ZeCommandList) {
3413-
// If the fence associated with this command list has signalled, then
3414-
// Reset the Command List Used in this event and put it back on the
3415-
// available list.
3416-
auto Queue = Event->Queue;
3417-
3418-
// Lock automatically releases when this goes out of scope.
3419-
std::lock_guard<std::mutex> lock(Queue->PiQueueMutex);
3420-
3421-
if (Queue->RefCount > 0) {
3422-
ze_result_t ZeResult = ZE_CALL_NOCHECK(zeFenceQueryStatus(
3423-
Event->Queue->ZeCommandListFenceMap[Event->ZeCommandList]));
3424-
if (ZeResult == ZE_RESULT_SUCCESS) {
3425-
Event->Queue->resetCommandListFenceEntry(Event->ZeCommandList, true);
3426-
}
3427-
}
3428-
Event->ZeCommandList = nullptr;
3429-
}
3425+
recycleEventCommandList(Event);
3426+
34303427
if (Event->CommandType == PI_COMMAND_TYPE_MEM_BUFFER_UNMAP &&
34313428
Event->CommandData) {
34323429
// Free the memory allocated in the piEnqueueMemBufferMap.

0 commit comments

Comments
 (0)